495 Commits
Author SHA1 Message Date
Discourse Translator Bot c77dfaf5a6 I18N: Update translations (#42907) 2026-09-02 10:28:40 +02:00
chapoi 00a249da13 UX: Update preview for Composer Redesign UC (#42876) 2026-08-25 16:24:13 +02:00
Jordan Vidrine f6cd2193e6 DEV: post type dropdown cleanup (#42589) 2026-08-17 16:09:55 -05:00
Discourse Translator Bot c4c9ab1de6 I18N: Update translations (#42577) 2026-08-13 10:30:16 +02:00
chapoi 7795493f07 DEV: Move composer redesign to experimental (#42358) 2026-08-06 10:22:04 +02: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
David Battersby 6d51f7b4f8 DEV: remove enable gifs upcoming change metadata (#41798)
We want to allow site admins to enable or disable the GIFs component, so
we will retire this setting at `stable` and remove the upcoming change
metadata. This setting will now be visible within the GIFs panel under
the Appearance section in the admin sidebar.

Intentionally keeping the migration rake task
(`lib/tasks/migrate_discourse_gifs_to_core.rake`) for a few more weeks
to account for any self-hosters who may not have migrated yet. We will
follow up in a few weeks to remove it entirely.
2026-07-20 12:30:00 +04:00
chapoiandMartin Brennan a7bcfad6bb UX: Composer redesign (#41781)
Introduces a new composer redesign behind the `enable_composer_redesign`
upcoming
change, which is `conceptual` for now and thus not shown to admins.

This change modernises the composer UI further, moving the toolbar to
the
bottom and trying an experimental approach to create more space for
writing on mobile

**Desktop**

<img width="781" height="685" alt="image"
src="https://github.com/user-attachments/assets/461e39f1-4409-4f8b-96b9-78a0c7a6877a"
/>
<img width="1490" height="681" alt="image"
src="https://github.com/user-attachments/assets/c1422bc6-c0e2-4d75-8110-d24c507bbc4c"
/>


**Mobile**

<img width="373" height="858" alt="image"
src="https://github.com/user-attachments/assets/d3a3048b-a532-4151-b7f4-efac3b7ebe25"
/>

<img width="376" height="854" alt="image"
src="https://github.com/user-attachments/assets/2a42503a-de55-4684-8edd-789c54eccd69"
/>

---------

Co-authored-by: Martin Brennan <martin@discourse.org>
2026-07-20 17:56:48 +10:00
Keegan George abe5700838 FEATURE: Allow inviting new users directly as admins (#41748)
**Previously**, getting a second admin onto a site took many steps:
create an invite, wait for the person to sign up, find their profile,
grant admin, and confirm via email.

**In this update**, a redesigned invite modal (gated behind the
`enable_admin_invites` upcoming change) lets admins invite someone as an
admin by email in one step. The invitee becomes a moderator on signup
and an admin once the inviter confirms via the existing admin
confirmation email. The admin onboarding panel's "Invite collaborators"
step now opens this flow with the admin option preselected.

| Invite members | Advanced options | Email delivery |
| --- | --- | --- |
|
![invite-members.png](https://github.com/discourse/discourse/releases/download/_gh-attach-assets/invite-members.png)
|
![invite-members-advanced.png](https://github.com/discourse/discourse/releases/download/_gh-attach-assets/invite-members-advanced.png)
|
![invite-members-email.png](https://github.com/discourse/discourse/releases/download/_gh-attach-assets/invite-members-email.png)
|

| Invite admins | Advanced options | Invite sent |
| --- | --- | --- |
|
![invite-admins.png](https://github.com/discourse/discourse/releases/download/_gh-attach-assets/invite-admins.png)
|
![invite-admins-advanced.png](https://github.com/discourse/discourse/releases/download/_gh-attach-assets/invite-admins-advanced.png)
|
![admin-invite-sent.png](https://github.com/discourse/discourse/releases/download/_gh-attach-assets/admin-invite-sent.png)
|

| Link created | Email invitation sent | Onboarding panel |
| --- | --- | --- |
|
![invite-created.png](https://github.com/discourse/discourse/releases/download/_gh-attach-assets/invite-created.png)
|
![invitation-sent.png](https://github.com/discourse/discourse/releases/download/_gh-attach-assets/invitation-sent.png)
|
![onboarding-banner.png](https://github.com/discourse/discourse/releases/download/_gh-attach-assets/onboarding-banner.png)
|
2026-07-16 14:59:24 -07:00
David Battersby 0a9a4d3820 UX: gifs modal style improvements (#41766)
Fixes overflow issues causing additional scrollbars, alignment and
padding improvements for search field and loading spinners. Also adds a
dark mode logo for KLIPY.

### How it looks (light)

<img width="700" alt="GIFs search modal (light mode)"
src="https://github.com/user-attachments/assets/32bc61ba-7e4a-4b26-b218-9ccfd0340695"
/>


### How it looks (dark)

<img width="700" alt="GIFs search modal (dark mode)"
src="https://github.com/user-attachments/assets/ac4f55d8-16f3-4319-8a17-653b48711e97"
/>
2026-07-16 14:56:55 +04:00
Keegan George 5e8d72c85e DEV: Introduce enable_local_logins_via_code as an alpha upcoming change (#41624)
**Previously**, login with email codes was gated behind a hidden site
setting, invisible to admins and checked via raw `SiteSetting` reads
that would ignore upcoming-change auto-promotion.

**In this update**, registered the setting as an alpha upcoming change
(with preview image and learn-more link), moved server-side checks to
`UpcomingChanges`, and hid the change on sites where it cannot be
enabled.
2026-07-10 10:19:27 -07:00
David Battersby f675e4d6a1 UX: add Klipy branding to gifs picker (#41501)
Update the GIFs picker to show Klipy logo to meet branding requirements
for using the service.

We conditionally showed this in the original theme component but it was
missed when porting the component to core.
2026-07-07 10:31:30 +04:00
David Taylor a32f09021f DEV: Refactor worker and WASM loading for media-optimization-worker (#40793)
- Add new `discourse/app/workers/...` directory

- Adds a custom rolldown plugin which can create a dynamic entrypoint
and return a digested URL for it

- Update media-optimization service to use this new rolldown interface,
and launch the worker via a `blob:`

- Updates media-optimization to use type:module worker, and improve
boot-error-handling strategy

This is an improvement for a few reasons:

1. We can drop all the manual entrypoint/manifest/ruby config which was
used to obtain the media-optimization bundle URL

2. We don't need to serve the worker from the (undigested/uncached)
`public/` directory on the forum domain. Instead we just generate a
one-liner worker entrypoint and create a blob from it

3. Since we're launching from a blob, the worker inherits the CSP of the
host document, which is a nice defense-in-depth improvement
2026-06-12 09:18:32 +01:00
David Battersby 031e17658c DEV: move discourse gifs to core (#40162)
Moves the theme component from Discourse Gifs and brings it into core as
an upcoming change. This PR also brings gifs under a single provider
(Klipy).
2026-06-10 11:35:44 +04:00
Martin Brennan c85b12934e FEATURE: Add upcoming change for unified new view (#40631)
Moves the `experimental_new_new_view_groups` setting to an
upcoming change called "Enable unified new" (`enable_unified_new`)

This will aim to introduce the unified new view topic list to
all sites as the permanent default experience.
2026-06-09 11:34:22 +10:00
Jordan Vidrine 938980ecb7 WIP: New "Post Type" dropdown in composer header (#38068) 2026-06-01 14:40:36 -05:00
Discourse Translator Bot adcc98750d I18N: Update translations (#40440) 2026-06-01 21:00:36 +02:00
9527868295 DEV: Replace JS build system with Rolldown (#35963)
This replaces the old ember-cli build with a modern Rolldown build. In
local testing, this provides an 80% improvement in build times, while
remaining 100% backwards compatible for themes and plugins.

As part of this move, we have decided to stop using a proxy in front of
Discourse for development. Development should now be done directly
against the Rails server.

`bin/ember-cli -u` has been replaced with `bin/dev`. This will launch
Rails on `:3000`, and will run the rolldown build in the background. Log
output from both processes will be shown with an appropriate prefix. You
should visit `:3000` in your browser. `:4200` will no longer serve
anything.

To help with migration, `bin/ember-cli` is now a backwards-compatible
shim. It will print help information, and will launch a lightweight
server on `:4200` with instructions to move to `:3000`.

If you prefer to launch Rails and the JS build as separate commands, you
can still do that. Rails boot commands are unchanged, and the rolldown
development builder can be run using `bin/dev --only ember`.

https://meta.discourse.org/t/403908

---------

Co-authored-by: Jarek Radosz <jarek@cvx.dev>
Co-authored-by: Chris Manson <chris@manson.ie>
2026-05-29 11:11:55 +01:00
David Battersby 01e81ffe73 DEV: add post reaction menu metadata to upcoming change (#40062)
Adds a learn more link which points to the feature request, along with a
preview image of the change.
2026-05-15 13:16:18 +04:00
Rafael dos Santos SilvaandClaude Opus 4.6 e5df5fe10b FEATURE: Client-side JXL, HEIC, and animated GIF conversion (#39014)
## Summary

- Extends client-side image optimization to convert **JXL → JPEG**,
**HEIC → JPEG**, and **animated GIF → animated WEBP** using jSquash WASM
packages before upload
- Transparent JXL/HEIC images are converted to **WEBP** instead of JPEG,
so transparency is preserved (WEBP compresses much better than PNG for
this case)
- Gated as an **upcoming change** via
`composer_media_optimization_image_convert_enabled` (experimental,
`feature,all_members`, opt-in per group through the upcoming changes
admin UI)
- Sends raw file bytes to Web Worker for formats browsers can't decode
natively (JXL, HEIC), with new `"convert"` and `"convertAnimated"`
worker message types
- Adds JXL to `authorized_extensions` and `supported_images`; adds
HEIC/HEIF to `supported_images` for consistency
- Skips GIF→WEBP when output is larger than input
- Falls back to filename when MIME type is missing (browsers may not
recognize JXL/HEIC)

### Note on jSquash packages

This depends on Discourse-scoped forks of the jSquash packages
(`@discourse/jxl`, `@discourse/heic`, `@discourse/webp`,
`@discourse/gif`, `@discourse/jpeg`, `@discourse/resize`). The following
upstream PRs would let us move back to the canonical `@jsquash/*`
packages, but the upstream maintainer is currently unresponsive:

- https://github.com/jamsinclair/jSquash/pull/101 (`@jsquash/heic`)
- https://github.com/jamsinclair/jSquash/pull/103 (`@jsquash/webp`
animated support)
- https://github.com/jamsinclair/jSquash/pull/104 (`@jsquash/gif`)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 12:02:50 -03:00
Rafael dos Santos Silva 2834cc7955 FIX: Duplicate notifications when mentioned in chat (#39670)
Previously, building the web push "Reply" action payload raised because
`inline_reply.png` lived under `public/images/` where Propshaft can't
resolve it, so `Jobs::Chat::NotifyMentioned` retried after
`create_notification!` and inflated the bell with duplicate rows.

This change moves the icon into `app/assets/images/push-notifications/`
and wraps the action builder in a `rescue` so any future payload failure
logs and returns `{}` instead of stranding the job.

A post-deploy migration sweeps the duplicate `chat_mention`
`Notification` rows (and their `chat_mention_notifications` join
entries) created during the deploy window — keeping the oldest row per
`(user_id, data)` group and merging the read state forward.
2026-04-30 14:52:39 -03:00
Martin Brennan dc65289cd5 UX: Permanently delete followup (#39339)
Followup to d56fca0fd7

Improve easter egg :D
2026-04-20 08:26:55 +10:00
Rafael dos Santos Silva ce3b528204 FIX: Use iframe style.height for embed resize messages (#39321)
## Summary

When Discourse is loaded in full app embed mode with `dynamicHeight:
true`, the iframe was not resizing in production despite
`discourse-resize` messages arriving correctly.

The full app path sets `iframe.style.height` as an inline style for the
initial height. Inline styles always win over the `height` HTML
attribute, so our resize handler — which set `iframe.height = ...` — had
no visible effect.

This changes the resize handler to set `iframe.style.height` so it
actually overrides the inline style. This also works for the standard
(non-full-app) embed path since no inline style is set there initially.

## Test plan

- [ ] Full app embed with `dynamicHeight: true` — verify iframe height
updates as content loads
- [ ] Standard (non-full-app) embed — verify iframe still resizes
correctly
- [ ] CSS `max-height` on the iframe still wins (inline `height` doesn't
override `max-height`)
2026-04-16 15:17:06 -03:00
Rafael dos Santos Silva 45b48524dc PERF: Use native iframe lazy loading for full app embeds (#39320)
## Summary

Replaces the `IntersectionObserver` implementation from #39299 with the
native `loading="lazy"` attribute on the iframe. All supported browsers
(Chrome 77+, Safari 16.4+, Firefox 121+) handle this, and the
browser-determined threshold adapts to connection speed — generally
smarter than a fixed pixel margin.

- Drops ~20 lines of JS and the feature-detection fallback
- Removes the `lazyLoadMargin` option (no longer configurable — browser
decides)
- `lazyLoad: false` still opts out by setting `loading="eager"`
- Admin embedding snippet updated to drop the `lazyLoadMargin` line

Shipped two days ago in #39299, so no external consumers should depend
on `lazyLoadMargin` yet.

## Test plan

- [ ] Full app embed below the fold — verify iframe defers loading until
scrolling near it
- [ ] Full app embed above the fold — verify it loads immediately
- [ ] `lazyLoad: false` — verify immediate loading, same as pre-#39299
behavior
- [ ] Standard (non-full-app) embed — verify unchanged behavior
2026-04-16 14:41:03 -03:00
Rafael dos Santos Silva 933bf50f0a UX: Support dynamic iframe height for full app embed mode (#39297)
## Summary

- Add opt-in `dynamicHeight` option for full app embeds that resizes the
iframe based on content
- Add `embedMinHeight` / `embedMaxHeight` options to clamp the dynamic
sizing
- Inside the embedded app, a `ResizeObserver` posts `discourse-resize`
messages to the parent window
- Scrolling stays enabled inside the iframe — Discourse's virtual DOM
only renders ~20 posts at a time and relies on internal scroll position
- Show the new options (commented out) in the admin embedding code
snippet

## Usage

```html
<script type="text/javascript">
  window.DiscourseEmbed = {
    discourseUrl: 'https://forum.example.com/',
    topicId: 123,
    fullApp: true,
    dynamicHeight: true,        // opt-in to iframe resizing
    embedMinHeight: '400',      // optional, pixels
    embedMaxHeight: '900',      // optional, pixels
    embedHeight: '600px',       // initial height before first resize
  };
</script>
```

## How it works

- **Default (no `dynamicHeight`)**: Full app embed uses fixed height
(`embedHeight` or `600px`) with internal scrolling. No change from
current behavior.
- **With `dynamicHeight: true`**: The iframe resizes to match content
height, clamped by `embedMinHeight` / `embedMaxHeight` if set. Short
topics shrink the iframe (no wasted whitespace), long topics grow to max
and scroll internally.

## Test plan

- [ ] Full app embed without `dynamicHeight` — verify unchanged behavior
(fixed height, scrolling)
- [ ] Full app embed with `dynamicHeight: true` — verify iframe resizes
as content loads
- [ ] Verify `embedMinHeight` / `embedMaxHeight` clamp the height
correctly
- [ ] Verify standard (non-full-app) embed still resizes as before
- [ ] Open the composer in embed mode — verify height updates propagate
- [ ] Load a long topic — verify virtual DOM post loading works with
scrolling
- [ ] Admin > Embedding page shows the new options commented out in the
code snippet
2026-04-16 12:06:09 -03:00
Rafael dos Santos Silva 0e6da77ff0 PERF: Lazy load full app embed iframe with IntersectionObserver (#39299)
## Summary

- Defer loading the Discourse iframe for full app embeds until the user
scrolls near it
- Feature detect `IntersectionObserver` — fall back to immediate loading
if unavailable
- Default margin of 1000px to give the heavy PWA time to load before the
user reaches it
- On by default for `fullApp` embeds, opt out with `lazyLoad: false`
- Configurable margin via `lazyLoadMargin`
- Show options in the admin embedding code snippet

## How it works

The iframe element is appended to the DOM immediately (preserving layout
space with `embedHeight`), but its `src` is not set until the
`IntersectionObserver` fires. The default 1000px margin gives Discourse
a head start on loading before the user actually scrolls to the embed.

```js
DiscourseEmbed = {
  discourseUrl: 'https://forum.example.com/',
  topicId: 123,
  fullApp: true,
  // lazyLoad: false,          // disable lazy loading of the iframe
  // lazyLoadMargin: '1000',   // pixels before viewport to start loading
};
```

## Test plan

- [ ] Full app embed below the fold — verify iframe doesn't load until
scrolling near it
- [ ] Full app embed above the fold — verify it loads immediately
(IntersectionObserver fires right away)
- [ ] `lazyLoad: false` — verify immediate loading, same as current
behavior
- [ ] Custom `lazyLoadMargin` — verify the margin is respected
- [ ] Standard (non-full-app) embed — verify unchanged behavior (always
loads immediately)
- [ ] Browser without IntersectionObserver — verify falls back to
immediate loading
2026-04-16 11:45:43 -03:00
Régis HANOLandMartin Brennan d56fca0fd7 FEATURE: Make can_permanently_delete visible with strong safeguards (#39179)
The `can_permanently_delete` site setting was hidden and could only be
enabled via the Rails console. There was no indication in the admin UI
that this capability existed, leading to confusion and wasted time for
admins trying to permanently delete content.

This commit unhides the setting and adds layered safeguards at every
level of the permanent deletion flow:

**Site setting visibility:**
- Remove `hidden: true` so the setting appears in the admin UI
- Add a `requires_confirmation` dialog when enabling (not when
disabling) via a new `simple_on_enable` confirmation type
- Add a proper setting description since it was missing

**Type-to-confirm on all permanent delete actions:**
- Replace the weak yes/no dialogs on post and revision permanent
deletion with a type-to-confirm pattern (type "permanently delete")
- Show context-aware titles and messages (post vs topic, with post count
for topics)
- Reusable `PermanentlyDeleteConfirm` dialog body component following
the `SecondFactorConfirmPhrase` pattern

**Server-side pre-check endpoint:**
- Add `GET /posts/:id/permanently_delete_check` (admin-only via
`AdminConstraint`) that uses the guardian to validate whether permanent
deletion is allowed before showing the confirmation dialog
- Returns the reason when denied (cooldown timer, undeleted posts) so
the admin gets immediate feedback instead of going through the full
confirmation flow only to be rejected
- Returns accurate `post_count` for topic deletion messages

**Refactors:**
- Extract `Topic#deletable_posts_count` to share the post counting query
between the guardian, `cannot_permanently_delete_reason`, and the new
endpoint
- Use exclusion (`NOT small_action`) instead of inclusion for post type
filtering, so plugin-added post types are counted correctly

Ref - t/181345

---------

Co-authored-by: Martin Brennan <martin@discourse.org>
2026-04-16 09:01:35 +02:00
chapoi 20405dce45 UX: new checkbox design (#38967)
Adds a redesigned FormKit checkbox behind the enable_new_checkbox_style
upcoming change flag. The native checkbox is visually hidden but remains
the functional element — the new checkmark span is purely
presentational, allowing for styling and animations.


https://github.com/user-attachments/assets/86986103-3832-4bde-917e-00eafe486b34

t/178553
2026-03-30 19:53:11 +02:00
af3385baba DEV: Introduce new rollup-based plugin build system (#35477)
This commit introduces a new build system for plugins, which shares a
large amount of code with the recently-modernized theme compiler.
Plugins are compiled to native ES Modules, and loaded using native
`import()` in the browser, just like themes.

To achieve inter-plugin imports, each bundled plugin entrypoint
implements a custom 'module federation' interface. Each export from
internal plugin modules is made available as a specially-named export on
the entrypoint. When modules in another plugin's namespace are imported,
they are automatically rewritten to use these federated entrypoints.

This change should be almost 100% backwards-compatible. There are some
edge cases which will behave differently, since modules are now eagerly
evaluated according to the ESM spec, instead of being lazily required
via asynchronous-module-definitions (AMD).

The native ESM format should also provide a performance improvement. The
old AMD system involved lots of nested function calls when booting the
app. Now, all the source modules are bundled up into a single ESM bundle
with minimal stack depth.

The build system implements a filesystem-based cache. That means that if
the plugin javascript files are unchanged, they will not need to be
recompiled, even after restarting the Rails server. This mimics the
behaviour of the theme system. Similarly, in production builds, existing
files will be automatically reused if they exist. In future, we plan to
include pre-built copies of common plugins in our prebuild-asset
bundles.

Initially, this new compiler is disabled by default. To test it, we can
set the `ROLLUP_PLUGIN_COMPILER=1` environment variable. We'll continue
to test, improve and document the system before enabling it by default.

---------

Co-authored-by: Jarek Radosz <jradosz@gmail.com>
Co-authored-by: Chris Manson <chris@manson.ie>
2026-03-03 13:50:55 +00:00
Joffrey JAFFEUX af5329588e FEATURE: Pin chat messages (#37985)
Allow staff to pin important messages in chat channels. Pinned messages
appear in a dedicated panel accessible from the channel navbar. Members
of allowed groups (admins/moderators by default) can pin and unpin
messages via the message actions menu.

Pinned messages show "pinned by" attribution, track unread state per
user, and auto-unpin when the original message is trashed. Real-time
updates via MessageBus keep the pinned list in sync.

Gated behind the chat_pinned_messages upcoming change (experimental).
2026-02-23 22:00:16 +01:00
Rafael dos Santos Silva 3893e55bd5 FEATURE: Full Ember app embed mode for blog comments (#36613)
## Summary

Adds a new `fullApp` option to the embed snippet that renders the
complete Discourse Ember application in the iframe instead of the
simplified Rails-templated view. This allows embedded comments to have
the full Discourse experience including likes, reactions, and inline
replies.

When `fullApp: true` is set:
- `/embed/comments` redirects to the topic URL with `?embed_mode=true`
- Header, sidebar, and footer are hidden
- All links open in new tabs (to avoid navigating away within the
iframe)
- Iframe is scrollable with configurable height (default 600px)

Feature is gated on a hidden site setting, default disabled, named `embed_full_app`

## Demo

https://discourse-full-embed.pages.dev/embed-test


## Usage

```js
DiscourseEmbed = {
  discourseUrl: 'https://forum.example.com/',
  discourseEmbedUrl: 'EMBED_URL',
  fullApp: true,
  // embedHeight: '800px',  // optional, defaults to 600px
};
```

## Security

The `embed_mode` parameter only removes the X-Frame-Options header if:
- `embed_any_origin` site setting is enabled, OR
- The request referer matches a configured embeddable host

This matches the existing security model for `/embed/comments`.
2026-02-18 18:22:57 -03:00
Martin Brennan 42da6860fd DEV: Migrate existing experiments to upcoming changes (#37401)
- **DEV: Migrate experimental_impersonation to upcoming changes**
- **DEV: Migrate experimental_form_templates to upcoming changes**
- **DEV: Migrate experimental_auto_grid_images to upcoming changes**
2026-02-02 11:08:12 +10:00
Martin BrennanandRégis Hanol d9805c8635 WIP: Additional simplified category improvements (#37338)
* Change the simplified category upcoming change to Experimental so
admins can try it out
* Delete unused preview-related code for the category UI
* Preserve category permissions when switching between public & private
access toggle

<img width="329" height="245" alt="image"
src="https://github.com/user-attachments/assets/729ba0f9-5e1c-4e71-8b4f-8c26d59bae45"
/>

---------

Co-authored-by: Régis Hanol <regis@hanol.fr>
2026-01-29 09:44:32 +10:00
af3e686989 FEATURE: Simplify category creation, hide settings (#36998)
This commit introduces a new simplified category creation and editing
form, hidden behind a `enable_simplified_category_creation` upcoming
change in the "conceptual" status
right now.

The simplified form allows users to toggle between simple + advanced
mode:

<img width="1106" height="641" alt="image"
src="https://github.com/user-attachments/assets/2ff70db7-280b-4edf-a119-bbb6554a1408"
/>

<img width="1116" height="694" alt="image"
src="https://github.com/user-attachments/assets/79e7e7d7-f7a8-49ee-80de-06f4dcb8a93f"
/>



The aim here is to make it faster for admins to create new categories,
which can be a fairly convoluted process right now. Our future aim
is to have different "types" of category creation flows.

In addition, all other forms in the other category tabs have been
converted
to use FormKit.

---------

Co-authored-by: Martin Brennan <martin@discourse.org>
Co-authored-by: Régis Hanol <regis@hanol.fr>
2026-01-27 14:51:30 +10:00
Derek Rushforth f5b01bc02a UX: New brand styles on wizard (#37229)
This PR aligns the wizard page styles with our latest brand updates.

## Before
<img width="1065" height="1034" alt="Screenshot 2026-01-22 at 11 51
16 AM"
src="https://github.com/user-attachments/assets/cb64346f-6136-46f3-8c5e-f1ddbac29144"
/>


## After
<img width="989" height="1101" alt="Screenshot 2026-01-22 at 11 48
48 AM"
src="https://github.com/user-attachments/assets/6ff7f7e9-6e7e-4422-a36e-0cef27757b39"
/>
2026-01-22 13:26:19 -07:00
Discourse Translator Bot bb8cfb8a65 I18N: Update translations (#37056) 2026-01-12 15:18:57 +01:00
Martin Brennan b2137390da FEATURE: Add floating dismiss on mobile upcoming change (#36747)
Adding "Floating dismiss topics on mobile" experiment.
2026-01-08 13:49:57 +10:00
Martin Brennan 74b9dab90f UX: Migrate experimental_rename_faq_to_guidelines to upcoming change (#36971)
This site setting was hidden anyway, so it is a good candidate to
move to testing upcoming changes. Admins will not see this still
until enable_upcoming_changes is turned on.
2026-01-07 10:55:10 +10:00
Keegan GeorgeandMartin Brennan 0e0e716e0d FEATURE: Ability to star chat channels (#36142)
## 🔍 Overview
This update adds the ability to star chat channels. Starred channels can
include DM channels or chat channels. Once a channel is starred it will
create a new section in the sidebar that can be collapsed/expanded. It
also adds a new tab to the mobile chat interface. Starring channels is a
user specific configuration and will be applied for the current user
rather than site wide.

At the moment this is enabled as an upcoming pre-alpha change by
toggling the settings for the respective groups in the upcoming changes
page:

<img width="986" height="141" alt="Screenshot 2025-11-28 at 14 45 07"
src="https://github.com/user-attachments/assets/1b297701-9135-4b6f-b36b-0805975a7872"/>

## 📹 Preview

### Desktop

https://github.com/user-attachments/assets/a0f84077-65a1-4f23-95f7-ac575c1387fa

### Mobile

https://github.com/user-attachments/assets/15ce190c-a647-4ae8-b552-c67686be56ea

---------

Co-authored-by: Martin Brennan <martin@discourse.org>
2025-12-03 09:25:08 -08:00
Discourse Translator Bot 8b9edc8829 Update translations (#35983) 2025-11-20 14:38:50 +01:00
Martin Brennan 2942ef375d DEV: System specs for image optimization in composer (#36060)
Followup 66cee823ab

Introduces a few basic system specs to verify that image optimization is
working as expected when uploading images via the composer. The specs
check
that images are optimized and that the optimization process completes
successfully
for both png and jpg images.

This PR also improves the formatting of optimization logs, including
adding
information about the original image size in bytes
2025-11-19 11:37:15 +10:00
David Taylor b21d317c64 DEV: Load magnific-popup via npm/webpack (#35250)
This removes our final vendored JS dependency 🎉
2025-10-08 08:28:06 +01:00
David Taylor 843f74e427 DEV: Load chartjs via npm/webpack (#35249) 2025-10-07 21:20:10 +01:00
David Taylor 782e0ea394 DEV: Replace 'squoosh' with jSquash for local media optimization (#35248)
A new webpack entrypoint is created for media-optimization, so that
webpack can take care of bundling up the dependencies. The main Worker
is still hosted in `public/javascripts`, since Workers must be
same-origin.
2025-10-07 19:31:21 +01:00
David Taylor 6c7baf3135 DEV: Stop vendoring pikaday (#35237)
Replace with Webpack-handled async import
2025-10-07 15:52:02 +01:00
Discourse Translator Bot 0bad5c6104 Update translations (#33746) 2025-07-23 00:13:58 +02:00
Discourse Translator Bot 59367ac03f Update translations (#33409) 2025-07-02 22:36:37 +02:00
Penar Musaraj f3c41af772 DEV: Refactor image compression for iOS (#32652) 2025-05-09 09:51:30 -04:00
Joffrey JAFFEUXandDavid Taylor d38acc5df1 DEV: discourse-emojis gem (#31408)
This commit moves most of emoji logic into the discourse-emojis gem:
https://github.com/discourse/discourse-emojis/

Most notably:
- images are now symlinked from the gem
- the gem provides path to the json files

Search aliases have also been made asynchronous and memoized. When you
will search for an emoji we will now load the aliases and store the list
for future use.

---------

Co-authored-by: David Taylor <david@taylorhq.com>
2025-03-03 13:09:08 +01:00
Discourse Translator Bot f0d6e9758d Update translations (#30898) 2025-01-21 15:55:30 +01:00