I think the text in the pinned message banner is too large in relation
to the default UI font width, so I scaled it down.
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
Parent-pr: 7014
If the split is not 100dp wide, the calculated message height can be
wrong. If the split is larger than 100dp and the message would wrap at
that size, the widget would be too tall. And vice versa for splits
smaller than 100dp.
We do calculate the height in our resize event, but we use the size of
our children. Their resize events are delivered after we're resized. So
we check if we need to resize after we show the widget. This does result
in a small flash where the content is sized incorrectly, but better than
it being incorrect the entire time.
Parent-pr: 7014
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
Split from #6906.
This changes the en-/decoding of channels in the window layout to use
magic-enum for translating between enum and string.
This way, the names are consistent when en-/deconding. And more
importantly, when adding channel types, you should get compiler warnings
in switch statements for uncovered cases.
Tested-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
We have info about the channel that we're derived from in `ChannelView`,
but didn't use it for context menu items. This PR does that.
Closes#7082.
Tested-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Reported-by: Mm2PL <mm2pl+gh@kotmisia.pl>
The plugin UI manually updated itself whenever the user changed the
state by clicking a button (e.g. enabling a plugin). This gets more
complicated when other parts of Chatterino can also load/toggle plugins.
To help with this, I added a signal for the current list of plugins. The
UI also reacts to changes to the enabled plugins (a setting).
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This adds a small section on the use of AI tools/assistants to the
`CONTRIBUTING.md` in hopes that people read it.
Co-authored-by: fourtf <tf.four@gmail.com>
Co-authored-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Co-authored-by: pajlada <rasmus.karlsson@pajlada.com>
`QStringList` has two advantages over `std::vector<QString>` for
settings:
1. Cheap to copy (COW). Setting values need to be copied when they're
accessed, because they're behind a mutex.
2. Better helper functions (see changes).
Co-authored-by: pajlada <rasmus.karlsson@pajlada.com>
Reviewed-by: Mm2PL <mm2pl+gh@kotmisia.pl>
`TwitchChannel` did a few `dynamic_cast`s to get from a weak pointer to
`Channel` back to `TwitchChannel` even though it knows that the pointer
is always to `TwitchChannel`. A similar case was lambdas capturing both
a weak pointer and a `this` pointer. The fix here is to use
`weakFromThis` instead of `weakOf`/`weak_from_this`, both of which
return a `weak_ptr<Channel>` instead of `weak_ptr<TwitchChannel>`,
because they're from the `enable_shared_from_this<Channel>`.
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This is split from #6906 to make it easier to review. The goal is to
move all (de)serialization to WindowDescriptors to make it easier to
change and interact with from the outside.
This removes the internal `loadNodes<T>` and uses `loadFromJSON` for
containers like the other structs, and it moves
`WindowManager::decodeChannel` to the descriptor.
Reviewed-by: mm2pl <mm2pl+gh@kotmisia.pl>
Parent-pr: #6906
This makes them render nicer in chat, but they do not have custom configuration.
Reported-by: JCRouzer29
Reported-by: sando
Reported-by: Wissididom
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
Before, the schema would use the latest schema.
We should specify that we only need the draft-07 schema like the
Chatterino themes. The newer drafts aren't well-supported. For example,
Visual Studio only recently added support for the 2019 and 2020 drafts
(not even sure if that's released yet).
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This adds the `/pin` and `/unpin` commands as well as action in the
context menu of messages.
The `/pin` command can do the following:
- `/pin`: Show the currently pinned message. Intended to be temporary
until we have the PubSub/EventSub topic for this.
- `/pin some message here`: Send a message and pin it for 20 minutes.
- `/pin -d none some message here` (or `/pin -d until-end msg`): Send a
message and pin it until the stream ends.
- `/pin --id abcd123 -d 15m`: Pin a message with ID `abcd123` for 15
min.
- `/pin -h` or `/pin --help`: Show usage.
`/unpin` either takes no arguments or the ID to unpin. When no arguments
are specified, it unpins the currently pinned message.
Having three layers of submenus in the channel view seems a bit weird.
But on the other hand, having multiple `Pin for x minutes` is also
weird.
Closes#5165
Co-authored-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Reported-by: MattIPv4
Reviewed-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
We compile with C++ 23 now and have compiled with 20 and 17 for a while.
These standards support `std::variant` which we use in several places. A
few older places still used `boost::variant`. `std::variant` supersedes
`boost::variant`. It doesn't require an extra dependency and (usually)
has built in support in debuggers.
I also removed includes for `boost/current_function` and
`boost/foreach`. We didn't use them. We still depend on Boost.Variant
through Boost.Signals2, though.
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com
This PR adds `Channel:on_message{_appended, _replaced, s_cleared}`. They
use the same functionality as the display name changed signal and
forward the respective signals in `Channel`.
**They're all synchronous.** This makes the implementation fairly
straight forward, but also a trivial stack overflow. Other than
Chatterino crashing, this shouldn't have any consequences, because the
OS will kill the process. Note that a plugin can already halt Chatterino
by executing an infinite loop, because plugins run in the GUI thread.
Reviewed-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
You can query them and on sets, you can change the images. Note that
sets are value types, so getting an image set in Lua will always refer
to a copy, not a reference.
Images are special, because plugin authors can specify a URL that
Chatterino will load if the image is shown. While the plugin can't see
the response, it still causes Chatterino to issue a request, so
_creating_ images will require the network permission.
Tested-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Tested-by: pajlada <rasmus.karlsson@pajlada.com>
Reviewed-by: Mm2PL <mm2pl+gh@kotmisia.pl>
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This removes the `ContextMap` in favor of individual accessors. This
removes two issues: Slow construction for the map for every message and
lookup into that map.
Some benchmark results:
**Before (5df704af85)**
```
---------------------------------------------------------------------------------------------
Benchmark Time CPU Iterations
---------------------------------------------------------------------------------------------
BM_FilterMessages/nymn_modmessages 3619 us 3606 us 195
BM_FilterMessages/nymn_mod_party 3813 us 3846 us 195
BM_FilterMessages/nymn_len40_or_sub 3591 us 3606 us 195
BM_FilterMessages/nymn_no_sub 3549 us 3526 us 195
BM_FilterMessages/nymn_with_color 3507 us 3523 us 204
BM_FilterMessages/nymn_complex_regex 3965 us 3906 us 172
BM_FilterMessages/nymn_big_or 3758 us 3753 us 179
BM_FilterMessages/nymn_with_color_and_edm_single 3701 us 3593 us 187
BM_FilterMessages/nymn_with_color_and_edm_separate 3591 us 3606 us 195
```
**After**
```
---------------------------------------------------------------------------------------------
Benchmark Time CPU Iterations
---------------------------------------------------------------------------------------------
BM_FilterMessages/nymn_modmessages 159 us 160 us 4480
BM_FilterMessages/nymn_mod_party 212 us 213 us 3446
BM_FilterMessages/nymn_len40_or_sub 76.6 us 76.7 us 8960
BM_FilterMessages/nymn_no_sub 48.3 us 48.7 us 14452
BM_FilterMessages/nymn_with_color 47.2 us 47.6 us 14452
BM_FilterMessages/nymn_complex_regex 442 us 449 us 1600
BM_FilterMessages/nymn_big_or 159 us 160 us 4480
BM_FilterMessages/nymn_with_color_and_edm_single 132 us 132 us 4978
BM_FilterMessages/nymn_with_color_and_edm_separate 138 us 135 us 4978
```
We get a speed-up of about 100x (nymn_no_sub)–9x (nymn_complex_regex).
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This sets `COMPONENT` for all installed files. This way `cmake --install
--component` can be used to select the desired component to install.
Without this, `install` will install the files with any component (i.e.
`cmake --install --component foobar` would install stuff without a
component set).
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
The JSON generation was broken with Clang 22, because the type names
didn't include the namespace (e.g. `std::string` → `string`). We need to
tell Clang to use the fully qualified name. This is possible with
`Type.get_fully_qualified_name` which was added in Clang 21.
This does have the consequence that more types are now fully qualified.
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
When the completer completes, we block all signals. However, we do want
to broadcast a text-changed signal. Since we can't unblock individual
signals, we unconditionally emit a signal after we unblock all signals.
This might come with some side-effects when the user uses certain combinations of settings. I'm merging this in with the hope that these concerns, if any real ones exist, pop up as issues.
Reported-by: 4rneee
Reviewed-by: Mm2PL
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This windows-only command relaunches Chatterino with a new console and some logging rules. In the console, they can see all the logs and copy them for debugging purposes.
Reviewed-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
In filters, we could never instantiate a `Map` (neither users nor the
context map), so the type was essentially unused. This PR removes it.
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
We used to use `QTextCursor`'s definition of a word when right-clicking.
This doesn't necessarily align with ours (e.g.
https://github.com/Chatterino/chatterino2/pull/6821#issuecomment-3941244373).
Furthermore, we didn't consider the character after a word as part of
it. Since Qt does some rounding, it might determine that you clicked on
the character after a word if you clicked on the right side of it. With
this PR, that's fixed.
Here's a visualization of which characters we consider as part of a word
(separated by even/odd):
```
███ █████ ██████ ████
this is some text#I#write in here
█████ █████ ██ ███
```
Fixes#6819
Reported-by: pajlada <rasmus.karlsson@pajlada.com>
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
Parent-pr: https://github.com/chatterino/chatterino2/pull/6446
CMake's `check_ipo_supported` doesn't support all compilers. For
example, clang-cl isn't supported
(https://gitlab.kitware.com/cmake/cmake/-/issues/21635). CMake itself
supports LTO with clang-cl just fine, though. By enabling
`CHATTERINO_FORCE_LTO` and `CHATTERINO_LTO`, users of clang-cl can still
use LTO.
The `targetIndex` (`int`) was compared to `maxIndex` (`size_t`). This
generated a large warning, because it was in a lambda. Since we parse
`targetIndex`, we can parse it as a `size_t`.