From 243a2744803935b1453c03b26b1c2aee0c259ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Schw=C3=B6rer?= Date: Sat, 8 Jun 2024 12:55:58 +0200 Subject: [PATCH] fixes and ui.dart --- flutter/lib/nav_layout.dart | 12 +- flutter/lib/pages/account/account.dart | 261 ++++++++---------- flutter/lib/pages/account/login.dart | 7 +- flutter/lib/pages/debug/debug_actions.dart | 41 +-- .../lib/pages/debug/debug_request_view.dart | 11 +- .../pages/message_list/message_list_item.dart | 18 +- .../lib/pages/message_view/message_view.dart | 47 +--- flutter/lib/utils/navi.dart | 1 + flutter/lib/utils/ui.dart | 109 ++++++++ 9 files changed, 277 insertions(+), 230 deletions(-) create mode 100644 flutter/lib/utils/navi.dart create mode 100644 flutter/lib/utils/ui.dart diff --git a/flutter/lib/nav_layout.dart b/flutter/lib/nav_layout.dart index 7399389..dbd9c93 100644 --- a/flutter/lib/nav_layout.dart +++ b/flutter/lib/nav_layout.dart @@ -64,13 +64,13 @@ class _SCNNavLayoutState extends State { showSearch: _selectedIndex == 0 || _selectedIndex == 1, showThemeSwitch: true, ), - body: LazyIndexedStack( + body: IndexedStack( children: [ - MessageListPage(), - ChannelRootPage(), - AccountRootPage(), - SettingsRootPage(), - SendRootPage(), + ExcludeFocus(excluding: _selectedIndex != 0, child: MessageListPage()), + ExcludeFocus(excluding: _selectedIndex != 1, child: ChannelRootPage()), + ExcludeFocus(excluding: _selectedIndex != 2, child: AccountRootPage()), + ExcludeFocus(excluding: _selectedIndex != 3, child: SettingsRootPage()), + ExcludeFocus(excluding: _selectedIndex != 4, child: SendRootPage()), ], index: _selectedIndex, ), diff --git a/flutter/lib/pages/account/account.dart b/flutter/lib/pages/account/account.dart index 3d903e0..72bd378 100644 --- a/flutter/lib/pages/account/account.dart +++ b/flutter/lib/pages/account/account.dart @@ -11,6 +11,7 @@ import 'package:simplecloudnotifier/state/application_log.dart'; import 'package:simplecloudnotifier/state/globals.dart'; import 'package:simplecloudnotifier/state/app_auth.dart'; import 'package:simplecloudnotifier/utils/toaster.dart'; +import 'package:simplecloudnotifier/utils/ui.dart'; import 'package:uuid/uuid.dart'; class AccountRootPage extends StatefulWidget { @@ -143,22 +144,23 @@ class _AccountRootPageState extends State { ), ), const SizedBox(height: 32), - FilledButton( - style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 24), padding: const EdgeInsets.fromLTRB(8, 12, 8, 12)), + UI.button( + text: 'Create new account', onPressed: () { if (loading) return; _createNewAccount(); }, - child: const Text('Create new account'), + big: true, ), const SizedBox(height: 16), - FilledButton.tonal( - style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 24), padding: const EdgeInsets.fromLTRB(8, 12, 8, 12)), + UI.button( + text: 'Use existing account', onPressed: () { if (loading) return; Navigator.push(context, MaterialPageRoute(builder: (context) => AccountLoginPage())); }, - child: const Text('Use existing account'), + tonal: true, + big: true, ), ], ), @@ -167,28 +169,22 @@ class _AccountRootPageState extends State { } Widget _buildShowAccount(BuildContext context, AppAuth acc, User user) { - //TODO better layout - return Column( - children: [ - SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Padding( - padding: const EdgeInsets.fromLTRB(8.0, 24.0, 8.0, 8.0), - child: Column( - children: [ - _buildHeader(context, user), - const SizedBox(height: 16), - Text(user.username ?? user.userID, overflow: TextOverflow.ellipsis, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), - const SizedBox(height: 16), - ..._buildCards(context, user), - ], - ), - ), + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.fromLTRB(8.0, 24.0, 8.0, 8.0), + child: Column( + children: [ + _buildHeader(context, user), + const SizedBox(height: 16), + Text(user.username ?? user.userID, overflow: TextOverflow.ellipsis, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + const SizedBox(height: 16), + ..._buildCards(context, user), + SizedBox(height: 16), + _buildFooter(context, user), + SizedBox(height: 40), + ], ), - const Expanded(child: SizedBox(height: 16)), - _buildFooter(context, user), - SizedBox(height: 40) - ], + ), ); } @@ -275,23 +271,15 @@ class _AccountRootPageState extends State { Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - IconButton( - icon: FaIcon(FontAwesomeIcons.pen), - iconSize: 18, - padding: EdgeInsets.all(4), - constraints: BoxConstraints(), - style: ButtonStyle(tapTargetSize: MaterialTapTargetSize.shrinkWrap), + UI.buttonIconOnly( onPressed: () {/*TODO*/}, + icon: FontAwesomeIcons.pen, ), const SizedBox(height: 4), if (!user.isPro) - IconButton( - icon: FaIcon(FontAwesomeIcons.cartCircleArrowUp), - iconSize: 18, - padding: EdgeInsets.all(4), - constraints: BoxConstraints(), - style: ButtonStyle(tapTargetSize: MaterialTapTargetSize.shrinkWrap), + UI.buttonIconOnly( onPressed: () {/*TODO*/}, + icon: FontAwesomeIcons.cartCircleArrowUp, ), ], ), @@ -301,132 +289,97 @@ class _AccountRootPageState extends State { List _buildCards(BuildContext context, User user) { return [ - Card.filled( + UI.buttonCard( + context: context, margin: EdgeInsets.fromLTRB(0, 4, 0, 4), - shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)), - color: Theme.of(context).cardTheme.color, - child: InkWell( - splashColor: Theme.of(context).splashColor, - onTap: () {/*TODO*/}, - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - FutureBuilder( - future: futureSubscriptionCount, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - return Text('${snapshot.data}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)); - } - return const SizedBox(width: 12, height: 12, child: Center(child: CircularProgressIndicator())); - }, - ), - const SizedBox(width: 12), - Text('Subscriptions', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), - ], + child: Row( + children: [ + FutureBuilder( + future: futureSubscriptionCount, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Text('${snapshot.data}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)); + } + return const SizedBox(width: 12, height: 12, child: Center(child: CircularProgressIndicator())); + }, ), - ), + const SizedBox(width: 12), + Text('Subscriptions', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + ], ), + onTap: () {/*TODO*/}, ), - Card.filled( + UI.buttonCard( + context: context, margin: EdgeInsets.fromLTRB(0, 4, 0, 4), - shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)), - color: Theme.of(context).cardTheme.color, - child: InkWell( - splashColor: Theme.of(context).splashColor, - onTap: () {/*TODO*/}, - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - FutureBuilder( - future: futureClientCount, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - return Text('${snapshot.data}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)); - } - return const SizedBox(width: 12, height: 12, child: Center(child: CircularProgressIndicator())); - }, - ), - const SizedBox(width: 12), - Text('Clients', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), - ], + child: Row( + children: [ + FutureBuilder( + future: futureClientCount, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Text('${snapshot.data}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)); + } + return const SizedBox(width: 12, height: 12, child: Center(child: CircularProgressIndicator())); + }, ), - ), + const SizedBox(width: 12), + Text('Clients', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + ], ), + onTap: () {/*TODO*/}, ), - Card.filled( + UI.buttonCard( + context: context, margin: EdgeInsets.fromLTRB(0, 4, 0, 4), - shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)), - color: Theme.of(context).cardTheme.color, - child: InkWell( - splashColor: Theme.of(context).splashColor, - onTap: () {/*TODO*/}, - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - FutureBuilder( - future: futureKeyCount, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - return Text('${snapshot.data}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)); - } - return const SizedBox(width: 12, height: 12, child: Center(child: CircularProgressIndicator())); - }, - ), - const SizedBox(width: 12), - Text('Keys', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), - ], + child: Row( + children: [ + FutureBuilder( + future: futureKeyCount, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Text('${snapshot.data}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)); + } + return const SizedBox(width: 12, height: 12, child: Center(child: CircularProgressIndicator())); + }, ), - ), + const SizedBox(width: 12), + Text('Keys', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + ], ), + onTap: () {/*TODO*/}, ), - Card.filled( + UI.buttonCard( + context: context, margin: EdgeInsets.fromLTRB(0, 4, 0, 4), - shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)), - color: Theme.of(context).cardTheme.color, - child: InkWell( - splashColor: Theme.of(context).splashColor, - onTap: () {/*TODO*/}, - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - FutureBuilder( - future: futureChannelSubscribedCount, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - return Text('${snapshot.data}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)); - } - return const SizedBox(width: 12, height: 12, child: Center(child: CircularProgressIndicator())); - }, - ), - const SizedBox(width: 12), - Text('Channels', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), - ], + child: Row( + children: [ + FutureBuilder( + future: futureChannelSubscribedCount, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Text('${snapshot.data}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)); + } + return const SizedBox(width: 12, height: 12, child: Center(child: CircularProgressIndicator())); + }, ), - ), + const SizedBox(width: 12), + Text('Channels', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + ], ), + onTap: () {/*TODO*/}, ), - Card.filled( + UI.buttonCard( + context: context, margin: EdgeInsets.fromLTRB(0, 4, 0, 4), - shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(0)), - color: Theme.of(context).cardTheme.color, - child: InkWell( - splashColor: Theme.of(context).splashColor, - onTap: () {/*TODO*/}, - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Text('${user.messagesSent}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), - const SizedBox(width: 12), - Text('Messages', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), - ], - ), - ), + child: Row( + children: [ + Text('${user.messagesSent}', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + const SizedBox(width: 12), + Text('Messages', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + ], ), + onTap: () {/*TODO*/}, ), ]; } @@ -436,9 +389,19 @@ class _AccountRootPageState extends State { padding: const EdgeInsets.fromLTRB(8, 0, 8, 0), child: Row( children: [ - Expanded(child: FilledButton(onPressed: _logout, child: Text('Logout'), style: TextButton.styleFrom(backgroundColor: Colors.orange))), + Expanded( + child: UI.button( + text: 'Logout', + onPressed: _logout, + color: Colors.orange, + )), const SizedBox(width: 8), - Expanded(child: FilledButton(onPressed: _deleteAccount, child: Text('Delete Account'), style: TextButton.styleFrom(backgroundColor: Colors.red))), + Expanded( + child: UI.button( + text: 'Delete Account', + onPressed: _deleteAccount, + color: Colors.red, + )), ], ), ); diff --git a/flutter/lib/pages/account/login.dart b/flutter/lib/pages/account/login.dart index 3230708..2711ce0 100644 --- a/flutter/lib/pages/account/login.dart +++ b/flutter/lib/pages/account/login.dart @@ -9,6 +9,7 @@ import 'package:simplecloudnotifier/state/globals.dart'; import 'package:simplecloudnotifier/state/app_auth.dart'; import 'package:simplecloudnotifier/state/token_source.dart'; import 'package:simplecloudnotifier/utils/toaster.dart'; +import 'package:simplecloudnotifier/utils/ui.dart'; class AccountLoginPage extends StatefulWidget { const AccountLoginPage({super.key}); @@ -102,10 +103,10 @@ class _AccountLoginPageState extends State { ), ), const SizedBox(height: 16), - FilledButton( - style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 24), padding: const EdgeInsets.fromLTRB(8, 12, 8, 12)), + UI.button( + text: 'Login', + big: true, onPressed: _login, - child: const Text('Login'), ), ], ), diff --git a/flutter/lib/pages/debug/debug_actions.dart b/flutter/lib/pages/debug/debug_actions.dart index 01d4118..281a4dc 100644 --- a/flutter/lib/pages/debug/debug_actions.dart +++ b/flutter/lib/pages/debug/debug_actions.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:simplecloudnotifier/utils/toaster.dart'; +import 'package:simplecloudnotifier/utils/ui.dart'; import 'package:toastification/toastification.dart'; class DebugActionsPage extends StatefulWidget { @@ -17,36 +18,40 @@ class _DebugActionsPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - FilledButton( - style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 20)), + UI.button( + big: false, onPressed: () => Toaster.success("Hello World", "This was a triumph!"), - child: const Text('Show Success Notification'), + text: 'Show Success Notification', ), - FilledButton( - style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 20)), + SizedBox(height: 4), + UI.button( + big: false, onPressed: () => Toaster.info("Hello World", "This was a triumph!"), - child: const Text('Show Info Notification'), + text: 'Show Info Notification', ), - FilledButton( - style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 20)), + SizedBox(height: 4), + UI.button( + big: false, onPressed: () => Toaster.warn("Hello World", "This was a triumph!"), - child: const Text('Show Warn Notification'), + text: 'Show Warn Notification', ), - FilledButton( - style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 20)), + SizedBox(height: 4), + UI.button( + big: false, onPressed: () => Toaster.error("Hello World", "This was a triumph!"), - child: const Text('Show Info Notification'), + text: 'Show Info Notification', ), - FilledButton( - style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 20)), + SizedBox(height: 4), + UI.button( + big: false, onPressed: () => Toaster.simple("Hello World"), - child: const Text('Show Simple Notification'), + text: 'Show Simple Notification', ), SizedBox(height: 20), - FilledButton( - style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 20)), + UI.button( + big: false, onPressed: _sendTokenToServer, - child: const Text('Send FCM Token to Server'), + text: 'Send FCM Token to Server', ), ], ), diff --git a/flutter/lib/pages/debug/debug_request_view.dart b/flutter/lib/pages/debug/debug_request_view.dart index 03f15ea..b6c7eed 100644 --- a/flutter/lib/pages/debug/debug_request_view.dart +++ b/flutter/lib/pages/debug/debug_request_view.dart @@ -4,6 +4,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:simplecloudnotifier/components/layout/scaffold.dart'; import 'package:simplecloudnotifier/state/request_log.dart'; import 'package:simplecloudnotifier/utils/toaster.dart'; +import 'package:simplecloudnotifier/utils/ui.dart'; class DebugRequestViewPage extends StatelessWidget { final SCNRequest request; @@ -55,17 +56,13 @@ class DebugRequestViewPage extends StatelessWidget { Expanded( child: Text(title, style: TextStyle(fontWeight: FontWeight.bold)), ), - IconButton( - icon: FaIcon( - FontAwesomeIcons.copy, - ), + UI.buttonIconOnly( iconSize: 14, - padding: EdgeInsets.fromLTRB(0, 0, 4, 0), - constraints: BoxConstraints(), onPressed: () { - Clipboard.setData(new ClipboardData(text: value)); + Clipboard.setData(new ClipboardData(text: title)); Toaster.info("Clipboard", 'Copied text to Clipboard'); }, + icon: FontAwesomeIcons.copy, ), ], ), diff --git a/flutter/lib/pages/message_list/message_list_item.dart b/flutter/lib/pages/message_list/message_list_item.dart index b81daf9..852b1ec 100644 --- a/flutter/lib/pages/message_list/message_list_item.dart +++ b/flutter/lib/pages/message_list/message_list_item.dart @@ -5,6 +5,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:simplecloudnotifier/models/channel.dart'; import 'package:simplecloudnotifier/models/message.dart'; import 'package:intl/intl.dart'; +import 'package:simplecloudnotifier/utils/ui.dart'; class MessageListItem extends StatelessWidget { static final _dateFormat = DateFormat('yyyy-MM-dd kk:mm'); @@ -102,19 +103,10 @@ class MessageListItem extends StatelessWidget { if (message.priority == 2) SizedBox(width: 4), if (message.priority == 0) FaIcon(FontAwesomeIcons.solidDown, size: 16, color: Colors.lightBlue[900]), if (message.priority == 0) SizedBox(width: 4), - Container( - padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), - margin: const EdgeInsets.fromLTRB(0, 0, 4, 0), - decoration: BoxDecoration( - color: Theme.of(context).hintColor, - borderRadius: BorderRadius.all(Radius.circular(4)), - ), - child: Text( - resolveChannelName(message), - style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).cardColor, fontSize: 12), - overflow: TextOverflow.clip, - maxLines: 1, - ), + UI.channelChip( + context: context, + text: resolveChannelName(message), + margin: EdgeInsets.fromLTRB(0, 0, 4, 0), ), Expanded(child: SizedBox()), Text( diff --git a/flutter/lib/pages/message_view/message_view.dart b/flutter/lib/pages/message_view/message_view.dart index 4bb62e5..92becc7 100644 --- a/flutter/lib/pages/message_view/message_view.dart +++ b/flutter/lib/pages/message_view/message_view.dart @@ -12,6 +12,7 @@ import 'package:simplecloudnotifier/models/keytoken.dart'; import 'package:simplecloudnotifier/models/message.dart'; import 'package:simplecloudnotifier/models/user.dart'; import 'package:simplecloudnotifier/state/app_auth.dart'; +import 'package:simplecloudnotifier/utils/ui.dart'; class MessageViewPage extends StatefulWidget { const MessageViewPage({super.key, required this.message}); @@ -129,19 +130,11 @@ class _MessageViewPageState extends State { return [ Row( children: [ - Container( - padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), + UI.channelChip( + context: context, + text: _resolveChannelName(channel, message), margin: const EdgeInsets.fromLTRB(0, 0, 4, 0), - decoration: BoxDecoration( - color: Theme.of(context).hintColor, - borderRadius: BorderRadius.all(Radius.circular(4)), - ), - child: Text( - _resolveChannelName(channel, message), - style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).cardColor, fontSize: 16), - overflow: TextOverflow.clip, - maxLines: 1, - ), + fontSize: 16, ), Expanded(child: SizedBox()), Text(_dateFormat.format(DateTime.parse(message.timestamp)), style: const TextStyle(fontSize: 14)), @@ -157,29 +150,18 @@ class _MessageViewPageState extends State { Row( children: [ Expanded(child: SizedBox()), - IconButton( - icon: FaIcon(FontAwesomeIcons.copy), - iconSize: 18, - padding: EdgeInsets.all(4), - constraints: BoxConstraints(), - style: ButtonStyle(tapTargetSize: MaterialTapTargetSize.shrinkWrap), + UI.buttonIconOnly( onPressed: () {/*TODO*/}, + icon: FontAwesomeIcons.copy, ), - IconButton( - icon: FaIcon(FontAwesomeIcons.lineColumns), - iconSize: 18, - padding: EdgeInsets.all(4), - constraints: BoxConstraints(), - style: ButtonStyle(tapTargetSize: MaterialTapTargetSize.shrinkWrap), + UI.buttonIconOnly( + icon: FontAwesomeIcons.lineColumns, onPressed: () {/*TODO*/}, ), ], ), - Container( - decoration: BoxDecoration( - border: Border.all(color: Theme.of(context).hintColor), - borderRadius: BorderRadius.circular(4), - ), + UI.box( + context: context, padding: const EdgeInsets.all(4), child: Text(message.content ?? ''), ), @@ -187,12 +169,9 @@ class _MessageViewPageState extends State { } Widget _buildMetaCard(BuildContext context, IconData icn, String title, List values, void Function()? action) { - final container = Container( + final container = UI.box( + context: context, padding: EdgeInsets.fromLTRB(16, 2, 4, 2), - decoration: BoxDecoration( - border: Border.all(color: Theme.of(context).hintColor), - borderRadius: BorderRadius.circular(4), - ), child: Row( children: [ FaIcon(icn, size: 18), diff --git a/flutter/lib/utils/navi.dart b/flutter/lib/utils/navi.dart new file mode 100644 index 0000000..6b6d16c --- /dev/null +++ b/flutter/lib/utils/navi.dart @@ -0,0 +1 @@ +class Navi {} diff --git a/flutter/lib/utils/ui.dart b/flutter/lib/utils/ui.dart new file mode 100644 index 0000000..c95e988 --- /dev/null +++ b/flutter/lib/utils/ui.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class UI { + static const double DefaultBorderRadius = 4; + + static Widget button({required String text, required void Function() onPressed, bool big = false, Color? color = null, bool tonal = false, IconData? icon = null}) { + final double fontSize = big ? 24 : 14; + final padding = big ? EdgeInsets.fromLTRB(8, 12, 8, 12) : null; + + final style = FilledButton.styleFrom( + textStyle: TextStyle(fontSize: fontSize), + padding: padding, + backgroundColor: color, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(DefaultBorderRadius)), + ); + + if (tonal) { + if (icon != null) { + return FilledButton.tonalIcon( + style: style, + onPressed: onPressed, + icon: Icon(icon), + label: Text(text), + ); + } else { + return FilledButton.tonal( + style: style, + onPressed: onPressed, + child: Text(text), + ); + } + } else { + if (icon != null) { + return FilledButton.icon( + style: style, + onPressed: onPressed, + icon: Icon(icon), + label: Text(text), + ); + } else { + return FilledButton( + style: style, + onPressed: onPressed, + child: Text(text), + ); + } + } + } + + static Widget buttonIconOnly({ + required void Function() onPressed, + required IconData icon, + double? iconSize = null, + }) { + return IconButton( + icon: FaIcon(icon), + iconSize: iconSize ?? 18, + padding: EdgeInsets.all(4), + constraints: BoxConstraints(), + style: ButtonStyle(tapTargetSize: MaterialTapTargetSize.shrinkWrap), + onPressed: onPressed, + ); + } + + static Widget buttonCard({required BuildContext context, required Widget child, required void Function() onTap, EdgeInsets? margin = null}) { + return Card.filled( + margin: margin, + shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(DefaultBorderRadius)), + color: Theme.of(context).cardTheme.color, + child: InkWell( + splashColor: Theme.of(context).splashColor, + onTap: onTap, + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), + ), + ); + } + + static Widget channelChip({required BuildContext context, required String text, EdgeInsets? margin = null, double fontSize = 12}) { + return Container( + padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), + margin: margin, + decoration: BoxDecoration( + color: Theme.of(context).hintColor, + borderRadius: BorderRadius.all(Radius.circular(DefaultBorderRadius)), + ), + child: Text( + text, + style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).cardColor, fontSize: fontSize), + overflow: TextOverflow.clip, + maxLines: 1, + ), + ); + } + + static Widget box({required BuildContext context, required Widget child, required EdgeInsets? padding}) { + return Container( + padding: padding ?? EdgeInsets.all(4), + decoration: BoxDecoration( + border: Border.all(color: Theme.of(context).hintColor), + borderRadius: BorderRadius.circular(DefaultBorderRadius), + ), + child: child, + ); + } +}