This commit mainly improves three things:
- slide up/down animation of the modals on mobile, also allowing swipe down to close the modal
- body scroll locked modals, it means that only the body of the modal can scroll
- a new `<:headerPrimaryAction>` block for `d-modal` which when present will move the cancel button to the left of the modal title, and this primary action to the right of the title
Why this change?
On the `/admin/customize/themes/<:id>` route, we allow admins to edit
all settings via a settings editor. Prior to this change, trying to edit
and save a typed objects theme settings will result in an error on the
server.
* A11Y: Update bulk selection keyboard shortcuts
Still a draft, but in current state this:
- adds `shift+b` as a keyboard shortcut to toggle bulk select
- adds `shift+d` as a keyboard shortcut to dismiss selected topic(s) (this
replaces `x r` and `x t` shortcuts)
- adds `x` as a keyboard shortcut to toggle selection (while in bulk select mode)
- fixes a bug with the `shift+a` shortcut, which was not working properly
Note that there is a breaking change here. Previously we had:
- `x r` to dismiss new topics
- `x t` to dismiss unread topics
However, this meant that we couldn't use `x` for selection, because the
itsatrap library does not allow the same character to be used both as a
single character shortcut and as the start of a sequence. The proposed
solution here is more consistent with other apps (Gmail, Github) that use
`x` to toggle selection.
Also, we never show both "Dismiss New" and "Dismiss Unread" in the same
screen, hence it makes sense to consolidate both actions under `shift+d`.
* Address review
Why this change?
Before this change, the new navigation item in the topic list will be
hidden when there are no new or unread topics for the user. We have
started to find this behaviour confusing UX wise so we decided to stop
hiding it.
Why this change?
This is a regression from introduced in
5c1147adf3 where dismissing unread topics
was changing the notification level of the topics instead of just
dismissing the unread posts.
What does this change do?
1. Bring back the previous implementation of the action
2. Fix the system test that was supposed to catch the problem but did
not.
Before, the `back to forum` link was part of experimental admin navigation. It means that the link could be filtered out.
Because it is essential navigation, it should not be part of sidebar links and should be moved above the filter.
When hiding/showing the sidebar, as is the case on mobile
and using the toggle in the top left on desktop, we delete
and recreate the ember component on the page. This causes
the `sections` for each sidebar panel to get re-evaluated
every time.
For the admin sidebar, this means that we were constantly
re-adding the plugin links to the sidebar, causing duplication.
This can be fixed by just adding @cached to the getter for
sections.
This is v0 of admin sidebar navigation, which moves
all of the top-level admin nav from the top of the page
into a sidebar. This is hidden behind a enable_admin_sidebar_navigation
site setting, and is opt-in for now.
This sidebar is dynamically shown whenever the user enters an
admin route in the UI, and is hidden and replaced with either
the:
* Main forum sidebar
* Chat sidebar
Depending on where they navigate to. For now, custom sections
are not supported in the admin sidebar.
This commit removes the experimental admin sidebar generation rake
task but keeps the experimental sidebar UI for now for further
testing; it just uses the real nav as the default now.
Why this change?
The test became flaky due to d208396c5c.
In that commit, we introduced `page.has_no_css?("div.menu-panel.animating")` to `PageObjects::Components::NavigationMenu::Sidebar#open_on_mobile` but
it did not work as intended because `page.has_no_css?("div.menu-panel.animating")` can return `true` immediately as the `animating` class has not been added
to the element.
What does this change do?
Switch to the `wait_for_animation` system helper to ensure that all
animations have ended on the element.
Why this change?
When we're in the midst of loading more tags, the filter dropdown
is still enabled and may result in us firing off multiple requests to
the server to load more tags. This makes the loading hard to reason
about in the tests environment and has led to flaky tests.
What does this change do?
This changes disables the filter dropdown when more tags are being
loading.
PERF: improve touch, swipe, panning performance on mobile menus
---
* stop event propagation on swipe events: other touch events were stealing a huge amount of time here. Stop event
propagation when handling pan events.
* animate with [web animations api](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API)
* prefer translate3d to hint for gpu rendering.
* query document for elements only on start move event, not on subsequent move
events
* remove unused calculations for directioned velocity and distance: all swipe/pan elements function in x/y direction only.
* re-implement scroll locking behavior.
re-implemented scroll lock behavior
---
With stop event propagation, we need to re-implement scroll locking on menu swipes.
Previously, this was using onTouchMove which was costly.
We may now use styling with overflow-y:hidden to lock scroll behavior.
overflow:hidden on html/body elements is now supported by iOS as of 2022
https://bugs.webkit.org/show_bug.cgi?id=153852https://bugs.webkit.org/show_bug.cgi?id=220908
UX: improve swipe
---
Some improvements to get gestures and swipes feeling a little more polished.
This focuses on end gesture, and how we transfer it to a css animation to
complete a menu open/close action.
Multitouch: events may pan, scroll, and zoom - especially on iOS safari.
Cancelling the swipe event allows for a more pleasant zooming experience.
* ease-out on menus opening, linear on close
* calculate animation duration for opening and closing,
attempt to better transfer user swipe velocity to css animation.
* more timely close/open and cleanup from calculated animation timing.
* add animation to closing menus on cloak tap
* correctly animate menus with ease-in and ease-out
* add swipe cancel event on multitouch event
DEV
---
* lean on promises
js animations api gives us promises to listen to. Update test waiters
to use waitForPromise from @ember/test-waiters instead of reigster/unregister.
* convert swipe mixin to its own class.
Convert swipe callbacks to custom events on the element.
Move shared functions for max animation time and close logic to
new shared class.
swipe-events lib uses custom events to trigger callbacks, rather than assuming
implemented hard coded function from the mixin's base class. Custom events are
triggered from the bound element as swipestart, swipeend, swipe
Add shared convenience functions for swipe events so they can be more easily
shared.
A client receives an initial swipe event and can check some state to see if it
wants to handle the swipe event and if it doesn't, calling
`event.preventDefault();` will prevent `swipe` and `swipeend` events from firing
until another distinct swipestart event is fired. Swipe events will auto-cancel on multitouch.
The scroll lock has also exposed as its own utility class.
This PR is a first step towards private groups. It redesigns settings/members area of a channel and also drops the "about" page which is now mixed into settings.
This commit is also:
- introducing chat-form, a small DSL to create forms, ideally I would want something in core for this
- introducing a DToggleSwitch page object component to simplify testing toggles
- migrating various components to gjs
Why this change?
Back in May 17 2023 along with the release of Discourse 3.1, we announced
on meta that the legacy hamburger dropdown navigation menu is
deprecated and will be dropped in Discourse 3.2. This is the link to the announcement
on meta: https://meta.discourse.org/t/removing-the-legacy-hamburger-navigation-menu-option/265274
## What does this change do?
This change removes the `legacy` option from the `navigation_menu` site
setting and migrates existing sites on the `legacy` option to the
`header dropdown` option.
All references to the `legacy` option in code and tests have been
removed as well.
- Allows to copy quotes from mobile
- Allows to copy text of a message from mobile
- Allows to select messages by clicking on it when selection has started
Note this commit is also now using toasts to show a confirmation of copy, and refactors system specs helpers concerning secondary actions.
<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in JavaScript). If your code does not include test coverage, please include an explanation of why it was omitted. -->
This adds a new secure_uploads_pm_only site setting. When secure_uploads
is true with this setting, only uploads created in PMs will be marked
secure; no uploads in secure categories will be marked as secure, and
the login_required site setting has no bearing on upload security
either.
This is meant to be a stopgap solution to prevent secure uploads
in a single place (private messages) for sensitive admin data exports.
Ideally we would want a more comprehensive way of saying that certain
upload types get secured which is a hybrid/mixed mode secure uploads,
but for now this will do the trick.
This could happen after you had already change the separation mode and would cause unexpected bugs.
This PR also adds more tests around using switch buttons with chat.
Short answer -- the problem is the video thumbnail generator & uploader
code added a couple of months back in f144c64e13.
It was implemented as another Mixin which overrides `this._uppyInstance`
when uploading the video thumbnail after the initial upload is complete,
which means the composer's `this._uppyInstance` value is overridden,
and it loses all of its preprocessors & upload code.
This is generally a problem with the Mixin based architecture that I
used for the Uppy code, which we need to remove at some point and
refacotr.
The most ideal thing to do here would be to convert this video thumbnail
code into an Uppy
[postprocessor](https://uppy.io/docs/uppy/#addpostprocessorfn) plugin,
which runs on each upload after they are complete. I started looking
into this, and the main hurdle here is adding support to tracking the
progress of postprocessors to
[ExtendableUploader](cf42466dea/app/assets/javascripts/discourse/app/mixins/extendable-uploader.js)
so that is out of scope at this time.
The fix here makes it so the ComposerVideoThumbnailUppy code is no
longer a Mixin, but acts more like a normal class, a pattern which
we have used in chat. I also clean up a lot of the thumbnail uploader
code and remove some unnecessary things.
Attempted to add a system spec, but video streaming does not work
in Chrome for Testing at this time, and it is needed for the
onloadedmetadata event.
* Minor style adjustments
* Removes "all" count because it's redundant to the count on New
* Updates generic class names with -- modifier to follow BEM and help avoid class name collisions
* Hides the toggle when bulk select is enabled (the UI ends up being too busy)
This PR adds a new toggle to switch the (new) /new list between showing topics with new replies (a.k.a unread topics), new topics, or everything mixed together.
What is the problem here?
When transiting between `/filter` routes with different `q` query
params, the input field is not updating to include the values in the `q`
query param. This was because we were setting the value of the input
field in the constructor of the controller but controllers are actually
singletons in Ember so setting the value of the input field is only done
once when the controller is initialised.
What is the fix here?
Instead of setting the value of the input field in the controller, we
set the value in the `setupController` hook in the route file.
This commit moves the calendar date and time picker shown in
the local dates modal into a core component that can be reused
in other places. Also add system specs to make sure there isn't
any breakages with this feature, and a section to the styleguide.
This fixes:
- a regression from 30c152c, where navigating to a topic's last reply
via keyboard would lose track of the topic when returning to the topic
list
- an issue where if a topic's last post is a small post, navigating to it
via keyboard would not focus the post
Co-authored-by: David Taylor <david@taylorhq.com>
By default, only 10 members are highlighted on group cards. However,
joining/leaving a big group via the buttons on the group card results in
up to 50 members being highlighted. For large groups, this causes the card
to move off-screen.
This happens because, while the initial render explicitly fetches only 10
members, we don't seem to apply the same limit as part of the member
reload performed when a user leaves/joins via the buttons on the card.
This PR fixes that by only making the first 10 users available for
highlight regardless of the number of members loaded in the store.
Why this change?
We're already displaying a category's description as the title attribute
on the category section link. We should do the same for tags as well.
Why was the test flaky?
The test relied on the fact that visiting a topic would marked its
post as unread. However, we did not actually stay on the topic long
enough in some cases for it to be considered read based on the logic in
our client side code.
This commit fixes the flakiness by ensuring that the post has actually
been read before navigating away.
Using the lastViewedTopicId indiscriminately can cause strange scrolling behavior when navigating to a **different** topic list after viewing a topic. We only want to refocus the topic when going 'back' to the same topic list which originally triggered the navigation.
Previously we were implementing scroll reset/memorization on a per-page basis. Many of these approaches relied on the `didInsertElement` hook, which is no longer appropriate since Discourse changed to use the 'loading slider' strategy for page transitions.
This commit rips out all of our custom scroll resetting/memorizing, and implements those things in a generic service. There are two features:
1. After every route transition, scroll to the top of the page
2. When using browser back/forward buttons, restore the last known scroll position for those routes
To opt-out of the behaviour, individual routes can add a scrollOnTransition boolean to their RouteInfo metadata using Ember's `buildRouteInfoMetadata` hook.