1 #pragma once
2 
3 #include <pajlada/settings/setting.hpp>
4 #include <pajlada/settings/settinglistener.hpp>
5 
6 #include "BaseSettings.hpp"
7 #include "common/Channel.hpp"
8 #include "common/SignalVector.hpp"
9 #include "controllers/filters/FilterRecord.hpp"
10 #include "controllers/highlights/HighlightBadge.hpp"
11 #include "controllers/highlights/HighlightPhrase.hpp"
12 #include "controllers/moderationactions/ModerationAction.hpp"
13 #include "controllers/nicknames/Nickname.hpp"
14 #include "singletons/Toasts.hpp"
15 #include "util/StreamerMode.hpp"
16 #include "widgets/Notebook.hpp"
17 
18 using TimeoutButton = std::pair<QString, int>;
19 
20 namespace chatterino {
21 
22 class HighlightPhrase;
23 class HighlightBlacklistUser;
24 class IgnorePhrase;
25 class TaggedUser;
26 class FilterRecord;
27 class Nickname;
28 
29 /// Settings which are availlable for reading on all threads.
30 class ConcurrentSettings
31 {
32 public:
33     ConcurrentSettings();
34 
35     SignalVector<HighlightPhrase> &highlightedMessages;
36     SignalVector<HighlightPhrase> &highlightedUsers;
37     SignalVector<HighlightBadge> &highlightedBadges;
38     SignalVector<HighlightBlacklistUser> &blacklistedUsers;
39     SignalVector<IgnorePhrase> &ignoredMessages;
40     SignalVector<QString> &mutedChannels;
41     SignalVector<FilterRecordPtr> &filterRecords;
42     SignalVector<Nickname> &nicknames;
43     //SignalVector<TaggedUser> &taggedUsers;
44     SignalVector<ModerationAction> &moderationActions;
45 
46     bool isHighlightedUser(const QString &username);
47     bool isBlacklistedUser(const QString &username);
48     bool isMutedChannel(const QString &channelName);
49     bool toggleMutedChannel(const QString &channelName);
50 
51 private:
52     void mute(const QString &channelName);
53     void unmute(const QString &channelName);
54 };
55 
56 ConcurrentSettings &getCSettings();
57 
58 enum UsernameDisplayMode : int {
59     Username = 1,                  // Username
60     LocalizedName = 2,             // Localized name
61     UsernameAndLocalizedName = 3,  // Username (Localized name)
62 };
63 /// Settings which are availlable for reading and writing on the gui thread.
64 // These settings are still accessed concurrently in the code but it is bad practice.
65 class Settings : public ABSettings, public ConcurrentSettings
66 {
67     static Settings *instance_;
68 
69 public:
70     Settings(const QString &settingsDirectory);
71 
72     static Settings &instance();
73 
74     /// Appearance
75     BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true};
76     BoolSetting animationsWhenFocused = {
77         "/appearance/enableAnimationsWhenFocused", false};
78     QStringSetting timestampFormat = {"/appearance/messages/timestampFormat",
79                                       "h:mm"};
80     BoolSetting showLastMessageIndicator = {
81         "/appearance/messages/showLastMessageIndicator", false};
82     EnumSetting<Qt::BrushStyle> lastMessagePattern = {
83         "/appearance/messages/lastMessagePattern", Qt::SolidPattern};
84     QStringSetting lastMessageColor = {"/appearance/messages/lastMessageColor",
85                                        "#7f2026"};
86     BoolSetting showEmptyInput = {"/appearance/showEmptyInputBox", true};
87     BoolSetting showMessageLength = {"/appearance/messages/showMessageLength",
88                                      false};
89     BoolSetting separateMessages = {"/appearance/messages/separateMessages",
90                                     false};
91     BoolSetting compactEmotes = {"/appearance/messages/compactEmotes", true};
92     BoolSetting hideModerated = {"/appearance/messages/hideModerated", false};
93     BoolSetting hideModerationActions = {
94         "/appearance/messages/hideModerationActions", false};
95     BoolSetting hideDeletionActions = {
96         "/appearance/messages/hideDeletionActions", false};
97     BoolSetting colorizeNicknames = {"/appearance/messages/colorizeNicknames",
98                                      true};
99     EnumSetting<UsernameDisplayMode> usernameDisplayMode = {
100         "/appearance/messages/usernameDisplayMode",
101         UsernameDisplayMode::UsernameAndLocalizedName};
102 
103     IntSetting tabDirection = {"/appearance/tabDirection",
104                                NotebookTabDirection::Horizontal};
105 
106     //    BoolSetting collapseLongMessages =
107     //    {"/appearance/messages/collapseLongMessages", false};
108     IntSetting collpseMessagesMinLines = {
109         "/appearance/messages/collapseMessagesMinLines", 0};
110     BoolSetting alternateMessages = {
111         "/appearance/messages/alternateMessageBackground", false};
112     FloatSetting boldScale = {"/appearance/boldScale", 63};
113     BoolSetting showTabCloseButton = {"/appearance/showTabCloseButton", true};
114     BoolSetting showTabLive = {"/appearance/showTabLiveButton", true};
115     BoolSetting hidePreferencesButton = {"/appearance/hidePreferencesButton",
116                                          false};
117     BoolSetting hideUserButton = {"/appearance/hideUserButton", false};
118     BoolSetting enableSmoothScrolling = {"/appearance/smoothScrolling", true};
119     BoolSetting enableSmoothScrollingNewMessages = {
120         "/appearance/smoothScrollingNewMessages", false};
121     BoolSetting boldUsernames = {"/appearance/messages/boldUsernames", true};
122     BoolSetting colorUsernames = {"/appearance/messages/colorUsernames", true};
123     BoolSetting findAllUsernames = {"/appearance/messages/findAllUsernames",
124                                     false};
125     // BoolSetting customizable splitheader
126     BoolSetting headerViewerCount = {"/appearance/splitheader/showViewerCount",
127                                      false};
128     BoolSetting headerStreamTitle = {"/appearance/splitheader/showTitle",
129                                      false};
130     BoolSetting headerGame = {"/appearance/splitheader/showGame", false};
131     BoolSetting headerUptime = {"/appearance/splitheader/showUptime", false};
132     FloatSetting customThemeMultiplier = {"/appearance/customThemeMultiplier",
133                                           -0.5f};
134     // BoolSetting useCustomWindowFrame = {"/appearance/useCustomWindowFrame",
135     // false};
136 
137     // Badges
138     BoolSetting showBadgesGlobalAuthority = {
139         "/appearance/badges/GlobalAuthority", true};
140     BoolSetting showBadgesPredictions = {"/appearance/badges/predictions",
141                                          true};
142     BoolSetting showBadgesChannelAuthority = {
143         "/appearance/badges/ChannelAuthority", true};
144     BoolSetting showBadgesSubscription = {"/appearance/badges/subscription",
145                                           true};
146     BoolSetting showBadgesVanity = {"/appearance/badges/vanity", true};
147     BoolSetting showBadgesChatterino = {"/appearance/badges/chatterino", true};
148     BoolSetting showBadgesFfz = {"/appearance/badges/ffz", true};
149     BoolSetting useCustomFfzModeratorBadges = {
150         "/appearance/badges/useCustomFfzModeratorBadges", true};
151     BoolSetting useCustomFfzVipBadges = {
152         "/appearance/badges/useCustomFfzVipBadges", true};
153 
154     /// Behaviour
155     BoolSetting allowDuplicateMessages = {"/behaviour/allowDuplicateMessages",
156                                           true};
157     BoolSetting mentionUsersWithAt = {"/behaviour/mentionUsersWithAt", false};
158     BoolSetting showJoins = {"/behaviour/showJoins", false};
159     BoolSetting showParts = {"/behaviour/showParts", false};
160     FloatSetting mouseScrollMultiplier = {"/behaviour/mouseScrollMultiplier",
161                                           1.0};
162     BoolSetting autoCloseUserPopup = {"/behaviour/autoCloseUserPopup", true};
163     // BoolSetting twitchSeperateWriteConnection =
164     // {"/behaviour/twitchSeperateWriteConnection", false};
165 
166     // Auto-completion
167     BoolSetting onlyFetchChattersForSmallerStreamers = {
168         "/behaviour/autocompletion/onlyFetchChattersForSmallerStreamers", true};
169     IntSetting smallStreamerLimit = {
170         "/behaviour/autocompletion/smallStreamerLimit", 1000};
171     BoolSetting prefixOnlyEmoteCompletion = {
172         "/behaviour/autocompletion/prefixOnlyCompletion", true};
173     BoolSetting userCompletionOnlyWithAt = {
174         "/behaviour/autocompletion/userCompletionOnlyWithAt", false};
175     BoolSetting emoteCompletionWithColon = {
176         "/behaviour/autocompletion/emoteCompletionWithColon", true};
177     BoolSetting showUsernameCompletionMenu = {
178         "/behaviour/autocompletion/showUsernameCompletionMenu", true};
179 
180     FloatSetting pauseOnHoverDuration = {"/behaviour/pauseOnHoverDuration", 0};
181     EnumSetting<Qt::KeyboardModifier> pauseChatModifier = {
182         "/behaviour/pauseChatModifier", Qt::KeyboardModifier::NoModifier};
183     BoolSetting autorun = {"/behaviour/autorun", false};
184     BoolSetting mentionUsersWithComma = {"/behaviour/mentionUsersWithComma",
185                                          true};
186 
187     /// Commands
188     BoolSetting allowCommandsAtEnd = {"/commands/allowCommandsAtEnd", false};
189 
190     /// Emotes
191     BoolSetting scaleEmotesByLineHeight = {"/emotes/scaleEmotesByLineHeight",
192                                            false};
193     BoolSetting enableEmoteImages = {"/emotes/enableEmoteImages", true};
194     BoolSetting animateEmotes = {"/emotes/enableGifAnimations", true};
195     FloatSetting emoteScale = {"/emotes/scale", 1.f};
196 
197     QStringSetting emojiSet = {"/emotes/emojiSet", "Twitter"};
198 
199     BoolSetting stackBits = {"/emotes/stackBits", false};
200     BoolSetting removeSpacesBetweenEmotes = {
201         "/emotes/removeSpacesBetweenEmotes", false};
202 
203     /// Links
204     BoolSetting linksDoubleClickOnly = {"/links/doubleClickToOpen", false};
205     BoolSetting linkInfoTooltip = {"/links/linkInfoTooltip", false};
206     IntSetting thumbnailSize = {"/appearance/thumbnailSize", 0};
207     IntSetting thumbnailSizeStream = {"/appearance/thumbnailSizeStream", 2};
208     BoolSetting unshortLinks = {"/links/unshortLinks", false};
209     BoolSetting lowercaseDomains = {"/links/linkLowercase", true};
210 
211     /// Streamer Mode
212     EnumSetting<StreamerModeSetting> enableStreamerMode = {
213         "/streamerMode/enabled", StreamerModeSetting::DetectObs};
214     BoolSetting streamerModeHideUsercardAvatars = {
215         "/streamerMode/hideUsercardAvatars", true};
216     BoolSetting streamerModeHideLinkThumbnails = {
217         "/streamerMode/hideLinkThumbnails", true};
218     BoolSetting streamerModeHideViewerCountAndDuration = {
219         "/streamerMode/hideViewerCountAndDuration", false};
220     BoolSetting streamerModeMuteMentions = {"/streamerMode/muteMentions", true};
221     BoolSetting streamerModeSuppressLiveNotifications = {
222         "/streamerMode/supressLiveNotifications", false};
223 
224     /// Ignored Phrases
225     QStringSetting ignoredPhraseReplace = {"/ignore/ignoredPhraseReplace",
226                                            "***"};
227 
228     /// Blocked Users
229     BoolSetting enableTwitchBlockedUsers = {"/ignore/enableTwitchBlockedUsers",
230                                             true};
231     IntSetting showBlockedUsersMessages = {"/ignore/showBlockedUsers", 0};
232 
233     /// Moderation
234     QStringSetting timeoutAction = {"/moderation/timeoutAction", "Disable"};
235     IntSetting timeoutStackStyle = {
236         "/moderation/timeoutStackStyle",
237         static_cast<int>(TimeoutStackStyle::Default)};
238 
239     /// Highlighting
240     //    BoolSetting enableHighlights = {"/highlighting/enabled", true};
241     BoolSetting customHighlightSound = {"/highlighting/useCustomSound", false};
242 
243     BoolSetting enableSelfHighlight = {
244         "/highlighting/selfHighlight/nameIsHighlightKeyword", true};
245     BoolSetting showSelfHighlightInMentions = {
246         "/highlighting/selfHighlight/showSelfHighlightInMentions", true};
247     BoolSetting enableSelfHighlightSound = {
248         "/highlighting/selfHighlight/enableSound", true};
249     BoolSetting enableSelfHighlightTaskbar = {
250         "/highlighting/selfHighlight/enableTaskbarFlashing", true};
251     QStringSetting selfHighlightSoundUrl = {
252         "/highlighting/selfHighlightSoundUrl", ""};
253     QStringSetting selfHighlightColor = {"/highlighting/selfHighlightColor",
254                                          ""};
255 
256     BoolSetting enableWhisperHighlight = {
257         "/highlighting/whisperHighlight/whispersHighlighted", true};
258     BoolSetting enableWhisperHighlightSound = {
259         "/highlighting/whisperHighlight/enableSound", false};
260     BoolSetting enableWhisperHighlightTaskbar = {
261         "/highlighting/whisperHighlight/enableTaskbarFlashing", false};
262     QStringSetting whisperHighlightSoundUrl = {
263         "/highlighting/whisperHighlightSoundUrl", ""};
264     QStringSetting whisperHighlightColor = {
265         "/highlighting/whisperHighlightColor", ""};
266 
267     BoolSetting enableRedeemedHighlight = {
268         "/highlighting/redeemedHighlight/highlighted", true};
269     //    BoolSetting enableRedeemedHighlightSound = {
270     //        "/highlighting/redeemedHighlight/enableSound", false};
271     //    BoolSetting enableRedeemedHighlightTaskbar = {
272     //        "/highlighting/redeemedHighlight/enableTaskbarFlashing", false};
273     QStringSetting redeemedHighlightSoundUrl = {
274         "/highlighting/redeemedHighlightSoundUrl", ""};
275     QStringSetting redeemedHighlightColor = {
276         "/highlighting/redeemedHighlightColor", ""};
277 
278     BoolSetting enableSubHighlight = {
279         "/highlighting/subHighlight/subsHighlighted", true};
280     BoolSetting enableSubHighlightSound = {
281         "/highlighting/subHighlight/enableSound", false};
282     BoolSetting enableSubHighlightTaskbar = {
283         "/highlighting/subHighlight/enableTaskbarFlashing", false};
284     QStringSetting subHighlightSoundUrl = {"/highlighting/subHighlightSoundUrl",
285                                            ""};
286     QStringSetting subHighlightColor = {"/highlighting/subHighlightColor", ""};
287 
288     QStringSetting highlightColor = {"/highlighting/color", ""};
289 
290     BoolSetting longAlerts = {"/highlighting/alerts", false};
291 
292     BoolSetting highlightMentions = {"/highlighting/mentions", true};
293 
294     /// Filtering
295     BoolSetting excludeUserMessagesFromFilter = {
296         "/filtering/excludeUserMessages", false};
297 
298     /// Logging
299     BoolSetting enableLogging = {"/logging/enabled", false};
300 
301     QStringSetting logPath = {"/logging/path", ""};
302 
303     QStringSetting pathHighlightSound = {"/highlighting/highlightSoundPath",
304                                          ""};
305 
306     BoolSetting highlightAlwaysPlaySound = {"/highlighting/alwaysPlaySound",
307                                             false};
308 
309     BoolSetting inlineWhispers = {"/whispers/enableInlineWhispers", true};
310     BoolSetting highlightInlineWhispers = {"/whispers/highlightInlineWhispers",
311                                            false};
312 
313     /// Notifications
314     BoolSetting notificationFlashTaskbar = {"/notifications/enableFlashTaskbar",
315                                             false};
316     BoolSetting notificationPlaySound = {"/notifications/enablePlaySound",
317                                          false};
318     BoolSetting notificationCustomSound = {"/notifications/customPlaySound",
319                                            false};
320     QStringSetting notificationPathSound = {"/notifications/highlightSoundPath",
321                                             "qrc:/sounds/ping3.wav"};
322     BoolSetting notificationOnAnyChannel = {"/notifications/onAnyChannel",
323                                             false};
324 
325     BoolSetting notificationToast = {"/notifications/enableToast", false};
326     IntSetting openFromToast = {"/notifications/openFromToast",
327                                 static_cast<int>(ToastReaction::OpenInBrowser)};
328 
329     /// External tools
330     // Streamlink
331     BoolSetting streamlinkUseCustomPath = {"/external/streamlink/useCustomPath",
332                                            false};
333     QStringSetting streamlinkPath = {"/external/streamlink/customPath", ""};
334     QStringSetting preferredQuality = {"/external/streamlink/quality",
335                                        "Choose"};
336     QStringSetting streamlinkOpts = {"/external/streamlink/options", ""};
337 
338     // Custom URI Scheme
339     QStringSetting customURIScheme = {"/external/urischeme"};
340 
341     // Image Uploader
342     BoolSetting imageUploaderEnabled = {"/external/imageUploader/enabled",
343                                         false};
344     QStringSetting imageUploaderUrl = {"/external/imageUploader/url", ""};
345     QStringSetting imageUploaderFormField = {
346         "/external/imageUploader/formField", ""};
347     QStringSetting imageUploaderHeaders = {"/external/imageUploader/headers",
348                                            ""};
349     QStringSetting imageUploaderLink = {"/external/imageUploader/link", ""};
350     QStringSetting imageUploaderDeletionLink = {
351         "/external/imageUploader/deletionLink", ""};
352 
353     /// Misc
354     BoolSetting betaUpdates = {"/misc/beta", false};
355 #ifdef Q_OS_LINUX
356     BoolSetting useKeyring = {"/misc/useKeyring", true};
357 #endif
358     BoolSetting enableExperimentalIrc = {"/misc/experimentalIrc", false};
359 
360     IntSetting startUpNotification = {"/misc/startUpNotification", 0};
361     QStringSetting currentVersion = {"/misc/currentVersion", ""};
362 
363     BoolSetting loadTwitchMessageHistoryOnConnect = {
364         "/misc/twitch/loadMessageHistoryOnConnect", true};
365     IntSetting twitchMessageHistoryLimit = {
366         "/misc/twitch/messageHistoryLimit",
367         800,
368     };
369 
370     IntSetting emotesTooltipPreview = {"/misc/emotesTooltipPreview", 1};
371     BoolSetting openLinksIncognito = {"/misc/openLinksIncognito", 0};
372 
373     QStringSetting cachePath = {"/cache/path", ""};
374     BoolSetting restartOnCrash = {"/misc/restartOnCrash", false};
375     BoolSetting attachExtensionToAnyProcess = {
376         "/misc/attachExtensionToAnyProcess", false};
377     BoolSetting askOnImageUpload = {"/misc/askOnImageUpload", true};
378     BoolSetting informOnTabVisibilityToggle = {"/misc/askOnTabVisibilityToggle",
379                                                true};
380 
381     /// Debug
382     BoolSetting showUnhandledIrcMessages = {"/debug/showUnhandledIrcMessages",
383                                             false};
384 
385     /// UI
386     // Purely QOL settings are here (like last item in a list).
387     IntSetting lastSelectChannelTab = {"/ui/lastSelectChannelTab", 0};
388     IntSetting lastSelectIrcConn = {"/ui/lastSelectIrcConn", 0};
389 
390     // Similarity
391     BoolSetting similarityEnabled = {"/similarity/similarityEnabled", false};
392     BoolSetting colorSimilarDisabled = {"/similarity/colorSimilarDisabled",
393                                         true};
394     BoolSetting hideSimilar = {"/similarity/hideSimilar", false};
395     BoolSetting hideSimilarMyself = {"/similarity/hideSimilarMyself", false};
396     BoolSetting shownSimilarTriggerHighlights = {
397         "/similarity/shownSimilarTriggerHighlights", false};
398     FloatSetting similarityPercentage = {"/similarity/similarityPercentage",
399                                          0.9f};
400     IntSetting hideSimilarMaxDelay = {"/similarity/hideSimilarMaxDelay", 5};
401     IntSetting hideSimilarMaxMessagesToCheck = {
402         "/similarity/hideSimilarMaxMessagesToCheck", 3};
403 
404     /// Timeout buttons
405 
406     ChatterinoSetting<std::vector<TimeoutButton>> timeoutButtons = {
407         "/timeouts/timeoutButtons",
408         {{"s", 1},
409          {"s", 30},
410          {"m", 1},
411          {"m", 5},
412          {"m", 30},
413          {"h", 1},
414          {"d", 1},
415          {"w", 1}}};
416 
417 private:
418     void updateModerationActions();
419 };
420 
421 }  // namespace chatterino
422 
423 #ifdef CHATTERINO
424 #    include "singletons/Settings.hpp"
425 #endif
426