FIX: stop youtube autoplay on scrollups (#19951)

When a user pauses a youtube video and scrolls up high enough to load
new posts, the video either rewinds or restarts depending on the browser.
The problem is solved by patching virtual-dom to handle element prepends
without reordering old elements.

Long-term, Discourse intends to move away from the vdom/widget implementation, so this is intended as a short-term solution. More context at https://meta.discourse.org/t/57692

Co-authored-by: David Taylor <david@taylorhq.com>
This commit is contained in:
Aleksey Bogdanov 2023-02-09 12:46:10 +02:00 committed by GitHub
parent f1a52db0a0
commit e216a98f74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 90 additions and 15 deletions

View File

@ -56,6 +56,9 @@ module.exports = function (defaults) {
enabled: true, enabled: true,
}, },
autoImport: { autoImport: {
alias: {
"virtual-dom": "@discourse/virtual-dom",
},
forbidEval: true, forbidEval: true,
insertScriptsAt: "ember-auto-import-scripts", insertScriptsAt: "ember-auto-import-scripts",
webpack: { webpack: {

View File

@ -94,7 +94,7 @@
"terser": "^5.16.3", "terser": "^5.16.3",
"tippy.js": "^6.3.7", "tippy.js": "^6.3.7",
"util": "^0.12.5", "util": "^0.12.5",
"virtual-dom": "^2.1.1", "@discourse/virtual-dom": "^2.1.2-0",
"webpack": "^5.75.0", "webpack": "^5.75.0",
"wizard": "1.0.0", "wizard": "1.0.0",
"xss": "^1.0.14" "xss": "^1.0.14"

View File

@ -9,6 +9,7 @@ import { Promise } from "rsvp";
import { createWidget } from "discourse/widgets/widget"; import { createWidget } from "discourse/widgets/widget";
import { next } from "@ember/runloop"; import { next } from "@ember/runloop";
import { withPluginApi } from "discourse/lib/plugin-api"; import { withPluginApi } from "discourse/lib/plugin-api";
import { h } from "virtual-dom";
module("Integration | Component | Widget | base", function (hooks) { module("Integration | Component | Widget | base", function (hooks) {
setupRenderingTest(hooks); setupRenderingTest(hooks);
@ -394,4 +395,75 @@ module("Integration | Component | Widget | base", function (hooks) {
"renders container with overridden tagName" "renders container with overridden tagName"
); );
}); });
test("avoids rerendering on prepend", async function (assert) {
createWidget("prepend-test", {
tagName: "div.test",
html(attrs) {
const result = [];
result.push(
this.attach("button", {
label: "rerender",
className: "rerender",
action: "dummyAction",
})
);
result.push(
h(
"div",
attrs.array.map((val) => h(`span.val.${val}`, { key: val }, val))
)
);
return result;
},
dummyAction() {},
});
const array = ["ElementOne", "ElementTwo"];
this.set("args", { array });
await render(
hbs`<MountWidget @widget="prepend-test" @args={{this.args}} />`
);
const startElements = Array.from(document.querySelectorAll("span.val"));
assert.deepEqual(
startElements.map((e) => e.innerText),
["ElementOne", "ElementTwo"]
);
const elementOneBefore = startElements[0];
const parent = elementOneBefore.parentNode;
const observer = new MutationObserver(function (mutations) {
assert.notOk(
mutations.some((m) =>
Array.from(m.addedNodes).includes(elementOneBefore)
)
);
});
observer.observe(parent, { childList: true });
array.unshift(
"PrependedElementOne",
"PrependedElementTwo",
"PrependedElementThree"
);
await click(".rerender");
const endElements = Array.from(document.querySelectorAll("span.val"));
assert.deepEqual(
endElements.map((e) => e.innerText),
[
"PrependedElementOne",
"PrependedElementTwo",
"PrependedElementThree",
"ElementOne",
"ElementTwo",
]
);
const elementOneAfter = endElements[3];
assert.strictEqual(elementOneBefore, elementOneAfter);
});
}); });

View File

@ -1013,6 +1013,20 @@
resolved "https://registry.yarnpkg.com/@discourse/itsatrap/-/itsatrap-2.0.10.tgz#c7e750eeb32b54e769e952c4ecc472213eb1385a" resolved "https://registry.yarnpkg.com/@discourse/itsatrap/-/itsatrap-2.0.10.tgz#c7e750eeb32b54e769e952c4ecc472213eb1385a"
integrity sha512-Jn1gdiyHMGUsmUfLFf4Q7VnTAv0l7NePbegU6pKhKHEmbzV3FosGxq30fTOYgVyTS1bxqGjlA6LvQttJpv3ROw== integrity sha512-Jn1gdiyHMGUsmUfLFf4Q7VnTAv0l7NePbegU6pKhKHEmbzV3FosGxq30fTOYgVyTS1bxqGjlA6LvQttJpv3ROw==
"@discourse/virtual-dom@^2.1.2-0":
version "2.1.2-0"
resolved "https://registry.yarnpkg.com/@discourse/virtual-dom/-/virtual-dom-2.1.2-0.tgz#74e44261c7b0a99b3bf6db0eac37b86e978906a6"
integrity sha512-5sTfdNxyrFK9yb98YLBAChYiO2K6Go7ptErVUQciT7rgueoGyLyw6Sm0FeVkSK1GLfusYFKZG8ch2vGNzJ0wlQ==
dependencies:
browser-split "0.0.1"
error "^4.3.0"
ev-store "^7.0.0"
global "^4.3.0"
is-object "^1.0.1"
next-tick "^0.2.2"
x-is-array "0.1.0"
x-is-string "0.1.0"
"@ember-compat/tracked-built-ins@^0.9.1": "@ember-compat/tracked-built-ins@^0.9.1":
version "0.9.1" version "0.9.1"
resolved "https://registry.yarnpkg.com/@ember-compat/tracked-built-ins/-/tracked-built-ins-0.9.1.tgz#4cc97c1841425fbf812ef3c63c00ab4790fc32a0" resolved "https://registry.yarnpkg.com/@ember-compat/tracked-built-ins/-/tracked-built-ins-0.9.1.tgz#4cc97c1841425fbf812ef3c63c00ab4790fc32a0"
@ -9315,20 +9329,6 @@ vary@^1, vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
virtual-dom@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/virtual-dom/-/virtual-dom-2.1.1.tgz#80eda2d481b9ede0c049118cefcb4a05f21d1375"
integrity sha1-gO2i1IG57eDASRGM78tKBfIdE3U=
dependencies:
browser-split "0.0.1"
error "^4.3.0"
ev-store "^7.0.0"
global "^4.3.0"
is-object "^1.0.1"
next-tick "^0.2.2"
x-is-array "0.1.0"
x-is-string "0.1.0"
w3c-xmlserializer@^4.0.0: w3c-xmlserializer@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073"