Add first message highlights and various tweaks (#191)
* Add first msg & tweak chat message styles * Add options to show/hide alerts * Remove unused setting * Fix color * Change resume scroll arrrow * Tweak streamer name and title opacity * Tweak card weights * Renamed followed streams tab * Move settings stuff to details button * Darken the dark theme again * Remove unecessary observer * Tweaks
This commit is contained in:
parent
d4e9d82ee2
commit
f42ed2bc4e
14 changed files with 245 additions and 184 deletions
|
|
@ -82,7 +82,7 @@ void main() async {
|
|||
// Navigator key for sleep timer. Allows navigation popping without context.
|
||||
final navigatorKey = GlobalKey<NavigatorState>();
|
||||
|
||||
const gray = Color.fromRGBO(22, 22, 22, 1.0);
|
||||
const gray = Color.fromRGBO(18, 18, 18, 1.0);
|
||||
const purple = Color(0xff9146ff);
|
||||
|
||||
const inputTheme = InputDecorationTheme(
|
||||
|
|
|
|||
|
|
@ -17,10 +17,8 @@ import 'package:frosty/screens/channel/chat/stores/chat_store.dart';
|
|||
import 'package:frosty/screens/channel/video/video.dart';
|
||||
import 'package:frosty/screens/channel/video/video_overlay.dart';
|
||||
import 'package:frosty/screens/channel/video/video_store.dart';
|
||||
import 'package:frosty/screens/settings/settings.dart';
|
||||
import 'package:frosty/screens/settings/stores/auth_store.dart';
|
||||
import 'package:frosty/screens/settings/stores/settings_store.dart';
|
||||
import 'package:frosty/widgets/modal.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
/// Creates a widget that shows the video stream (if live) and chat of the given user.
|
||||
|
|
@ -73,65 +71,11 @@ class _VideoChatState extends State<VideoChat> {
|
|||
Widget build(BuildContext context) {
|
||||
final settingsStore = _chatStore.settings;
|
||||
|
||||
void showSettings() {
|
||||
showModalBottomSheet(
|
||||
backgroundColor: Colors.transparent,
|
||||
context: context,
|
||||
builder: (context) => FrostyModal(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.app_settings_alt),
|
||||
title: const Text('App settings'),
|
||||
onTap: () => showModalBottomSheet(
|
||||
backgroundColor: Colors.transparent,
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
builder: (context) => FrostyModal(
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.8,
|
||||
child: Settings(settingsStore: settingsStore),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.refresh),
|
||||
title: const Text('Reconnect to chat'),
|
||||
onTap: () {
|
||||
_chatStore.updateNotification('Reconnecting to chat...');
|
||||
|
||||
_chatStore.connectToChat();
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.refresh),
|
||||
title: const Text('Refresh badges and emotes'),
|
||||
onTap: () async {
|
||||
await _chatStore.getAssets();
|
||||
|
||||
_chatStore.updateNotification('Badges and emotes refreshed');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final appBar = AppBar(
|
||||
title: Text(
|
||||
regexEnglish.hasMatch(_chatStore.displayName) ? _chatStore.displayName : '${_chatStore.displayName} (${_chatStore.channelName})',
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: 'Settings',
|
||||
icon: const Icon(Icons.settings),
|
||||
onPressed: showSettings,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final player = GestureDetector(
|
||||
|
|
@ -144,7 +88,6 @@ class _VideoChatState extends State<VideoChat> {
|
|||
|
||||
final videoOverlay = VideoOverlay(
|
||||
videoStore: _videoStore,
|
||||
onSettingsPressed: showSettings,
|
||||
);
|
||||
|
||||
final overlay = GestureDetector(
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ class Chat extends StatelessWidget {
|
|||
: Button(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0),
|
||||
onPressed: chatStore.resumeScroll,
|
||||
icon: const Icon(Icons.arrow_circle_down),
|
||||
child: const Text('Resume Scroll'),
|
||||
icon: const Icon(Icons.arrow_downward),
|
||||
child: const Text('Resume scroll'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:frosty/screens/channel/chat/details/chat_details_store.dart';
|
||||
import 'package:frosty/screens/channel/chat/details/chat_modes.dart';
|
||||
import 'package:frosty/screens/channel/chat/details/chat_users_list.dart';
|
||||
import 'package:frosty/screens/channel/chat/stores/chat_store.dart';
|
||||
import 'package:frosty/screens/settings/settings.dart';
|
||||
import 'package:frosty/widgets/modal.dart';
|
||||
|
||||
class ChatDetails extends StatefulWidget {
|
||||
|
|
@ -32,28 +32,71 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FrostyModal(
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.8,
|
||||
child: GestureDetector(
|
||||
onTap: FocusScope.of(context).unfocus,
|
||||
child: Observer(
|
||||
builder: (_) => Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 15.0),
|
||||
child: ChatModes(roomState: widget.chatDetailsStore.roomState),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: ChatModes(roomState: widget.chatDetailsStore.roomState),
|
||||
),
|
||||
const Divider(
|
||||
height: 1.0,
|
||||
thickness: 1.0,
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.settings),
|
||||
title: const Text('Settings'),
|
||||
onTap: () => showModalBottomSheet(
|
||||
backgroundColor: Colors.transparent,
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
builder: (context) => FrostyModal(
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.8,
|
||||
child: Settings(settingsStore: widget.chatStore.settings),
|
||||
),
|
||||
Expanded(
|
||||
child: ChattersList(
|
||||
chatDetailsStore: widget.chatDetailsStore,
|
||||
chatStore: widget.chatStore,
|
||||
userLogin: widget.userLogin,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.people),
|
||||
title: const Text('Chatters'),
|
||||
onTap: () => showModalBottomSheet(
|
||||
backgroundColor: Colors.transparent,
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
builder: (context) => FrostyModal(
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.8,
|
||||
child: GestureDetector(
|
||||
onTap: FocusScope.of(context).unfocus,
|
||||
child: ChattersList(
|
||||
chatDetailsStore: widget.chatDetailsStore,
|
||||
chatStore: widget.chatStore,
|
||||
userLogin: widget.userLogin,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.refresh),
|
||||
title: const Text('Reconnect to chat'),
|
||||
onTap: () {
|
||||
widget.chatStore.updateNotification('Reconnecting to chat...');
|
||||
|
||||
widget.chatStore.connectToChat();
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.refresh),
|
||||
title: const Text('Refresh badges and emotes'),
|
||||
onTap: () async {
|
||||
await widget.chatStore.getAssets();
|
||||
|
||||
widget.chatStore.updateNotification('Badges and emotes refreshed');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class ChatModes extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Tooltip(
|
||||
preferBelow: false,
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ class ChatBottomBar extends StatelessWidget {
|
|||
else
|
||||
IconButton(
|
||||
icon: Icon(Icons.adaptive.more),
|
||||
tooltip: 'Chat details',
|
||||
tooltip: 'More',
|
||||
onPressed: () => showModalBottomSheet(
|
||||
backgroundColor: Colors.transparent,
|
||||
isScrollControlled: true,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ class ChatMessage extends StatelessWidget {
|
|||
chatStore.updateNotification('Message copied');
|
||||
}
|
||||
|
||||
final defaultTextStyle = DefaultTextStyle.of(context).style;
|
||||
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
Color? color;
|
||||
|
|
@ -59,13 +61,14 @@ class ChatMessage extends StatelessWidget {
|
|||
case Command.privateMessage:
|
||||
case Command.userState:
|
||||
// If user is being mentioned in the message, highlight it red.
|
||||
if (ircMessage.mention == true) color = Colors.red.withOpacity(0.3);
|
||||
if (ircMessage.mention == true) color = Colors.red.withOpacity(0.2);
|
||||
if (chatStore.settings.highlightFirstTimeChatter && ircMessage.tags['first-msg'] == '1') color = Colors.green.withOpacity(0.2);
|
||||
|
||||
final messageSpan = Text.rich(
|
||||
TextSpan(
|
||||
children: ircMessage.generateSpan(
|
||||
onLongPressName: onLongPressName,
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
style: defaultTextStyle,
|
||||
assetsStore: chatStore.assetsStore,
|
||||
emoteScale: chatStore.settings.emoteScale,
|
||||
badgeScale: chatStore.settings.badgeScale,
|
||||
|
|
@ -82,32 +85,41 @@ class ChatMessage extends StatelessWidget {
|
|||
final replyUser = ircMessage.tags['reply-parent-display-name'];
|
||||
final replyBody = ircMessage.tags['reply-parent-msg-body'];
|
||||
|
||||
if (replyUser != null && replyBody != null) {
|
||||
if ((replyUser != null && replyBody != null) || (chatStore.settings.highlightFirstTimeChatter && ircMessage.tags['first-msg'] == '1')) {
|
||||
renderMessage = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: 0.5,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.reply,
|
||||
size: defaultBadgeSize * chatStore.settings.badgeScale,
|
||||
),
|
||||
const SizedBox(width: 5.0),
|
||||
Flexible(
|
||||
child: Tooltip(
|
||||
message: 'Replying to @$replyUser: $replyBody',
|
||||
preferBelow: false,
|
||||
child: Text(
|
||||
'Replying to @$replyUser: $replyBody',
|
||||
maxLines: 1,
|
||||
style: const TextStyle(overflow: TextOverflow.ellipsis),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
replyUser != null && replyBody != null ? Icons.reply : Icons.new_releases_outlined,
|
||||
size: defaultBadgeSize * chatStore.settings.badgeScale,
|
||||
color: defaultTextStyle.color?.withOpacity(0.5),
|
||||
),
|
||||
const SizedBox(width: 5.0),
|
||||
Flexible(
|
||||
child: replyUser != null && replyBody != null
|
||||
? Tooltip(
|
||||
message: 'Replying to @$replyUser: $replyBody',
|
||||
preferBelow: false,
|
||||
child: Text(
|
||||
'Replying to @$replyUser: $replyBody',
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: defaultTextStyle.color?.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
'First time chatting',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: defaultTextStyle.color?.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5.0),
|
||||
messageSpan,
|
||||
|
|
@ -124,15 +136,32 @@ class ChatMessage extends StatelessWidget {
|
|||
final banDuration = ircMessage.tags['ban-duration'];
|
||||
|
||||
renderMessage = Opacity(
|
||||
opacity: 0.5,
|
||||
opacity: 0.4,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (banDuration == null)
|
||||
if (ircMessage.command == Command.clearMessage)
|
||||
const Text(
|
||||
'Message deleted',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
)
|
||||
else
|
||||
const Text(
|
||||
'Permanently banned',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
)
|
||||
else
|
||||
Text(
|
||||
'Timed out for $banDuration ${int.parse(banDuration) > 1 ? 'seconds' : 'second'}',
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
const SizedBox(height: 5.0),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: ircMessage.generateSpan(
|
||||
onLongPressName: onLongPressName,
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
style: defaultTextStyle,
|
||||
assetsStore: chatStore.assetsStore,
|
||||
emoteScale: chatStore.settings.emoteScale,
|
||||
badgeScale: chatStore.settings.badgeScale,
|
||||
|
|
@ -145,23 +174,6 @@ class ChatMessage extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5.0),
|
||||
if (banDuration == null)
|
||||
if (ircMessage.command == Command.clearMessage)
|
||||
const Text(
|
||||
'Message deleted',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
)
|
||||
else
|
||||
const Text(
|
||||
'User permanently banned',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
)
|
||||
else
|
||||
Text(
|
||||
'Timed out for $banDuration ${int.parse(banDuration) > 1 ? 'seconds' : 'second'}',
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
@ -169,51 +181,58 @@ class ChatMessage extends StatelessWidget {
|
|||
case Command.notice:
|
||||
renderMessage = Text.rich(
|
||||
TextSpan(text: ircMessage.message),
|
||||
style: TextStyle(color: Theme.of(context).textTheme.bodyText2?.color?.withOpacity(0.5)),
|
||||
style: TextStyle(color: defaultTextStyle.color?.withOpacity(0.5)),
|
||||
);
|
||||
break;
|
||||
case Command.userNotice:
|
||||
color = Colors.deepPurple.withOpacity(0.3);
|
||||
if (chatStore.settings.showUserNotices) {
|
||||
color = Colors.deepPurple.withOpacity(0.2);
|
||||
|
||||
renderMessage = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (ircMessage.tags.containsKey('system-msg'))
|
||||
Text(
|
||||
ircMessage.tags['system-msg']!,
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
if (ircMessage.tags.containsKey('msg-id') && ircMessage.tags['msg-id'] == 'announcement')
|
||||
Row(
|
||||
children: const [
|
||||
Icon(Icons.announcement),
|
||||
SizedBox(width: 5.0),
|
||||
Text(
|
||||
'Announcement',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5.0),
|
||||
if (ircMessage.message != null)
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: ircMessage.generateSpan(
|
||||
onLongPressName: onLongPressName,
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
assetsStore: chatStore.assetsStore,
|
||||
emoteScale: chatStore.settings.emoteScale,
|
||||
badgeScale: chatStore.settings.badgeScale,
|
||||
useZeroWidth: chatStore.settings.showZeroWidth,
|
||||
useReadableColors: chatStore.settings.useReadableColors,
|
||||
isLightTheme: Theme.of(context).brightness == Brightness.light,
|
||||
launchExternal: chatStore.settings.launchUrlExternal,
|
||||
timestamp: chatStore.settings.timestampType,
|
||||
renderMessage = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (ircMessage.tags.containsKey('system-msg'))
|
||||
Text(
|
||||
ircMessage.tags['system-msg']!,
|
||||
style: TextStyle(fontWeight: FontWeight.w600, color: defaultTextStyle.color?.withOpacity(0.5)),
|
||||
),
|
||||
if (ircMessage.tags['msg-id'] == 'announcement')
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.announcement_outlined,
|
||||
size: defaultBadgeSize * chatStore.settings.badgeScale,
|
||||
),
|
||||
const SizedBox(width: 5.0),
|
||||
const Text(
|
||||
'Announcement',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5.0),
|
||||
if (ircMessage.message != null)
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: ircMessage.generateSpan(
|
||||
onLongPressName: onLongPressName,
|
||||
style: defaultTextStyle,
|
||||
assetsStore: chatStore.assetsStore,
|
||||
emoteScale: chatStore.settings.emoteScale,
|
||||
badgeScale: chatStore.settings.badgeScale,
|
||||
useZeroWidth: chatStore.settings.showZeroWidth,
|
||||
useReadableColors: chatStore.settings.useReadableColors,
|
||||
isLightTheme: Theme.of(context).brightness == Brightness.light,
|
||||
launchExternal: chatStore.settings.launchUrlExternal,
|
||||
timestamp: chatStore.settings.timestampType,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
],
|
||||
);
|
||||
} else {
|
||||
renderMessage = const SizedBox();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
renderMessage = const SizedBox();
|
||||
|
|
|
|||
|
|
@ -14,12 +14,10 @@ import 'package:intl/intl.dart';
|
|||
/// Creates a widget containing controls which enable interactions with an underlying [Video] widget.
|
||||
class VideoOverlay extends StatelessWidget {
|
||||
final VideoStore videoStore;
|
||||
final void Function() onSettingsPressed;
|
||||
|
||||
const VideoOverlay({
|
||||
Key? key,
|
||||
required this.videoStore,
|
||||
required this.onSettingsPressed,
|
||||
}) : super(key: key);
|
||||
|
||||
Future<void> _showSleepTimerDialog(BuildContext context) {
|
||||
|
|
@ -108,15 +106,6 @@ class VideoOverlay extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
|
||||
final settingsButton = IconButton(
|
||||
tooltip: 'Settings',
|
||||
icon: const Icon(
|
||||
Icons.settings,
|
||||
color: Colors.white,
|
||||
),
|
||||
onPressed: onSettingsPressed,
|
||||
);
|
||||
|
||||
final chatOverlayButton = Observer(
|
||||
builder: (_) => IconButton(
|
||||
tooltip: videoStore.settingsStore.fullScreenChatOverlay ? 'Hide chat overlay' : 'Show chat overlay',
|
||||
|
|
@ -196,7 +185,6 @@ class VideoOverlay extends StatelessWidget {
|
|||
backButton,
|
||||
const Spacer(),
|
||||
if (videoStore.settingsStore.fullScreen && orientation == Orientation.landscape) chatOverlayButton,
|
||||
settingsButton,
|
||||
],
|
||||
),
|
||||
Align(
|
||||
|
|
@ -251,7 +239,6 @@ class VideoOverlay extends StatelessWidget {
|
|||
const Spacer(),
|
||||
if (videoStore.settingsStore.fullScreen && orientation == Orientation.landscape) chatOverlayButton,
|
||||
sleepTimerButton,
|
||||
settingsButton,
|
||||
],
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class _HomeState extends State<Home> {
|
|||
title: Observer(
|
||||
builder: (_) {
|
||||
final titles = [
|
||||
if (_authStore.isLoggedIn) 'Followed Streams',
|
||||
if (_authStore.isLoggedIn) 'Following',
|
||||
'Top',
|
||||
'Search',
|
||||
];
|
||||
|
|
@ -139,7 +139,7 @@ class _HomeState extends State<Home> {
|
|||
if (_authStore.isLoggedIn)
|
||||
const BottomNavigationBarItem(
|
||||
icon: Icon(Icons.favorite),
|
||||
label: 'Followed',
|
||||
label: 'Following',
|
||||
tooltip: 'Followed streams',
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ class StreamCard extends StatelessWidget {
|
|||
streamerName,
|
||||
style: TextStyle(
|
||||
fontSize: large ? 20.0 : 16.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: fontColor,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
|
@ -147,9 +147,8 @@ class StreamCard extends StatelessWidget {
|
|||
streamInfo.title.trim(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: subFontSize,
|
||||
color: fontColor,
|
||||
color: fontColor?.withOpacity(0.8),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class CategoryCard extends StatelessWidget {
|
|||
padding: const EdgeInsets.all(10.0),
|
||||
child: Text(
|
||||
category.name,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -217,6 +217,23 @@ class _ChatSettingsState extends State<ChatSettings> {
|
|||
.toList(),
|
||||
),
|
||||
),
|
||||
const SectionHeader(
|
||||
'Alerts',
|
||||
padding: sectionPadding,
|
||||
showDivider: true,
|
||||
),
|
||||
SwitchListTile.adaptive(
|
||||
title: const Text('Highlight first time chatters'),
|
||||
value: settingsStore.highlightFirstTimeChatter,
|
||||
onChanged: (newValue) => settingsStore.highlightFirstTimeChatter = newValue,
|
||||
),
|
||||
SwitchListTile.adaptive(
|
||||
isThreeLine: true,
|
||||
title: const Text('Show notices'),
|
||||
subtitle: const Text('Shows notices such as subs and re-subs, announcements, and raids.'),
|
||||
value: settingsStore.showUserNotices,
|
||||
onChanged: (newValue) => settingsStore.showUserNotices = newValue,
|
||||
),
|
||||
const SectionHeader(
|
||||
'Message Sizing',
|
||||
padding: sectionPadding,
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ abstract class _SettingsStoreBase with Store {
|
|||
static const defaultShowChatMessageDividers = false;
|
||||
static const defaultTimestampType = TimestampType.disabled;
|
||||
|
||||
static const defaultHighlightFirstTimeChatter = true;
|
||||
static const defaultShowUserNotices = true;
|
||||
|
||||
static const defaultBadgeScale = 1.0;
|
||||
static const defaultEmoteScale = 1.0;
|
||||
static const defaultMessageScale = 1.0;
|
||||
|
|
@ -165,6 +168,14 @@ abstract class _SettingsStoreBase with Store {
|
|||
@observable
|
||||
var timestampType = defaultTimestampType;
|
||||
|
||||
@JsonKey(defaultValue: defaultHighlightFirstTimeChatter)
|
||||
@observable
|
||||
var highlightFirstTimeChatter = defaultHighlightFirstTimeChatter;
|
||||
|
||||
@JsonKey(defaultValue: defaultShowUserNotices)
|
||||
@observable
|
||||
var showUserNotices = defaultHighlightFirstTimeChatter;
|
||||
|
||||
@JsonKey(defaultValue: defaultBadgeScale)
|
||||
@observable
|
||||
var badgeScale = defaultBadgeScale;
|
||||
|
|
@ -201,6 +212,8 @@ abstract class _SettingsStoreBase with Store {
|
|||
showDeletedMessages = defaultShowDeletedMessages;
|
||||
showChatMessageDividers = defaultShowChatMessageDividers;
|
||||
timestampType = defaultTimestampType;
|
||||
highlightFirstTimeChatter = defaultHighlightFirstTimeChatter;
|
||||
showUserNotices = defaultShowUserNotices;
|
||||
badgeScale = defaultBadgeScale;
|
||||
emoteScale = defaultEmoteScale;
|
||||
messageScale = defaultMessageScale;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ SettingsStore _$SettingsStoreFromJson(Map<String, dynamic> json) =>
|
|||
_$TimestampTypeEnumMap, json['timestampType'],
|
||||
unknownValue: TimestampType.disabled) ??
|
||||
TimestampType.disabled
|
||||
..highlightFirstTimeChatter =
|
||||
json['highlightFirstTimeChatter'] as bool? ?? true
|
||||
..showUserNotices = json['showUserNotices'] as bool? ?? true
|
||||
..badgeScale = (json['badgeScale'] as num?)?.toDouble() ?? 1.0
|
||||
..emoteScale = (json['emoteScale'] as num?)?.toDouble() ?? 1.0
|
||||
..messageScale = (json['messageScale'] as num?)?.toDouble() ?? 1.0
|
||||
|
|
@ -79,6 +82,8 @@ Map<String, dynamic> _$SettingsStoreToJson(SettingsStore instance) =>
|
|||
'showDeletedMessages': instance.showDeletedMessages,
|
||||
'showChatMessageDividers': instance.showChatMessageDividers,
|
||||
'timestampType': _$TimestampTypeEnumMap[instance.timestampType]!,
|
||||
'highlightFirstTimeChatter': instance.highlightFirstTimeChatter,
|
||||
'showUserNotices': instance.showUserNotices,
|
||||
'badgeScale': instance.badgeScale,
|
||||
'emoteScale': instance.emoteScale,
|
||||
'messageScale': instance.messageScale,
|
||||
|
|
@ -507,6 +512,39 @@ mixin _$SettingsStore on _SettingsStoreBase, Store {
|
|||
});
|
||||
}
|
||||
|
||||
late final _$highlightFirstTimeChatterAtom = Atom(
|
||||
name: '_SettingsStoreBase.highlightFirstTimeChatter', context: context);
|
||||
|
||||
@override
|
||||
bool get highlightFirstTimeChatter {
|
||||
_$highlightFirstTimeChatterAtom.reportRead();
|
||||
return super.highlightFirstTimeChatter;
|
||||
}
|
||||
|
||||
@override
|
||||
set highlightFirstTimeChatter(bool value) {
|
||||
_$highlightFirstTimeChatterAtom
|
||||
.reportWrite(value, super.highlightFirstTimeChatter, () {
|
||||
super.highlightFirstTimeChatter = value;
|
||||
});
|
||||
}
|
||||
|
||||
late final _$showUserNoticesAtom =
|
||||
Atom(name: '_SettingsStoreBase.showUserNotices', context: context);
|
||||
|
||||
@override
|
||||
bool get showUserNotices {
|
||||
_$showUserNoticesAtom.reportRead();
|
||||
return super.showUserNotices;
|
||||
}
|
||||
|
||||
@override
|
||||
set showUserNotices(bool value) {
|
||||
_$showUserNoticesAtom.reportWrite(value, super.showUserNotices, () {
|
||||
super.showUserNotices = value;
|
||||
});
|
||||
}
|
||||
|
||||
late final _$badgeScaleAtom =
|
||||
Atom(name: '_SettingsStoreBase.badgeScale', context: context);
|
||||
|
||||
|
|
@ -748,6 +786,8 @@ useReadableColors: ${useReadableColors},
|
|||
showDeletedMessages: ${showDeletedMessages},
|
||||
showChatMessageDividers: ${showChatMessageDividers},
|
||||
timestampType: ${timestampType},
|
||||
highlightFirstTimeChatter: ${highlightFirstTimeChatter},
|
||||
showUserNotices: ${showUserNotices},
|
||||
badgeScale: ${badgeScale},
|
||||
emoteScale: ${emoteScale},
|
||||
messageScale: ${messageScale},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue