Context: https://meta.discourse.org/t/pixel-jump-whenever-page-refreshes-mobile-desktop/231053
We currently add 1 extra pixel when we try to restore the last scroll position on a few routes.
This is causing a bit of jumpiness, as described in the linked topic above.
<img height="300" src="ae9e69f7fd.gif">
Notice how the content shifts by 1px while stuff loads.
I believe this 1px that we add is an artifact from the days when we used to set the header to `fixed` but I'm not sure. Either way, the header now uses `position: sticky;` so we shouldn't need that 1px adjustment.
This PR introduced no visual changes except that it fixes the jitter mentioned above.
The idea behind this refactor is to centralise all of the user ignoring / muting / disallow PM checks in a single place, so they can be used consistently in core as well as for plugins like chat, while improving the main bulk of the checks to run in a single fast non-AR query.
Also fixed up the invite error when someone is muting/ignoring the user that is trying to invite them to the topic.
- following c3fd91670e `paste` has been typoed into `pase`
- adds two tests for pasting in `multi-select` and `email-group-user-chooser`
- selectKitOptions would not be following the right overriding order
- `category-selector` was using `selectKitOptions` directly which shouldn't be the case as it's not using computed values
- apparently since a recent ember upgrade, paste event is not providing `originalEvent` anymore and `clipboardData` should be retrieved directly on the event
Adds BEM-style classes to the input-group elements, and a dynamic class to the create-account-form element that reflects which auth provider is being used (if any).
Similar to e15c6302, overriding an auto-injected value like this triggers errors in more recent versions of Ember. Instead, we can use the registry to inject the value we need.
Co-authored-by: Peter Wagenet <peter.wagenet@gmail.com>
All our development-mode assets serve a `Cache-Control: no-cache` header, so a query parameter shouldn't be needed. Ember CLI does not include cache-busting parameters, so this change will move the development rails app to the same behaviour.
This will fix adding persistent breakpoints in the dev tools. Previously, the browser would think that the assets have been replaced and throw away the breakpoints.
Prior to v89, Firefox has bugs with document.execCommand("insertText"): https://bugzil.la/1220696
This commit introduces some variables to browser-detect, and therefore wraps the entire logic in an IIFE to avoid state leaking. (`let`/`const` are not supported on older browsers)
This manual assignment was added before the keyValueStore was refactored into a service. Now that it's a service, it gets all our standard auto-injections, including the keyValueStore.
Overwriting an automatic injection like this raises an error in future Ember versions.
This is useful when debugging exceptions - when the box is checked, exceptions will be thrown and handled by the browser rather than being absorbed by qunit. This allows developers to intercept the exception and inspect the stack.
This update covers commits:
* e309b6d [BREAKING Make JS client throw if lastId not number](e309b6d533)
* f0bae69 [DEV: removes dead code](f0bae695b0)
* a72b930 [FIX: force a poll more consistently when visibility changes](a72b9308b4)
* 5c01715 [Permit CORS preflight caching](5c01715432)
* 1789784 [DEV: lint files](17897843b4)
* b9cfb90 [FIX: do not leak visibility event subscriptions on stop/start](b9cfb90dd6)
* Use QUnit `module` instead of `discourseModule`
* Use QUnit `test` instead of `componentTest`
* Use angle-bracket syntax
* Remove jQuery usage
* Improve assertions (and actually fix some of them)
Currently we only apply watched words of the `Block` type to custom user
fields and user profile fields.
This patch enables all rules to be applied such as `Censor` or
`Replace`.
Previously we would only expand the main `<noscript>` element for older browsers. This commit ensures that we expand all noscript elements on the page, including the one used by the splashscreen to hide itself on the no-js view.
It ends up just triggering an error:
```
[Intervention] Blocked call to navigator.vibrate because user hasn't tapped on the frame or any embedded frame yet: https://www.chromestatus.com/feature/5644273861001216.
```
We don't count quote characters as part of the reply length.
We don't save drafts if the reply length is less than the min_post_length site setting.
If you start a reply that only contains a bunch of quotes with the intent to continue later, you get no draft.
This PR fixes that.
Note that we still don't save drafts if the composer is completely empty or if you're composing a new topic. This only affects replies.
This PR only changes the behavior if the reply composer contains something regardless of whether that something is a quote or not and ignores the min_post_length site setting.
The dots in the splash were previously hard-coded (v1). This PR makes progress towards making them be based on current theme colors.
Note that this is an improvement and not the "final" version. We're going to dynamically generate the splash file and the base64 URL later on.
All files under `app/assets/javascripts/scripts` will be run through babel, given sourcemaps, and output under `/assets/{name}.js`. This is another step towards removing our sprockets dependence.
The default Ember resolver implementation allows this for components. We need the same for connectors (which are essentially components behind-the-scenes)
This switches us to use the modern ember resolver package, and re-implements a number of our custom resolution rules within it. The legacy resolver remains for now, and is used as a fallback if the modern resolver is unable to resolve a package. When this happens, a warning will be printed to the console.
Co-authored-by: Peter Wagenet <peter.wagenet@gmail.com>
Mutating the `raw` variable like this would cause issues upstream, meaning that the modification is not persisted. Instead, we should allocate a new string like the other replacement methods.
Some plugins/themes are still awaiting updates for some deprecations, and they started raising errors in development. It's not clear that the errors are development-only, so it can be quite confusing for developers.
Disabling this flag for now until we can make the messages clearer and fix up existing deprecation issues in themes/plugins.
7caaee2 introduced a duplicate definition of the component JS. This likely happened because we had the template defined under `javascripts/discourse`, and the component JS defined under `javascript/admin`. This commit removes the duplicate definition, and moves the template to the admin addon
* FIX: Posts can belong to hard-deleted topics
This was a problem when serializing deleted posts because they might
belong to a topic that was permanently deleted. This caused to DB
lookup to fail immediately and raise an exception. In this case, the
endpoint returned a 404.
* FIX: Remove N+1 queries
Deleted topics were not loaded because of the default scope that
filters out all deleted topics. It executed a query for each deleted
topic.
If an image is oneboxed directly, then we should replace the onebox URL with a markdown image tag. This ensures that the wrapper link points to the downloaded version rather than the original.
This regressed in bf6f8299
Category badge changes based on the `category style` site setting so we
do not want to forcing all category names to the same color.
Follow-up to 3266350e80
This commit adds preload links for core/plugin/theme CSS stylesheets in the head.
Preload links are non-blocking and run in parallel. This means that they should have already been downloaded by the time we use the actual stylesheets (in the <body> tag).
Google is currently complaining about this here and this PR will address that warning.
This commit will also fix an issue in the splash screen where it sometimes doesn't respect the theme colors - causing a slightly jarring experience on dark themes.
Note that I opted not to add new specs because the underlying work required already has a lot of coverage. The new methods only change the output HTML so we can chuck that in the document <head>
This change also means that we can make all the stylesheets non-render blocking, but that will follow in a separate commit.
```sh
npx ember-holy-futuristic-template-namespacing-batman-codemod ensure-template-only-has-backing-class
```
We would like to colocate templates but, when no backing class exists, colocated templates extend `templateOnly` instead of `Ember.Component`. Generating the backing class helps avoid any behavioral changes.
We can also run the `tagless-ember-components-codemod` to put the tags into the templates at which point we could convert these back to template-only components.
We previously used the window load event as a target to remove the splash. The issue with that is that it means we wait for images to download before we remove the splash.
Ember has a better method that we can use ready(). This PR triggers a custom discourse-ready when that happens and uses that as the baseline for removing the splash.
This PR also adds three new performance marks. discourse-ready, discourse-splash-visible, and discourse-splash-removed
These will help us keep track of performance.
Internal topic /t/65378/81
Since we removed the `row:after { clear: both }` CSS we no longer use `float` style here. Instead, we should use `flex` style to align the button in right side.
We previously relied on CSS animation-delay for the splash. This means that we can get inconsistent results based on device/network conditions.
This PR moves us to a more consistent timing based on {request time + 2 seconds}
Internal topic: /t/65378/65
Tests have been intentionally left out as it is hard to test interaction that relies on local storage.
It also isn't the end of the world if the feature regresses.
Before, whispers were only available for staff members.
Config has been changed to allow to configure privileged groups with access to whispers. Post migration was added to move from the old setting into the new one.
I considered having a boolean column `whisperer` on user model similar to `admin/moderator` for performance reason. Finally, I decided to keep looking for groups as queries are only done for current user and didn't notice any N+1 queries.
Seems to only be a problem when a markdown.it rule inserts links without a attribute value. There's no test, because it's not reproducible with the markdown rules in core.
Updates automatically data on the stats section of the topic.
It will update automatically the following information: likes, replies and last reply (timestamp and user)
- Sets `https://www.mixcloud.com` as a `requires_iframe_origins` to allow the iframe content to be displayed
- Attempts to render something approximating the Mixcloud content in the preview pane of the Composer, rather than just displaying a large version of the artwork associated with the link
We currently remove the splash screen once Discourse starts booting.
This can be an issue on very slow devices, which can take up to 6 seconds. This PR ensures that we don't remove the splash until the browser has finished parsing all of the site's assets. It won't impact fast devices.
Internal topic /t/65378/60
Hopefully fixes flakes like:
```
not ok 1123 Chrome 102.0 - [undefined ms] - Global error: Uncaught Error: Unhandled request in test environment: /forum/u/eviltrout.json (PUT) at http://localhost:7357/assets/vendor.js, line 38378
While executing test: Unit | Utility | click-track: routes to absolute internal urls
---
browser log: |
{"type":"error","text":"Unhandled request in test environment: /forum/u/eviltrout.json (PUT)"}
{"type":"error","text":"Uncaught Error: Unhandled request in test environment: /forum/u/eviltrout.json (PUT) at http://localhost:7357/assets/vendor.js, line 38378\n","testContext":{"id":1123,"name":"Unit | Utility | click-track: routes to absolute internal urls","items":[],"state":"executing"}}
...
```
There's an obscure bug where really slow devices end up removing the splash screen before they're finished parsing all of the Discourse assets.
This PR won't impact fast devices but should hopefully prevent the premature removal of the splash on super slow devices.
We use javascript to remove the splash screen when the site boots up. If the user has js disabled, they get stuck on the splash screen.
If the user has js disabled. We don't show the splash screen at all.
There's an obscure bug where really slow devices end up removing the splash screen before they're finished parsing all of the Discourse assets.
This PR won't impact fast devices but should hopefully prevent the premature removal of the splash on super slow devices.
We use javascript to remove the splash screen when the site boots up. If the user has js disabled, they get stuck on the splash screen.
If the user has js disabled. We don't show the splash screen at all.
Fixes a flaky spec:
```
1) WordWatcher.word_matcher_regexp format of the result regexp is correct when watched_words_regular_expressions = true
Failure/Error: expect(regexp.inspect).to eq("/(#{word1})|(#{word2})/i")
expected: "/(word35)|(word36)/i"
got: "/(word36)|(word35)/i"
(compared using ==)
# ./spec/services/word_watcher_spec.rb:19:in `block (4 levels) in <main>'
```
This commit does six things
* changes the animation for the splash screen. To a more subtle animation.
* defers displaying the splash by 1.5 seconds
* defers displaying the splash "loading" text by 2.5 seconds
* defers removing the splash until all Discourse initializers have run
* fixes a display issue in Firefox
* Inlines the SVG as a base64 and inlines the required CSS.
The encoded SVG is hard coded for now, but we will use a helper to generate that based on the file after some testing.
We have a `cleanup!` class method on bookmarks that deletes
bookmarks X days after their related record (post/topic) are
deleted. This commit changes this method to use the
registered_bookmarkables for this instead, and each bookmarkable
type can delete related bookmarks in their own way.
When calling the API to delete a user:
```
curl -X DELETE "https://discourse.example.com/admin/users/159.json" \
-H "Content-Type: multipart/form-data;" \
-H "Api-Key: ***" \
-H "Api-Username: ***" \
-F "delete_posts=true" \
-F "block_email=false" \
-F "block_urls=false" \
-F "block_ip=false"
```
Setting the parameters `block_email`, `block_urls` and `block_ip`explicitly to `false` did not work because the values weren't being parsed to boolean.
This PR introduces a new hidden site setting that allows admins to display a splash screen while site assets load.
The splash screen can be enabled via the `splash_screen` hidden site setting.
This is what the splash screen currently looks like
5ceb72f085.mp4
Once site assets load, the splash screen is automatically removed.
To control the loading text that shows in the splash screen, you can change the preloader_text translation string in admin > customize > text
It's already included in the `ignored_columns` list in the group model. 03ffb0bf27/app/models/group.rb (L9)
Also, removed the `MigrateGroupFlairImages` onceoff job and spec.
On the password_reset error screen, it was totally unused
On the show_confirm_new_email screen, we can load the `vendor` bundle instead. Eventually we should move all this logic into the Ember app
In certain situations, a logged in user can redeem an invite with an email that
either doesn't match the invite's email or does not adhere to the email domain
restriction of an invite link. The impact of this flaw is aggrevated
when the invite has been configured to add the user that accepts the
invite into restricted groups.
This commit allows quoting of discourse-local-date elements
and converts the quoted tags back into bbcode so that the
rendered quote will also render the discourse-local-date HTML.
This works on single dates as well as date ranges, and supports
all of the options used by discourse-local-date.
This also necessitated adding addTextDecorateCallback to the
to-markdown core lib (similar to addBlockDecorateCallback and
addTagDecorateCallback) to transform the text nodes between
date ranges to remove the -> in the final quote.
c.f. https://meta.discourse.org/t/quotes-that-contain-date-time/101999
Now that we've switched to Ember CLI, these things are no longer used.
- These sprockets manifests are superceded by the assets generated by ember cli
- These vendored scripts are now fetched by ember-auto-import at compile time
Updates markdown-it to v13.0.1
Noteworthy changes:
* `markdownit()` is now available on `globalThis` instead of `window`.
* The `text_collapse` rule was renamed to `fragments_join` which affected the `bbcode-inline` implementation.
* The `linkify` rule was added to the `inline` chain which affected the handling of the `[url]` BBCode. If available, our implementation reuses `link_open` and `link_close` tokens created by linkify in order to prevent duplicate links.
* The rendered HTML for code changed slightly. There's now a linebreak before the `</code>` tag. The tests were adjusted accordingly.
```
{"type":"warn","text":"DEPRECATION: Using this.clearRender has been deprecated, consider using `clearRender` imported from `@ember/test-helpers`. [deprecation id: ember-test-helpers.setup-rendering-context.clearRender]"}
```
Similar to #17145
This commit moves the SVG sprite container to the <discourse-assets> element.
There is 0 visual or functional changes in this PR. It just tidies up the element view in devTools.
This PR introduces 0 visual or functional changes. The only thing that it changes is that it moves the data-preloaded div (which has the app boot json into the <discourse-assets> element.
See #17078 for a bit more context.
The reason behind this change is that it makes devTools element view a little bit less cluttered.
Certain rogue bots such as Yandex may send across invalid CSP reports
when CSP report collection is enabled.
This ensures that invalid reports will not cause log floods and simply
returns a 422 error.
Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
At some point in the past we decided to rename the 'regular' notification state of topics/categories to 'normal'. However, some UI copy was missed when the initial renaming was done so this commit changes the spots that were missed to the new name.
This is related to #17063 and is also a pre-request for the splash screen work.
This PR introduces 0 visual or functional changes. It just relocates the stylesheets in the load order.
`.css` stylesheets block the browser render. We need to move those out of the <head> tag.
However, they still need to be loaded before core/plugin/theme rendered HTML to avoid FOUC.
This is pre-request work to introduce a splash screen while site assets load.
The only change this commit introduces is that it ensures we add the defer attribute to core/plugin/theme .JS files. This will allow us to insert markup before the browser starts evaluating those scripts later on. It has no visual or functional impact on core.
This will not have any impact on how themes and plugins work. The only exception is themes loading external scripts in the </head> theme field directly via script tags. Everything will work the same but those would need to add the defer attribute if they want to keep the benefits introduced in this PR.
`email-group-user-chooser` currently handles paste events to allow users to paste multiple entries at once instead of entering them one by one. This behavior makes sense when the component is used in scenarios where it makes sense to provide multiple entries such as the recipients field when creating a PM. However, for instances where the component accepts only 1 entry, it doesn't make a lot of sense to do custom handling of paste events.
This commit makes our paste event handler a NOOP when the component is configured to accept only 1 entry in which case pasting will simply input the value into the component's search field.
* FIX: Make watched words uploads work as intended
Currently when we upload a file containing watched words, it will always
add the words to the action that was initially selected: this is the
`block` action by default but if changing manually the action in the URL
to `flag` for example, then this action will be selected and uploaded
watched words will be categorised as `flag` no matter what.
The problem lies with how the component works: it’s an Uppy object where
extra data is defined to provide an action key to the server but when
navigating to another listed action, while this action key is properly
updated on the component itself, the underlying Uppy object has already
been created and doesn’t care about the new value.
This patch solves this by using the `_perFileData` method instead of
`data`: the former is merged just before uploading a file whereas the
latter is used when the Uppy object is created.
This reverts commit 94c3bbc2d1.
At this current point in time, we do not have enough data on whether
this centralisation is the trade-offs of coupling features into a single
channel.
Presence endpoints are often called asynchronously at the same time as other request, and never need to modify the session. Skipping ensures that an unneeded cookie rotation doesn't race against another request and cause issues.
This change brings presence in line with message-bus's behaviour.
In the specific case where you start typing an emoji, then open the full emoji picker, the chosen emoji would be inserted in the wrong place. This was an unintentional side effect of the changes in 75d9c16156
This commit updates the `emojiSelected` logic to avoid mutating the 'selected' object, and also adds a test for this specific behaviour.
* The `javascript:update` rake task failed because recent versions of chart.js use a lowercase filename (`chart.min.js` instead of `Chart.min.js`)
* Changed `loadScript()` to use lowercase keys to lookup scripts
* `svg-arrow.css` seems to have changed slightly (linebreak at the end of file)
e.g.
```
presenceChannel = this.presence.getChannel('/blah');
presenceChannel.subscribe();
presenceChannel.on('change', (channel) => console.log(channel.users));
```
This commit also does some refactoring to remove the use of an unnecessary EmberObject and dynamic `defineProperty` call
When sending emails with delivery_method_options -> return_response
set to true, the SMTP sending code inside Mail will return the SMTP
response when calling deliver! for mail within the app. This commit
ensures that Email::Sender captures this response if it is returned
and stores it against the EmailLog created for the sent email.
A follow up PR will make this visible within the admin email UI.
When a user is answering a whisper comment, they cannot change from whisper to regular answer.
However, user can click reply to topic. We keep `postSnapshot` so user can change mind and switch back to reply to post. In that case, a toggle whisper button should appear.
To make it happen, I am ensuring to display a toggle whisper button when user is replying to topic - `postLink` attribute is missing.
Fixes many Ember deprecation warnings like:
```
WARNING: Binding style attributes may introduce cross-site scripting vulnerabilities; please ensure that values being bound are properly escaped. For more information, including how to disable this warning, see https://emberjs.com/deprecations/v1.x/#toc_binding-style-attributes. Style affected: "border-color: #33B0B0; --category-color: #33B0B0;"
```
As part of this commit, a bug where updating a tag's notification level on the server side does not update the state of the user's tag notification levels on the client side is fixed too.
The query is very inefficient without any constraints on large sites and
the average of all time to first response since the beginning of time is
not useful as well.
We do not zero-pad our base62 short URLs, so there is no guarantee that the length is 27. Instead, let's greedily match all consecutive base62 characters and look for a matching upload.
This reverts bd32656157 and 36f5d5eada.
The `WebhookController` inherits directly from `ActionController::Base`. Since Rails 5.2, forgery protection has been enabled by default. When we applied those new defaults in 0403a8633b, it took effect on this controller and broke integrations.
This commit explicitly disables CSRF protection on these webhook routes, and updates the specs so they'll catch this kind of regression in future.
Allow for a default translation string to be returned when a translation cannot
be found.
Useful in contexts where there is a known fallback, such as custom emoji group
strings.
This commit removes many uses of `this._$textarea`, and also switches us to use `document.execCommand("insertText")` for the majority of manipulations. This means that the browser undo history will be preserved when doing things like pasting rich html, using bold/italic shortcuts, etc.
These manipulations are already extensively tested. This commit extends a few of the tests to verify the undo behavior.
There are still a few cases (e.g. replacing upload placeholders with true URLs) where we don't necessarily want to bring the composer into focus. In those cases, the old history-breaking behavior remains for now.
The test was un-skipped in 6f25f17360 but
has since been flaky again. Removing the test completely as it has
resulted in more pain for us than the value the test provides.
This table holds associations between uploads and other models. This can be used to prevent removing uploads that are still in use.
* DEV: Create upload_references
* DEV: Use UploadReference instead of PostUpload
* DEV: Use UploadReference for SiteSetting
* DEV: Use UploadReference for Badge
* DEV: Use UploadReference for Category
* DEV: Use UploadReference for CustomEmoji
* DEV: Use UploadReference for Group
* DEV: Use UploadReference for ThemeField
* DEV: Use UploadReference for ThemeSetting
* DEV: Use UploadReference for User
* DEV: Use UploadReference for UserAvatar
* DEV: Use UploadReference for UserExport
* DEV: Use UploadReference for UserProfile
* DEV: Add method to extract uploads from raw text
* DEV: Use UploadReference for Draft
* DEV: Use UploadReference for ReviewableQueuedPost
* DEV: Use UploadReference for UserProfile's bio_raw
* DEV: Do not copy user uploads to upload references
* DEV: Copy post uploads again after deploy
* DEV: Use created_at and updated_at from uploads table
* FIX: Check if upload site setting is empty
* DEV: Copy user uploads to upload references
* DEV: Make upload extraction less strict
This reverts one of the changes introduced just now in:
27d7b0c6de
I don't think we need this `activated_not_suspended_not_staged` scope
because we can just compose it ourselves via method chaining like
`User.activated.not_suspended.not_staged`.
This commit introduces a new site setting: `block_hotlinked_media`. When enabled, all attempts to hotlink media (images, videos, and audio) will fail, and be replaced with a linked placeholder. Exceptions to the rule can be added via `block_hotlinked_media_exceptions`.
`download_remote_image_to_local` can be used alongside this feature. In that case, hotlinked images will be blocked immediately when the post is created, but will then be replaced with the downloaded version a few seconds later.
This implementation is purely server-side, and does not impact the composer preview.
Technically, there are two stages to this feature:
1. `PrettyText.sanitize_hotlinked_media` is called during `PrettyText.cook`, and whenever new images are introduced by Onebox. It will iterate over all src/srcset attributes in the post HTML and check if they're allowed. If not, the attributes will be removed and replaced with a `data-blocked-hotlinked-src(set)` attribute
2. In the `CookedPostProcessor`, we iterate over all `data-blocked-hotlinked-src(set)` attributes and check whether we have a downloaded version of the media. If yes, we update the src to use the downloaded version. If not, the entire media element is replaced with a placeholder. The placeholder is labelled 'external media', and is a link to the offsite media.
If the select-kit header is not in the viewport (scrolled out of view), popper adds a data-popper-reference-hidden attribute.
This PR adds the recommended styles to "hide" the select-kit body when that happens. See
https://popper.js.org/docs/v2/modifiers/hide/
* FIX: Email Send post has already been taken error
Adding a failing test first before coming up with a good solution.
Related: 357011eb3b
The above commit changed
```
PostReplyKey.find_or_create_by_safe!
```
to
```
PostReplyKey.create_or_find_by!
```
But I don't think it is working as a 1-1 replacement because of the
`Validation failed: Post has already been taken` error we are receiving
with this change. Also we need to make sure we don't re-introduce any
concurrency issues.
Reported: https://meta.discourse.org/t/224706/13
* Remove rails unique constraint and rely on db index
I believe this is what is causing `create_or_find_by!` to fail. Because
we have a unique constraint in the db I think we can remove this rails
unique constraint?
* clean up spec wording
This commit resolves a bug where users are not auto approved based on
`SiteSetting.auto_approve_email_domains` when
`SiteSetting.must_approve_users` has been enabled.
When a site has `SiteSetting.invite_only` enabled, we create a
`ReviewableUser`record when activating a user if the user is not
approved. Therefore, we need to approve the user when redeeming an
invite.
There are some uncertainties surrounding why a `ReviewableRecord` is
created for a user in an invites only site but this commit does not seek
to address that.
Follow-up to 7c4e2d33fa