9 Commits
Author SHA1 Message Date
Steven Chang 5973f83419 FIX: Preserve push subscription when DND is active on page load (#43243) 2026-09-04 09:34:40 -07:00
Steven Chang 2239124ce4 FIX: Always allow stop impersonation (#43137)
Fixes an edge case where an user can get stuck impersonating another
user without 2FA, when 2FA enforcement is enabled. The impersonation
correctly shows the user can only interact with UI elements for adding
2FA. But this restriction extends to the closing of the impersonation
session.

This commit fixes this by ensuring the DELETE /admin/impersonate
endpoint is always accessible.
2026-09-02 14:08:12 -07:00
Steven ChangandMartin Brennan 07a13cfd47 FEATURE: Add emoji_picker_pinned_groups for pinning groups in the picker (#41881)
This adds the `emoji_picker_pinned_groups` site setting for pinning
emoji groups at the top of the emoji picker list. It accepts both custom
& non custom emoji group names, and can be ordered to preference.

If a custom emoji group is added, and the group is deleted, it will
gracefully ignore the missing group. A validator is included to ensure
the site setting is correct at time of save.

<img width="912" height="228" alt="image"
src="https://github.com/user-attachments/assets/0a832cd9-146d-4d46-b9d1-4e8d4ea3b30d"
/>

<img width="464" height="354" alt="image"
src="https://github.com/user-attachments/assets/2512df0e-035c-457a-bed3-b5d0ac3edc2c"
/>

---------

Co-authored-by: Martin Brennan <martin@discourse.org>
2026-07-22 09:51:15 -07:00
Steven Chang bd3906ce64 FEATURE: Add bulk emoji import/export for admins (#41816)
Previously, admins could only add or delete custom emojis one at a time
through the admin UI, with no way to migrate emoji sets between sites or
manage them in bulk.

This adds a Select to export flow on the emoji list page that packages
selected emojis (images + a CSV manifest) into a downloadable ZIP, and
an Import page that accepts a ZIP, previews the result with per-emoji
conflict resolution (keep existing / use incoming), and applies the
import in a single confirmed transaction.

The generated CSV manifest contains a list of the exported emoji names,
groups, and filenames. The import process relies on this manifest, and
only imports emojis listed on it. Should there be conflicting between
identical names, non matching groups, etc. the admin will be able to see
conflicts on a preview confirmation page.

<img width="1462" height="899" alt="image"
src="https://github.com/user-attachments/assets/b6e45b8b-0081-41bb-88c5-a5525287827e"
/>
<img width="1461" height="852" alt="image"
src="https://github.com/user-attachments/assets/feb9a791-eb70-4c1e-b2f7-495884282aa3"
/>
2026-07-20 15:56:49 -07:00
Steven Chang 39f73fb398 DEV: add clean_up_inactive_users_query modifier for plugins to extend query for inactive users (#41372)
This PR adds Bookmarks and PostActions (likes) to the query for
`CleanUpInactiveUsers` to fetch qualified users.

This PR also allows plugins to modify the `CleanUpInactiveUsers` job
query for selecting which users to destroy. The modifier is given the AR
relation as the argument. Plugins should avoid executing the query, as
it expects a builder style pattern.

Implementation:
```ruby
register_modifier(:clean_up_inactive_users_query) do |relation|
  relation.where.missing(:table_name)
end
```
2026-07-06 09:39:11 -07:00
Steven Chang 71585c9ec9 FIX: remove embed mode horizontal overflow and z-index issue (#39499)
**Before** on small widths, there is an horizontal overflow beyond the
document width. This is caused by the `.read-state` indicator being
placed in the `#main-outlet-wrapper` padding in regular mode. In embed
mode, the wrapper does not have a padding, and thus the indicator forces
the overflow.

There is also an issue where the topic progress overlaps over the docked
composer.

Screen recording of blog.discourse.org:


https://github.com/user-attachments/assets/ffabbef8-beb5-495a-b383-082bb165958c

<details>
<summary>Before</summary>


https://github.com/user-attachments/assets/0cbfcd64-ddaa-48de-975c-ddcf14f25ff6

</details>

**This commit** adjusts the `post-infos` div to the left a bit so that
the `.read-state` indicator can still be within the window frame while
keeping the timestamp close to the right.

Also updates the z-index of the docked composer in embed mode.


https://github.com/user-attachments/assets/a4578057-46e5-440e-9684-18f83c536a17
2026-04-24 08:06:54 -07:00
Steven Chang c9aee79707 FEAT: add copy button to code blocks in chat (#38332)
Adds CodeblockButtons functionality to chat messages, include copy and
fullscreen. Adds the hidden `chat_show_copy_button_on_codeblocks` site
setting following the pattern for `show_copy_button_on_codeblocks`

<img width="413" height="366" alt="image"
src="https://github.com/user-attachments/assets/0f5bffc7-4040-41c8-a6d6-ae1e446bf845"
/>
2026-03-06 13:15:31 -08:00
Steven Chang e89cf8ee4e FIX: can't paste text when upload authorized extensions is empty (#36601)
Fixes an issue where if a forum has disabled users from uploading media
in posts, rich text editor mistakenly also prevents all pastes including
plain text.

Affects forums where`authorized_extensions` is empty, and non-staff
users using the rich text editor.
2025-12-10 16:58:42 -08:00
Steven Chang 0f252b6676 UX: Improve template filtering with usage count and preserving tags (#35881)
On sites with a large amount of templates, the default display and
filter can become ineffective. By default, templates are ordered by
alphabetical title order. If filtered by keyword, the plugin does a
simple scoring based on whether the text is in the title (+2) or in the
content (+1), then by alphabetical title order. This PR updates it to
use the `usages` count, so the new priority of ordering is by score >
usage > title.

Also adds a localstorage for the selected tag used to filter the
template list. The tag field will be pre-populated with the last used
filtered tag if available.

Renames hint from "Filter by title..." to "Filter by keyword..." to
reflect actual filtering behavior.
2025-11-14 09:01:42 -08:00