[pull] master from mattermost:master - #868
Merged
Merged
Conversation
* Add discoverable private channels request-to-join UX
Let users mark private channels discoverable, find them in Browse Channels,
submit and withdraw join requests, and track status via My pending requests
instead of DM notifications.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Drop unrelated server changes from the branch
Restore server files to master; this PR is webapp-only and builds on the
existing discoverable-channels server implementation.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Close Request to Join modal immediately on submit
Drop the in-modal pending state so the modal closes as soon as the
request is sent, rather than flipping into a "sent / Withdraw" view
before disappearing. Browse Channels rows already handle the post-send
state (Requested pill + Withdraw), so the modal's pending branch was
redundant and visually noisy.
* Fix lint in channel_settings_info_tab test
Split multi-prop JSX onto separate lines and remove the trailing blank
line inside the Discoverable toggle describe block. Resolves the
react/jsx-max-props-per-line and padded-blocks errors that were
failing check-lint and cascading into a skipped build / failed Spinwick.
* Fix stylelint property order in request_join_channel_modal SCSS
Move min-width before align-items in .RequestJoinChannelModal__header
to satisfy stylelint's order/properties-order rule (dimensions before
flex alignment).
* Restore unintended deletions from original branch commit
The initial PR commit accidentally reverted master-side changes in
several shared files when the AI agent regenerated them. The rebase
onto current master preserved those reverts. Restore each piece while
keeping the branch's discoverable additions:
- client4.ts: previewLicense method
- websocket_actions.ts: handleFileUploadRejected function + switch case
- websocket_message.ts / websocket_messages.ts: FileUploadRejected type
- config.ts: License type fields (expires_at, customer required,
sku_short_name, is_gov_sku)
- constants.tsx: CHANNEL_MENTION_AUTO_FOLLOW notification section
- en.json: master keys (admin.license.*, admin.access_control.*,
etc.) restored; discoverable keys re-inserted using the Mattermost
i18n formatter sort rule (case-insensitive, '_' before '.')
- package-lock.json: reset to master
* Sync webapp package-lock.json with master to fix CI install
The branch carried a stale package-lock.json pinning eslint@8.57.0 while
package.json (identical to master) declares eslint@9.39.4. npm aborted with
an ERESOLVE peer conflict (@typescript-eslint/eslint-plugin@7.18.0 peers
eslint@^8.56.0), failing check-lint and the E2E check before any code ran.
This branch adds no dependencies, so the lockfile is restored to match master.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix join-request pending count double-decrement and prune stale pending map
Decrement countsByChannel from the actual pending->terminal transition
instead of the incoming status alone, so the acting admin's optimistic
dispatch plus the server's WebSocket echo of a single approve/deny no
longer double-decrements the badge. Make CREATED count-idempotent for
re-delivered events. Rebuild myPendingByChannel from the authoritative
full list on RECEIVED_MY_CHANNEL_JOIN_REQUESTS so a request that resolved
while the client missed the WS event no longer lingers as stale.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Surface discoverable channels in Browse without requiring a search
getChannels only returns public channels, so non-member discoverable
private channels (and the Discoverable filter) were empty until the user
typed a search term. Fetch them on mount via an empty-term non-admin
search (already ABAC-filtered server-side), fold them into the default
All list and the Discoverable filter, and resolve My pending requests
rows against them.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Browse row cleanup: drop unused action, keep Withdraw if discoverability revoked
Remove the requestJoinChannel action that was wired into Browse Channels
but never called (the confirmation modal dispatches it directly). Show the
Withdraw affordance for any non-member with an open request even after an
admin flips the channel's discoverable flag off, instead of falling
through to a Join button the server rejects for a private channel.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Fix discoverable-toggle a11y labels and gate settings toggle on in-progress type
- Description <label>s reused aria-label={discoverableTitle}, so screen
readers announced the title twice and skipped the description; point them
at discoverableDescription (channel settings + new channel modal).
- Gate the channel-settings discoverable toggle on the in-progress
channelType selection rather than the saved channel.type, so it appears
immediately during a Public->Private conversion, matching the New
Channel modal. The save flow already applies the privacy conversion
before the discoverable patch.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Guard Browse request/withdraw re-entry and make Withdraw keyboard-accessible
Ignore row clicks that would re-trigger request/withdraw while one is
already in flight (the row bypassed the disabled button), and disable the
buttons whenever any request/withdrawal is pending. Drop tabIndex={-1}
from the Withdraw button: pending rows are a no-op on Enter, so the button
was the only action and needed to stay keyboard-focusable.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Persist untracked join-request updates so duplicate terminal events stay idempotent
When a terminal CHANNEL_JOIN_REQUEST_UPDATED arrives for a row not yet in
byChannel (only the count was loaded), store it instead of leaving the
list unchanged. A re-delivered terminal event then finds it as terminal
and no longer decrements countsByChannel a second time.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Memoize filtered pending join-request selectors
getPendingChannelJoinRequests and getMyPendingJoinRequestList ran an
unmemoized .filter() on every call, returning a new array reference each
time and causing avoidable re-renders in any connected consumer. Wrap
both in createSelector.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Address review: drop redundant done() guards and harden withdraw error message
done is a required callback, so the if (done) guards in handleRequestToJoin
and handleWithdrawRequest were dead. Fall back to server_error_id / a
generic string when the withdraw error has no message, since error.message
isn't guaranteed at runtime.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Address review: use a class for the discoverable row indicator
The indicator rendered id='discoverableIndicatorContainer' on every
discoverable row, producing duplicate ids in the DOM when more than one
discoverable channel is listed. Switch it to a class (and update the SCSS
selector + test) so the markup stays valid.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Add discoverable private channels admin join-request queue UX (#37082)
QA deferred to the base branch
* Fix Quick Switch join flow for discoverable channels in recent/default lists (MM-68764)
The discoverableNonMember / hasPendingJoinRequest flags were only set on
Quick Switch search results, so a discoverable private channel surfaced via
the Recent or default (no-search-term) list fell through to the legacy
private-channel join confirmation, which the server rejects for a
non-member — leaving the user in a broken confirm/error loop.
Extract the detection into a shared applyDiscoverableFlags helper and run
it on every channel-list path (search via formatGroup, recent + unread via
wrapChannels) so the Request to Join flow fires consistently.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Bound concurrency of sidebar join-request count prefetch
Address CodeRabbit: the effect fired one count request per manageable
discoverable channel simultaneously. Process them in capped batches (5 at a
time) and cancel in-flight work on unmount / dependency change so a user who
manages many channels doesn't trigger an unbounded request burst.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Add ChannelHeader snapshot test for pending join requests
Address CodeRabbit: cover the join-request badge's conditional rendering
with a hasPendingJoinRequests=true snapshot case.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Add e2e tests for discoverable private channels request-to-join UX
Cover common use cases behind the DiscoverableChannels feature flag: a
non-member requesting to join a discoverable private channel from Browse
Channels and withdrawing, and selecting a discoverable channel from Find
Channels (Cmd+K) routing to the Request to Join modal rather than the
legacy join. Add supporting Browse Channels modal page-object helpers.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Address review: locate Browse Channels rows by display name in e2e helpers
Per the Playwright suite conventions, filter rows by visible display name
(.more-modal__row + hasText) instead of data-testid, and pass
channel.display_name from the spec.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Reveal Browse Channels row actions on keyboard focus (:focus-within)
Address review: the Withdraw button is keyboard-focusable (tabIndex removed
earlier) but the row action buttons are visibility:hidden and only revealed
on :hover / row :focus. Tabbing to the Withdraw button moves focus off the
row, so the buttons hid again. Add :focus-within so the actions stay visible
while any child button holds keyboard focus.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
* Route discoverable channel URL / mention-link navigation to Request to Join
Address review: opening a discoverable private channel a user isn't a member
of via a pasted channel URL or a ~channel mention link fired the legacy
'Join private channel' confirmation, which attempts a direct join the server
rejects, leaving the user on a broken channel view. When the feature flag is
on and the channel is discoverable, redirect to a safe channel and open the
Request to Join modal instead — matching Browse Channels and Quick Switch.
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Ibrahim Serdar Acikgoz <isacikgoz@users.noreply.github.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* Remove initialScrollOffset prop and associated mount hook code Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com> Co-authored-by: Mattermost Build <build@mattermost.com>
…nding page (#37690) The "Integrate & Extend" card and inline link pointed to /developers/integrate, which has no index page (only its "Get started" subcategory does), causing a 404. Point both links to /developers/integrate/getting-started instead. Co-authored-by: Cursor <cursoragent@cursor.com>
* MM-69940 Fix height of AdvancedTextEditor placeholder while loading The previous height included the margin which it shouldn't have. The 100% height on the post list also seemed to cause its height to change as well. That 98px assumes that this is the empty AdvancedTextEditor which is likely the most common case. * MM-69940 Change ChannelView to not split code as much I don't think this code splitting was necessary given we would always immediately load those components right away whenever the ChannelView is shown. It's not like the contents of a modal or the routing where we only need the async component conditionally. I did this so that the height of the PostView would change less while the app is loading to prevent layout shift and make accurate scrolling easier. * Move getPopoutChannelTitle to fix circular imports and update snapshots
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )