diff --git a/lib/core/settings/settings.dart b/lib/core/settings/settings.dart index 1f0a01a7..054eb000 100644 --- a/lib/core/settings/settings.dart +++ b/lib/core/settings/settings.dart @@ -26,6 +26,17 @@ class Settings extends StatelessWidget { value: settingsStore.videoEnabled, onChanged: (newValue) => settingsStore.videoEnabled = newValue, ), + ListTile( + title: const Text('Chat Message Limit'), + subtitle: Slider( + value: settingsStore.messageLimit, + onChanged: (newValue) => settingsStore.messageLimit = newValue, + min: 0, + max: 1000, + divisions: 10, + label: settingsStore.messageLimit == 1000 ? 'Unlimited' : '${settingsStore.messageLimit}', + ), + ) ], ); }, diff --git a/lib/core/settings/settings_store.dart b/lib/core/settings/settings_store.dart index df616af6..a492cf16 100644 --- a/lib/core/settings/settings_store.dart +++ b/lib/core/settings/settings_store.dart @@ -7,21 +7,26 @@ part 'settings_store.g.dart'; class SettingsStore = _SettingsStoreBase with _$SettingsStore; abstract class _SettingsStoreBase with Store { + @observable + bool videoEnabled = true; + + @observable + double messageLimit = 200; + Future init() async { // Retrieve the instance that will allow us to store and persist settings. final prefs = await SharedPreferences.getInstance(); // Initialize settings from stored preferences if any. videoEnabled = prefs.getBool('video_enabled') ?? videoEnabled; + messageLimit = prefs.getDouble('message_limit') ?? messageLimit; // Set up autorun to store setting anytime they're changed. // The ReactionDisposer will not be needed since settings will always exist. autorun((_) { - debugPrint('video changed'); + debugPrint('settings changed'); prefs.setBool('video_enabled', videoEnabled); + prefs.setDouble('message_limit', messageLimit); }); } - - @observable - bool videoEnabled = true; } diff --git a/lib/core/settings/settings_store.g.dart b/lib/core/settings/settings_store.g.dart index 286c8dec..16a11ce4 100644 --- a/lib/core/settings/settings_store.g.dart +++ b/lib/core/settings/settings_store.g.dart @@ -24,10 +24,26 @@ mixin _$SettingsStore on _SettingsStoreBase, Store { }); } + final _$messageLimitAtom = Atom(name: '_SettingsStoreBase.messageLimit'); + + @override + double get messageLimit { + _$messageLimitAtom.reportRead(); + return super.messageLimit; + } + + @override + set messageLimit(double value) { + _$messageLimitAtom.reportWrite(value, super.messageLimit, () { + super.messageLimit = value; + }); + } + @override String toString() { return ''' -videoEnabled: ${videoEnabled} +videoEnabled: ${videoEnabled}, +messageLimit: ${messageLimit} '''; } } diff --git a/lib/screens/channel/chat/chat_store.dart b/lib/screens/channel/chat/chat_store.dart index 6a371104..cf88a3e6 100644 --- a/lib/screens/channel/chat/chat_store.dart +++ b/lib/screens/channel/chat/chat_store.dart @@ -7,6 +7,7 @@ import 'package:frosty/api/irc_api.dart'; import 'package:frosty/api/seventv_api.dart'; import 'package:frosty/api/twitch_api.dart'; import 'package:frosty/core/auth/auth_store.dart'; +import 'package:frosty/core/settings/settings_store.dart'; import 'package:frosty/models/irc.dart'; import 'package:mobx/mobx.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; @@ -38,6 +39,9 @@ abstract class _ChatStoreBase with Store { /// The provided auth store to determine login status, get the token, and use the headers for requests. final AuthStore auth; + /// The provided setting store to account for any user-defined behaviors. + final SettingsStore settings; + /// The logged-in user's appearance in chat. String? _userState; @@ -52,7 +56,11 @@ abstract class _ChatStoreBase with Store { @readonly var _roomState = const ROOMSTATE(); - _ChatStoreBase({required this.auth, required this.channelName}) { + _ChatStoreBase({ + required this.auth, + required this.settings, + required this.channelName, + }) { // Listen for new messages and forward them to the handler. _channel.stream.listen( (data) => _handleIRCData(data.toString()), @@ -170,9 +178,9 @@ abstract class _ChatStoreBase with Store { @action void _deleteAndScrollToEnd() { if (_autoScroll) { - // If there are over 200 messages, remove at least 20. - if (messages.length > 200) { - messages.removeRange(0, messages.length - 180); + // If there are more messages than the limit, remove around 10% of them from the oldest. + if (messages.length > settings.messageLimit && settings.messageLimit != 1000) { + messages.removeRange(0, (messages.length - settings.messageLimit * 0.1).ceil()); } // After the end of the frame, scroll to the bottom of the chat. diff --git a/lib/screens/channel/video_chat.dart b/lib/screens/channel/video_chat.dart index e3e3c086..3d8fadff 100644 --- a/lib/screens/channel/video_chat.dart +++ b/lib/screens/channel/video_chat.dart @@ -68,6 +68,7 @@ class VideoChat extends StatelessWidget { child: Chat( chatStore: ChatStore( auth: context.read(), + settings: context.read(), channelName: userLogin, ), ),