Commit 56399ced authored by jaywink's avatar jaywink
Browse files

Merge branch 'asdwork' into 'master'

Grid layout after content iframe resize

See merge request !574
parents cb0c904f 4024e11c
Pipeline #6465 passed with stages
in 14 minutes and 41 seconds
import datetime
import os
import re
import string
import random
from django.db import DataError
from django.db import IntegrityError
......@@ -88,6 +90,12 @@ class OEmbedDiscoverer(ChainingDiscoverer):
"https://twitter.com/"
],
"url": "https://publish.twitter.com/oembed",
}),
StaticDiscoveryEndpoint({
"schemes": [
"https://www.nextplatform.com/*"
],
"url": "https://www.nextplatform.com/wp-json/oembed/1.0/embed",
})
])
])
......@@ -117,9 +125,21 @@ def fetch_oembed_preview(content, urls):
continue
if not oembed:
continue
# Keep height if width = 100%
if not re.search(r'\s+width="100%"', oembed):
oembed = re.sub(r'\s+height="[0-9]+"', " ", oembed)
# Ensure width is 100% not fixed
oembed = re.sub(r'width="[0-9]*"', 'width="100%"', oembed)
oembed = re.sub(r'height="[0-9]*"', "", oembed)
oembed = re.sub(r'\s+width="[0-9]+"', ' width="100%"', oembed)
# Wordpress sites use a random token and message events to identify the right iframe in order
# to set the rendered height. For this to work within a masonry grid, the parent script
# must already be loaded. Since in that context the parent script which updates the iframe
# tag with the token is not called, we add it here.
if "wp-embedded-content" in oembed:
oembed = re.sub(r'<script.*</script>', '', oembed, flags=re.S)
oembed = re.sub(r'<blockquote.*</blockquote>', '', oembed)
ltr = string.ascii_lowercase + string.digits
secret = ''.join(random.choice(ltr) for i in range(10))
oembed = re.sub(r'(<iframe.*src=".*?)"', '\g<1>#?secret='+secret+'" data-secret="'+secret+'"', oembed)
try:
with transaction.atomic():
oembed = OEmbedCache.objects.create(url=url, oembed=oembed)
......
<template>
<div v-images-loaded.on.progress="onImageLoad">
<div>
<div v-if="content.hasLoadMore">
<div v-infinite-scroll="loadMore" infinite-scroll-disabled="disableLoadMore" />
</div>
......@@ -8,10 +8,10 @@
<nsfw-shield v-if="content.is_nsfw" :tags="content.tags">
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-html="content.rendered" />
<div :id="content.id" v-html="content.rendered" />
</nsfw-shield>
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-else v-html="content.rendered" />
<div v-else :id="content.id" v-html="content.rendered" />
<reactions-bar :content="content">
<div v-if="!showAuthorBar" class="stream-element-content-timestamp mr-2">
......@@ -33,7 +33,6 @@
<script>
import Vue from "vue"
import imagesLoaded from "vue-images-loaded"
import AuthorBar from "@/components/streams/AuthorBar.vue"
import ContentTimestamp from "@/components/streams/ContentTimestamp"
......@@ -42,7 +41,6 @@ import NsfwShield from "@/components/streams/NsfwShield.vue"
const StreamElement = {
name: "StreamElement",
directives: {imagesLoaded},
components: {
ContentTimestamp, NsfwShield, ReactionsBar, AuthorBar,
},
......@@ -81,7 +79,11 @@ const StreamElement = {
},
},
mounted() {
this.layoutAfterDOMChange()
this.layoutAfterTwitterOEmbeds()
if (!this.$store.state.stream.stream.single) {
this.$redrawVueMasonry()
}
},
updated() {
if (!this.$store.state.stream.stream.single) {
......@@ -89,6 +91,18 @@ const StreamElement = {
}
},
methods: {
layoutAfterDOMChange() {
const post = document.getElementById(this.content.id)
if (post) {
const redraw = this.$redrawVueMasonry
// eslint-disable-next-line prefer-arrow-callback
const resizeObs = new MutationObserver(function () {
redraw()
})
// eslint-disable-next-line object-curly-newline
resizeObs.observe(post, {attributes: true, subtree: true, childList: true})
}
},
layoutAfterTwitterOEmbeds() {
// Hackity hack a Masonry redraw after hopefully Twitter oembeds are loaded...
// Let's try only add these once even if we have many oembed's
......@@ -104,28 +118,12 @@ const StreamElement = {
window.twttr.widgets.load(document.getElementsByClassName(".streams-container")[0])
}, 1000)
}
if (this.$store.state.stream.layoutDoneAfterTwitterOEmbeds) {
return
}
this.$store.dispatch("stream/setLayoutDoneAfterTwitterOEmbeds", true)
const c = this
setTimeout(() => {
c.onImageLoad()
}, 2000)
setTimeout(() => {
c.onImageLoad()
}, 4000)
}
},
loadMore() {
this.$store.dispatch("stream/disableLoadMore", this.content.id)
this.$emit("loadmore")
},
onImageLoad() {
if (!this.$store.state.stream.stream.single) {
this.$redrawVueMasonry()
}
},
},
}
......
......@@ -39,6 +39,7 @@
<script type="text/javascript" charset="utf-8">{% js_reverse_inline %}</script>
<script src="{% static 'dist/vue/js/app.js' %}"></script>
{% include "streams/includes/_twitter_widget.html" %}
{% include "streams/includes/_wordpress_widget.html" %}
{% endblock %}
{% block css %}
......
<script id="npmsg" type='text/javascript'>
! function(c, d) {
"use strict";
var e = !1,
n = !1;
if (d.querySelector)
if (c.addEventListener) e = !0;
if (c.wp = c.wp || {}, !c.wp.receiveEmbedMessage)
if (c.wp.receiveEmbedMessage = function(e) {
var t = e.data;
if (t)
if (t.secret || t.message || t.value)
if (!/[^a-zA-Z0-9]/.test(t.secret)) {
for (var r, a, i, s = d.querySelectorAll('iframe[data-secret="' + t.secret + '"]'), n = d.querySelectorAll('blockquote[data-secret="' + t.secret + '"]'), o = 0; o < n.length; o++) n[o].style.display = "none";
for (o = 0; o < s.length; o++)
if (r = s[o], e.source === r.contentWindow) {
if (r.removeAttribute("style"), "height" === t.message) {
if (1e3 < (i = parseInt(t.value, 10))) i = 1e3;
else if (~~i < 200) i = 200;
r.height = i
}
if ("link" === t.message)
if (a = d.createElement("a"), i = d.createElement("a"), a.href = r.getAttribute("src"), i.href = t.value, i.host === a.host)
if (d.activeElement === r) c.top.location.href = t.value
}
}
}, e) c.addEventListener("message", c.wp.receiveEmbedMessage, !1), d.addEventListener("DOMContentLoaded", t, !1), c.addEventListener("load", t, !1);
function t() {
if (!n) {
n = !0;
for (var e, t, r = -1 !== navigator.appVersion.indexOf("MSIE 10"), a = !!navigator.userAgent.match(/Trident.*rv:11\./), i = d.querySelectorAll("iframe.wp-embedded-content"), s = 0; s < i.length; s++) {
if (!(e = i[s]).getAttribute("data-secret")) t = Math.random().toString(36).substr(2, 10), e.src += "#?secret=" + t, e.setAttribute("data-secret", t);
if (r || a)(t = e.cloneNode(!0)).removeAttribute("security"), e.parentNode.replaceChild(t, e)
}
}
}
}(window, document);
</script>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment