diff --git a/lib/screens/channel/chat/chat.dart b/lib/screens/channel/chat/chat.dart index b8f7765e..6a9f15cb 100644 --- a/lib/screens/channel/chat/chat.dart +++ b/lib/screens/channel/chat/chat.dart @@ -5,6 +5,7 @@ import 'package:frosty/screens/channel/chat/widgets/chat_bottom_bar.dart'; import 'package:frosty/screens/channel/chat/widgets/chat_message.dart'; import 'package:frosty/screens/channel/chat/widgets/chat_user_modal.dart'; import 'package:frosty/screens/channel/stores/chat_store.dart'; +import 'package:frosty/widgets/button.dart'; class Chat extends StatelessWidget { final ChatStore chatStore; @@ -15,10 +16,6 @@ class Chat extends StatelessWidget { Widget build(BuildContext context) { return Observer( builder: (context) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (chatStore.scrollController.hasClients) chatStore.scrollController.jumpTo(chatStore.scrollController.position.maxScrollExtent); - }); - return Column( children: [ Expanded( @@ -93,14 +90,11 @@ class Chat extends StatelessWidget { duration: const Duration(milliseconds: 200), child: chatStore.autoScroll ? null - : Container( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - width: double.infinity, - child: ElevatedButton.icon( - onPressed: chatStore.resumeScroll, - label: const Text('Resume Scroll'), - icon: const Icon(Icons.arrow_circle_down), - ), + : Button( + padding: const EdgeInsets.all(10.0), + onPressed: chatStore.resumeScroll, + icon: const Icon(Icons.arrow_circle_down), + child: const Text('Resume Scroll'), ), ), ), @@ -109,11 +103,13 @@ class Chat extends StatelessWidget { ), ), if (chatStore.settings.showBottomBar) ChatBottomBar(chatStore: chatStore), - if (chatStore.assetsStore.showEmoteMenu) - SizedBox( - height: MediaQuery.of(context).size.height / 3, - child: EmoteMenu(chatStore: chatStore), - ), + AnimatedContainer( + curve: Curves.ease, + duration: const Duration(milliseconds: 200), + height: chatStore.assetsStore.showEmoteMenu ? MediaQuery.of(context).size.height / 3 : 0, + child: EmoteMenu(chatStore: chatStore), + onEnd: () => chatStore.scrollController.jumpTo(chatStore.scrollController.position.maxScrollExtent), + ), ], ); }, diff --git a/lib/screens/channel/chat/details/chat_users_list.dart b/lib/screens/channel/chat/details/chat_users_list.dart index 9faea78a..328b3a35 100644 --- a/lib/screens/channel/chat/details/chat_users_list.dart +++ b/lib/screens/channel/chat/details/chat_users_list.dart @@ -7,6 +7,7 @@ import 'package:frosty/core/auth/auth_store.dart'; import 'package:frosty/screens/channel/chat/widgets/chat_user_modal.dart'; import 'package:frosty/screens/channel/stores/chat_details_store.dart'; import 'package:frosty/screens/channel/stores/chat_store.dart'; +import 'package:frosty/widgets/button.dart'; import 'package:frosty/widgets/loading_indicator.dart'; import 'package:frosty/widgets/scroll_to_top_button.dart'; import 'package:frosty/widgets/section_header.dart'; @@ -104,7 +105,7 @@ class _ChattersListState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('Failed to get chatters'), - TextButton( + Button( onPressed: () => chatDetailsStore.updateChatters(widget.userLogin), child: const Text('Try Again'), ) diff --git a/lib/screens/channel/chat/emote_menu/emote_menu.dart b/lib/screens/channel/chat/emote_menu/emote_menu.dart index f21440a3..df18f42b 100644 --- a/lib/screens/channel/chat/emote_menu/emote_menu.dart +++ b/lib/screens/channel/chat/emote_menu/emote_menu.dart @@ -4,6 +4,7 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:frosty/screens/channel/chat/emote_menu/emote_menu_panel.dart'; import 'package:frosty/screens/channel/chat/emote_menu/recent_emotes_panel.dart'; import 'package:frosty/screens/channel/stores/chat_store.dart'; +import 'package:frosty/widgets/button.dart'; class EmoteMenu extends StatefulWidget { final ChatStore chatStore; @@ -31,14 +32,19 @@ class _EmoteMenuState extends State { ]; return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ + const Divider( + height: 5.0, + thickness: 1.0, + ), SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: sections .mapIndexed( (index, section) => Observer( - builder: (context) => TextButton( + builder: (context) => Button( onPressed: () { _pageContoller.animateToPage( index, @@ -47,7 +53,7 @@ class _EmoteMenuState extends State { ); widget.chatStore.assetsStore.emoteMenuIndex = index; }, - style: index == widget.chatStore.assetsStore.emoteMenuIndex ? null : TextButton.styleFrom(primary: Colors.grey), + color: index == widget.chatStore.assetsStore.emoteMenuIndex ? Theme.of(context).colorScheme.secondary : Colors.grey, child: Text( section, style: const TextStyle( diff --git a/lib/screens/channel/chat/emote_menu/recent_emotes_panel.dart b/lib/screens/channel/chat/emote_menu/recent_emotes_panel.dart index e0001bb3..23a6c182 100644 --- a/lib/screens/channel/chat/emote_menu/recent_emotes_panel.dart +++ b/lib/screens/channel/chat/emote_menu/recent_emotes_panel.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:frosty/constants/constants.dart'; import 'package:frosty/screens/channel/stores/chat_store.dart'; import 'package:frosty/screens/settings/stores/settings_store.dart'; +import 'package:frosty/widgets/button.dart'; import 'package:frosty/widgets/section_header.dart'; import 'package:provider/provider.dart'; @@ -26,12 +27,12 @@ class _RecentEmotesPanelState extends State { title: const Text('Clear Recent Emotes'), content: const Text('Are you sure you want to clear your recent emotes?'), actions: [ - TextButton( + Button( onPressed: Navigator.of(context).pop, - style: TextButton.styleFrom(primary: Colors.red), + color: Colors.red, child: const Text('Cancel'), ), - ElevatedButton( + Button( onPressed: () { setState(widget.chatStore.assetsStore.recentEmotes.clear); Navigator.pop(context); @@ -56,9 +57,10 @@ class _RecentEmotesPanelState extends State { ), const Spacer(), SizedBox( - height: 30, - child: TextButton( + height: 25, + child: Button( onPressed: widget.chatStore.assetsStore.recentEmotes.isEmpty ? null : _showClearDialog, + color: Theme.of(context).colorScheme.secondary, child: const Text( 'CLEAR', style: TextStyle( diff --git a/lib/screens/channel/chat/widgets/chat_bottom_bar.dart b/lib/screens/channel/chat/widgets/chat_bottom_bar.dart index cba6191e..5ac8dcc3 100644 --- a/lib/screens/channel/chat/widgets/chat_bottom_bar.dart +++ b/lib/screens/channel/chat/widgets/chat_bottom_bar.dart @@ -4,6 +4,7 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:frosty/constants/constants.dart'; import 'package:frosty/screens/channel/chat/details/chat_details.dart'; import 'package:frosty/screens/channel/stores/chat_store.dart'; +import 'package:frosty/widgets/button.dart'; class ChatBottomBar extends StatelessWidget { final ChatStore chatStore; @@ -70,7 +71,7 @@ class ChatBottomBar extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 5.0), itemCount: matchingChatters.length, scrollDirection: Axis.horizontal, - itemBuilder: (context, index) => TextButton( + itemBuilder: (context, index) => Button( onPressed: () { final split = chatStore.textController.text.split(' ') ..removeLast() @@ -104,12 +105,13 @@ class ChatBottomBar extends StatelessWidget { ), if (!chatStore.expandChat && chatStore.settings.chatWidth < 0.3 && MediaQuery.of(context).orientation == Orientation.landscape) IconButton( - tooltip: 'Send a Message', - onPressed: () { - chatStore.expandChat = true; - chatStore.textFieldFocusNode.requestFocus(); - }, - icon: const Icon(Icons.chat)) + tooltip: 'Send a Message', + onPressed: () { + chatStore.expandChat = true; + chatStore.textFieldFocusNode.requestFocus(); + }, + icon: const Icon(Icons.chat), + ) else Expanded( child: Padding( @@ -122,7 +124,7 @@ class ChatBottomBar extends StatelessWidget { enabled: chatStore.auth.isLoggedIn ? true : false, decoration: InputDecoration( suffixIcon: IconButton( - color: chatStore.assetsStore.showEmoteMenu ? Colors.deepPurple : null, + color: chatStore.assetsStore.showEmoteMenu ? Theme.of(context).colorScheme.secondary : null, tooltip: 'Emote Menu', icon: const Icon(Icons.emoji_emotions_outlined), onPressed: () { diff --git a/lib/screens/channel/chat/widgets/chat_user_modal.dart b/lib/screens/channel/chat/widgets/chat_user_modal.dart index c2f9f1ab..11737968 100644 --- a/lib/screens/channel/chat/widgets/chat_user_modal.dart +++ b/lib/screens/channel/chat/widgets/chat_user_modal.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:frosty/screens/channel/chat/widgets/chat_message.dart'; import 'package:frosty/screens/channel/stores/chat_store.dart'; import 'package:frosty/widgets/block_report_modal.dart'; +import 'package:frosty/widgets/button.dart'; import 'package:frosty/widgets/profile_picture.dart'; import 'package:frosty/widgets/section_header.dart'; @@ -62,7 +63,7 @@ class _ChatUserModalState extends State { ], ), trailing: widget.chatStore.auth.isLoggedIn - ? OutlinedButton( + ? Button( onPressed: () { widget.chatStore.textController.text = '@${widget.username} '; Navigator.pop(context); diff --git a/lib/screens/channel/video_chat.dart b/lib/screens/channel/video_chat.dart index daeff269..6ea4038e 100644 --- a/lib/screens/channel/video_chat.dart +++ b/lib/screens/channel/video_chat.dart @@ -18,6 +18,7 @@ import 'package:frosty/screens/channel/stores/chat_store.dart'; import 'package:frosty/screens/channel/stores/video_store.dart'; import 'package:frosty/screens/settings/settings.dart'; import 'package:frosty/screens/settings/stores/settings_store.dart'; +import 'package:frosty/widgets/button.dart'; import 'package:frosty/widgets/profile_picture.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; @@ -342,13 +343,13 @@ class _VideoOverlay extends StatelessWidget { ), ), actions: [ - TextButton( + Button( onPressed: Navigator.of(context).pop, - style: TextButton.styleFrom(primary: Colors.red), + color: Colors.red, child: const Text('Dismiss'), ), Observer( - builder: (context) => ElevatedButton( + builder: (context) => Button( onPressed: videoStore.sleepHours == 0 && videoStore.sleepMinutes == 0 ? null : () => videoStore.updateSleepTimer( @@ -590,7 +591,7 @@ class _VideoOverlay extends StatelessWidget { overflow: TextOverflow.ellipsis, style: const TextStyle( color: Colors.white, - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w600, ), ), ), diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 060cf147..f138a6e8 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -10,6 +10,7 @@ import 'package:frosty/screens/home/top/top_section.dart'; import 'package:frosty/screens/home/widgets/streams_list.dart'; import 'package:frosty/screens/settings/settings.dart'; import 'package:frosty/screens/settings/stores/settings_store.dart'; +import 'package:frosty/widgets/button.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -63,7 +64,7 @@ class _HomeState extends State { ], ), actions: [ - TextButton( + Button( onPressed: () { prefs.setBool('first_run', false); diff --git a/lib/screens/home/widgets/stream_card.dart b/lib/screens/home/widgets/stream_card.dart index b08e5c31..369392d0 100644 --- a/lib/screens/home/widgets/stream_card.dart +++ b/lib/screens/home/widgets/stream_card.dart @@ -143,7 +143,7 @@ class _StreamCardState extends State { widget.streamInfo.title.trim(), overflow: TextOverflow.ellipsis, style: const TextStyle( - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w600, ), ), ), diff --git a/lib/screens/settings/sections/account_settings.dart b/lib/screens/settings/sections/account_settings.dart index 7e5a1408..de9eaa29 100644 --- a/lib/screens/settings/sections/account_settings.dart +++ b/lib/screens/settings/sections/account_settings.dart @@ -6,6 +6,7 @@ import 'package:frosty/constants/constants.dart'; import 'package:frosty/core/auth/auth_store.dart'; import 'package:frosty/screens/settings/stores/settings_store.dart'; import 'package:frosty/widgets/block_button.dart'; +import 'package:frosty/widgets/button.dart'; import 'package:webview_flutter/webview_flutter.dart'; class AccountSettings extends StatelessWidget { @@ -132,22 +133,44 @@ class ProfileCard extends StatelessWidget { return showDialog( context: context, builder: (context) => AlertDialog( - title: const Text('Log Out'), - content: const Text('Are you sure you want to log out?'), - actions: [ - TextButton( - onPressed: Navigator.of(context).pop, - style: TextButton.styleFrom(primary: Colors.red), - child: const Text('Cancel'), + title: const Text( + 'Log Out', + style: TextStyle( + fontWeight: FontWeight.bold, ), - ElevatedButton( - onPressed: () { - authStore.logout(); - Navigator.pop(context); - }, - child: const Text('Yes'), - ), - ], + ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('Are you sure you want to log out?'), + const SizedBox(height: 50.0), + Column( + children: [ + SizedBox( + width: double.infinity, + child: Button( + fontSize: 16.0, + onPressed: () { + authStore.logout(); + Navigator.pop(context); + }, + child: const Text('Yes'), + ), + ), + const SizedBox(height: 10.0), + SizedBox( + width: double.infinity, + child: Button( + fontSize: 16.0, + onPressed: Navigator.of(context).pop, + color: Colors.red.withOpacity(0.8), + child: const Text('Cancel'), + ), + ), + ], + ) + ], + ), ), ); } @@ -160,7 +183,7 @@ class ProfileCard extends StatelessWidget { if (authStore.error != null) { return ListTile( title: const Text('Failed to Connect'), - trailing: OutlinedButton( + trailing: Button( onPressed: authStore.init, child: const Text('Try Again'), ), @@ -175,11 +198,12 @@ class ProfileCard extends StatelessWidget { authStore.user.details!.displayName, style: const TextStyle(fontWeight: FontWeight.w600), ), - trailing: OutlinedButton.icon( + trailing: Button( onPressed: () => _showLogoutDialog(context), icon: const Icon(Icons.logout_outlined), - label: const Text('Log Out'), - style: OutlinedButton.styleFrom(primary: Colors.red), + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 5.0), + color: Colors.red, + child: const Text('Log Out'), ), ); } @@ -191,10 +215,10 @@ class ProfileCard extends StatelessWidget { ), title: const Text('Anonymous User'), subtitle: const Text('Log in to chat, view followed streams, and more.'), - trailing: ElevatedButton.icon( + trailing: Button( onPressed: () => _showLoginDialog(context), icon: const Icon(Icons.login), - label: const Text('Log In'), + child: const Text('Log In'), ), ); }, diff --git a/lib/screens/settings/sections/other_settings.dart b/lib/screens/settings/sections/other_settings.dart index fee1d161..2805c692 100644 --- a/lib/screens/settings/sections/other_settings.dart +++ b/lib/screens/settings/sections/other_settings.dart @@ -4,6 +4,7 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:frosty/constants/constants.dart'; import 'package:frosty/screens/settings/stores/settings_store.dart'; +import 'package:frosty/widgets/button.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -28,12 +29,12 @@ class _OtherSettingsState extends State { title: const Text('Reset All Settings'), content: const Text('Are you sure you want to reset all settings?'), actions: [ - TextButton( + Button( onPressed: Navigator.of(context).pop, - style: TextButton.styleFrom(primary: Colors.red), + color: Colors.red, child: const Text('Cancel'), ), - ElevatedButton( + Button( onPressed: () { widget.settingsStore.resetAllSettings(); Navigator.pop(context); @@ -104,9 +105,9 @@ class _OtherSettingsState extends State { Container( padding: const EdgeInsets.symmetric(horizontal: 15.0), width: double.infinity, - child: OutlinedButton.icon( + child: Button( icon: const Icon(Icons.delete_sweep), - label: const Text('Clear Image Cache'), + child: const Text('Clear Image Cache'), onPressed: () async { await DefaultCacheManager().emptyCache(); @@ -123,10 +124,10 @@ class _OtherSettingsState extends State { Container( padding: const EdgeInsets.symmetric(horizontal: 15.0), width: double.infinity, - child: OutlinedButton.icon( - icon: const Icon(Icons.restore), - label: const Text('Reset All Settings'), + child: Button( onPressed: () => _showConfirmDialog(context), + icon: const Icon(Icons.restore), + child: const Text('Reset All Settings'), ), ), ], diff --git a/lib/widgets/block_button.dart b/lib/widgets/block_button.dart index 6b4ee7a5..6a4b0cef 100644 --- a/lib/widgets/block_button.dart +++ b/lib/widgets/block_button.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:frosty/core/auth/auth_store.dart'; +import 'package:frosty/widgets/button.dart'; class BlockButton extends StatelessWidget { final AuthStore authStore; @@ -29,12 +30,12 @@ class BlockButton extends StatelessWidget { content: Text( 'Are you sure you want to ${isBlocked ? 'unblock $targetUser?' : 'block $targetUser? This will remove them from channel lists, search results, and chat messages.'}'), actions: [ - TextButton( + Button( onPressed: Navigator.of(context).pop, - style: TextButton.styleFrom(primary: Colors.red), + color: Colors.red, child: const Text('Cancel'), ), - ElevatedButton( + Button( onPressed: () { if (isBlocked) { authStore.user.unblock(targetId: targetUserId, headers: authStore.headersTwitch); @@ -60,16 +61,16 @@ class BlockButton extends StatelessWidget { builder: (context) { final isBlocked = authStore.user.blockedUsers.where((blockedUser) => blockedUser.userId == targetUserId).isNotEmpty; - return OutlinedButton.icon( + return Button( icon: const Icon(Icons.block), - label: isBlocked ? Text(simple ? 'Unblock' : 'Unblock $targetUser') : Text(simple ? 'Block' : 'Block $targetUser'), + color: Colors.red, onPressed: () => _showDialog( context, isBlocked: isBlocked, targetUser: targetUser, targetUserId: targetUserId, ), - style: OutlinedButton.styleFrom(primary: Colors.red), + child: isBlocked ? Text(simple ? 'Unblock' : 'Unblock $targetUser') : Text(simple ? 'Block' : 'Block $targetUser'), ); }, ); diff --git a/lib/widgets/report_button.dart b/lib/widgets/report_button.dart index 12b5654f..a2914db2 100644 --- a/lib/widgets/report_button.dart +++ b/lib/widgets/report_button.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:frosty/widgets/button.dart'; import 'package:webview_flutter/webview_flutter.dart'; class ReportButton extends StatelessWidget { @@ -13,7 +14,7 @@ class ReportButton extends StatelessWidget { @override Widget build(BuildContext context) { - return OutlinedButton.icon( + return Button( icon: const Icon(Icons.report), onPressed: () => Navigator.push( context, @@ -31,8 +32,8 @@ class ReportButton extends StatelessWidget { }, ), ), - label: Text('Report $displayName'), - style: OutlinedButton.styleFrom(primary: Colors.red), + color: Colors.red, + child: Text('Report $displayName'), ); } }