These were set to `passive: true` in ff72522f.
However, two consumers of this mixin (topic-navigation and site-header) do need to call `e.preventDefault()`, so we can't use passive listeners here.
That's ok, because this mixin only applies to a specific component's element, not the entire page. So having these non-passive listeners doesn't affect the vast majority of scrolling
This mixin calls the "scrolled" method of some object with no parameters, so there is no way that consumers would ever call `event.preventDefault()`. Therefore we can make the listeners passive, and improve scrolling performance on mobile.
This commit also updates the mixin to remove JQuery usage. The API is slightly modified to remove the need for an event 'name' for binding/unbinding.
The calls to `.bindScrolling` and `.unbindScrolling` in user-stream.js are removed because they are already called by the LoadMore mixin which is applied to the component.
The `bindScrolling` method claimed to offer debouncing-by-default. However, a bug in the `opts` parsing meant that debouncing was skipped if a 'name' was passed in. Therefore the only consumer actually being debounced was the LoadMore mixin. This commit fixes the opts parsing, so all consumers get the same behavior.
However, when scrolling, debounce is rarely what we want. The documentation of `bindScrolling` says "called every 100ms". In fact, debounce means that the functions were only called 'after the user **stops scrolling** for 100ms'. If you're scrolling very slowly (e.g. when using momentum-based scrolling on mobile), then this can be quite frustrating. This is why "Load more" is only triggered on topics/topic-lists when you completely stop scrolling.
Therefore, this commit also replaces the default 'debounce' with a 'throttle'. The 'throttle' is configured with `immediate = false`, so that it fires on the trailing edge, and therefore the final call will always be **after** we finish scrolling. (the default `immediate: true` would fire on the leading edge, and so the last call could be up to 100ms **before** we finish scrolling).
Registering non-passive listeners for the touchstart event can affect scroll performance on mobile devices, and now shows a warning in Chrome. Our current version of Ember unconditionally registers all event listeners, even if they're unused. It also doesn't support passive event listeners. Once we get to Ember 4.0, it lazily registers event listeners, and supports passive listeners via the `{{on` helper.
We already disable the ember `mousemove` and `touchmove` events for performance, so it makes sense to do the same for `touchstart`. We are not using `touchstart` anywhere in core, and I cannot find any official/unofficial plugins which use it. If a `touchstart` event is required, plugins/themes can always register their own listeners (preferably on a specific element, rather than the whole `document`)
We do call `event.preventDefault()` on these events. They're limited to a single element, so performance impact should be negligable. Adding `passive: false` prevents the chrome dev tools warning.
None of these places call `event.preventDefault()`. Therefore we can register the event listeners as 'passive', and improve scroll performance on mobile devices.
Calling `setProperty("--header-offset", newValue)` will always cause a 'Recalculate Style' event, even if the value is unchanged. On my browser, these 'Recalculate Style' events take about 6-7ms each time the `dockCheck` function is run.
This commit stores the 'previous' value in an instance variable, and only calls setProperty if the value has changed. This brings the total runtime of `dockCheck` down to about 70µs on my machine.
The theme creator endpoints return JSON with a 201 CREATED
status code. With the recent changes to bootstrap-json/index.js
for the Ember CLI proxy, these endpoints were broken because
201 was not an accepted status code. This commit simply
adds 201 to the array, but prettier forced a reformat as well!
- Remove JQuery
- Remove legacy `document.webkitHidden` support. None of our currently supported browsers need this
- Use `passive` event listeners. These allows the browser to process the events first, before passing control to us
- Add a new `unseenTime` parameter. This allows consumers to request a delay before being notified about the browser going into the background
- Add a method for removing a callback
- Fire the callback when presence changes in either direction. Previously it would only fire when the user becomes present after a period of inactivity.
- Ensure callbacks are only called once for each state change. Previously they would be called every 60s, regardless of the value
- Listen to the `visibilitychanged` and `focus` events, treating them as equivalent to user action. This will make messagebus re-activate more quickly when switching back to a stale tab
- Add test helpers
- Delete the unused `discourse/lib/page-visible` module.
- Call message-bus's onVisibilityChange API directly, rather than dispatching a fake event on the `document`
Use @here to mention all users that were allowed to topic directly or
through group, who liked topics or read the topic. Only first 10 users
will be notified.
c401d641 introduced a new translation key for auth providers, and provided new strings for core providers. However, not all plugins have added this string. This commit makes the screenreader title fallback to the regular title in those cases.
This commit adds handlers for the composer uppy mixin to allow
for cancelling individual file uploads, not just all of them
at once. This is also combined with better tracking of in progress
uploads along with their progress percentage, for UI that needs
to be able to display the progress for individual files and
also cancel individual files.
To use this, a cancel button in the UI should call a function like this:
```javascript
cancelSingleUpload(fileId) {
this.appEvents.trigger(`${this.eventPrefix}:cancel-upload`, {
fileId,
});
},
```
Additionally, the `inProgressUploads` can be shown in the UI. It is an array of objects with the file name, ID, and the progress percentage. We can add more data to this if needed down the line.
This takes the uppy chunking algorithm and combines it with some
form submission from resumable.js for parity with the current
backup controller to make local backup uploads work with uppy.
We can then use this to replace the resumable-upload component
and the resumable.js library from our codebase, once stable.
This is disabled by default, so people using local backups will not
be affected. The enable_experimental_backup_uploader site setting
must be enabled for this to work.
When rendering the markdown code blocks we replace the
offending characters in the output string with spans highlighting a textual
representation of the character, along with a title attribute with
information about why the character was highlighted.
The list of characters stripped by this fix, which are the bidirectional
characters considered relevant, are:
U+202A
U+202B
U+202C
U+202D
U+202E
U+2066
U+2067
U+2068
U+2069
In the topic lists, it's important that we apply `pointer-events: none;` to the links. 0e371d4 updated the selector used for this css.
In `templates/list/topic-list-item.hbs`, `.main-link` is applied to the same element as `.topic-list-data`, so the new selector applied correctly.
In `templates/mobile/list/topic-list-item.hbr`, `.main-link` is nested within `.topic-list-data`, so the new selector did not apply correctly.
This commit switches the selector back to simply `.main-link`, so that it works for both mobile and desktop.
Calling `window.getComputedStyle` during initialization causes the browser to pause and 'Recalculate Style'. On my machine, this adds about 7ms to boot time. Instead, we can check for the `rtl` class on the html element, which is added by the server, and doesn't require computing styles.
This fixes an issue CvX found on PR #14666 where a previous fix
overwrote a computed property.
The better fix (as is often the case with Ember) is to remove an
observer and call methods when things change ourselves.
* FEATURE: Always show advanced invite options
The UI is more simple and more efficient than how it was when the
advanced options toggle was introduced. It does not make sense to keep
it anymore.
* UX: Minor copy edits
* UX: Merge expire invite controls
There were two controls in the create invite modal. One was a static
text that displayed how much time is left until the invite expires. The
other one was a datetime selector that set the time the invite expires.
This commit merges the two controls in a single one: staff users will
continue to see the datetime selector without the static text and
regular users will only see the static text because they cannot set
when the invite expires.
* UX: Remove invite link
It should only be visible after the invite was created.
Time spent in the 'find module with suffix' portion of our `customResolve` function were adding up to around 100ms-150ms when booting the app. This time is spread over 150+ calls, so it's not immediately obvious in flamegraphs.
This commit implements a (reversed) [Trie](https://en.wikipedia.org/wiki/Trie) which enables fast suffix-based lookups on a list of strings.
In my tests, this requires < 5ms to initialize, and brings the cumulative 'find module with suffix' time down to `< 5ms`. This corresponds to a ~100ms improvement in LCP metrics in my browser.
The only behavior change is to remove support for module filenames which are **not** dasherized. I haven't found any core/theme/plugin modules which are not dasherized in their filenames.
This commit refactors the direct external upload routes (get presigned
put, complete external, create/abort/complete multipart) into a
helper which is then included in both BackupController and the
UploadController. This is done so UploadController doesn't need
strange backup logic added to it, and so each controller implementing
this helper can do their own validation/error handling nicely.
This is a follow up to e4350bb966
* FIX: register customOptions as select kit filter
We are allowing plugins to define custom filters which are added to CUSTOM_USER_SEARCH_OPTIONS const. However, we need to have static placeholder for custom filters, so those props will be passed, and we can use it later.
* fix
* FEATURE: display warning when sharing a topic in a restricted category
If a topic belongs to a category that is not readable by everyone, display a text warning of "Only visible to members of groups: [group_a], [group_b]"
* DEV: Adding a new category means we need to bump this value
* DEV: pass category to showModal
- ensures arrow up/down doesn’t also apply to textarea while autocomplete is opened
- ensures esc is closing autocomplete and also not closing composer while autocomplete is opened
- Removes jquery
- Removes a not unregistered listener and uses component event
- Removes external-url class as it was only valid in one case of the dropdown
- Uses @action
- Tagless
- Other minor changes