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