Handle cards with iframe embeds
This commit is contained in:
parent
16e2ac9bce
commit
147a12cbcb
27
src/components/embed-modal.css
Normal file
27
src/components/embed-modal.css
Normal file
|
@ -0,0 +1,27 @@
|
|||
.embed-modal-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
pointer-events: none;
|
||||
|
||||
.top-controls {
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: space-between;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.embed-content {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
iframe {
|
||||
pointer-events: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
28
src/components/embed-modal.jsx
Normal file
28
src/components/embed-modal.jsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
import './embed-modal.css';
|
||||
|
||||
import Icon from './icon';
|
||||
|
||||
function EmbedModal({ html, url, onClose = () => {} }) {
|
||||
return (
|
||||
<div class="embed-modal-container">
|
||||
<div class="top-controls">
|
||||
<button type="button" class="light" onClick={() => onClose()}>
|
||||
<Icon icon="x" />
|
||||
</button>
|
||||
{url && (
|
||||
<a
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="button plain"
|
||||
>
|
||||
<span>Open link</span> <Icon icon="external" />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<div class="embed-content" dangerouslySetInnerHTML={{ __html: html }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default EmbedModal;
|
|
@ -10,6 +10,7 @@ import states from '../utils/states';
|
|||
import AccountSheet from './account-sheet';
|
||||
import Compose from './compose';
|
||||
import Drafts from './drafts';
|
||||
import EmbedModal from './embed-modal';
|
||||
import GenericAccounts from './generic-accounts';
|
||||
import MediaAltModal from './media-alt-modal';
|
||||
import MediaModal from './media-modal';
|
||||
|
@ -200,6 +201,21 @@ export default function Modals() {
|
|||
/>
|
||||
</Modal>
|
||||
)}
|
||||
{!!snapStates.showEmbedModal && (
|
||||
<Modal
|
||||
onClose={() => {
|
||||
states.showEmbedModal = false;
|
||||
}}
|
||||
>
|
||||
<EmbedModal
|
||||
html={snapStates.showEmbedModal.html}
|
||||
url={snapStates.showEmbedModal.url}
|
||||
onClose={() => {
|
||||
states.showEmbedModal = false;
|
||||
}}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1984,6 +1984,20 @@ function Card({ card, selfReferential, instance }) {
|
|||
|
||||
if (snapStates.unfurledLinks[url]) return null;
|
||||
|
||||
const hasIframeHTML = /<iframe/i.test(html);
|
||||
const handleClick = useCallback(
|
||||
(e) => {
|
||||
if (hasIframeHTML) {
|
||||
e.preventDefault();
|
||||
states.showEmbedModal = {
|
||||
html,
|
||||
url: url || embedUrl,
|
||||
};
|
||||
}
|
||||
},
|
||||
[hasIframeHTML],
|
||||
);
|
||||
|
||||
if (hasText && (image || (type === 'photo' && blurhash))) {
|
||||
const domain = new URL(url).hostname
|
||||
.replace(/^www\./, '')
|
||||
|
@ -2016,6 +2030,7 @@ function Card({ card, selfReferential, instance }) {
|
|||
'--average-color':
|
||||
rgbAverageColor && `rgb(${rgbAverageColor.join(',')})`,
|
||||
}}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div class="card-image">
|
||||
<img
|
||||
|
@ -2054,6 +2069,7 @@ function Card({ card, selfReferential, instance }) {
|
|||
target="_blank"
|
||||
rel="nofollow noopener noreferrer"
|
||||
class="card photo"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<img
|
||||
src={embedUrl}
|
||||
|
@ -2068,7 +2084,8 @@ function Card({ card, selfReferential, instance }) {
|
|||
/>
|
||||
</a>
|
||||
);
|
||||
} else if (type === 'video') {
|
||||
} else {
|
||||
if (type === 'video') {
|
||||
if (/youtube/i.test(providerName)) {
|
||||
// Get ID from e.g. https://www.youtube.com/watch?v=[VIDEO_ID]
|
||||
const videoID = url.match(/watch\?v=([^&]+)/)?.[1];
|
||||
|
@ -2076,16 +2093,17 @@ function Card({ card, selfReferential, instance }) {
|
|||
return <lite-youtube videoid={videoID} nocookie></lite-youtube>;
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div
|
||||
class="card video"
|
||||
style={{
|
||||
aspectRatio: `${width}/${height}`,
|
||||
}}
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
/>
|
||||
);
|
||||
} else if (hasText && !image) {
|
||||
// return (
|
||||
// <div
|
||||
// class="card video"
|
||||
// style={{
|
||||
// aspectRatio: `${width}/${height}`,
|
||||
// }}
|
||||
// dangerouslySetInnerHTML={{ __html: html }}
|
||||
// />
|
||||
// );
|
||||
}
|
||||
if (hasText && !image) {
|
||||
const domain = new URL(url).hostname.replace(/^www\./, '');
|
||||
return (
|
||||
<a
|
||||
|
@ -2094,6 +2112,7 @@ function Card({ card, selfReferential, instance }) {
|
|||
rel="nofollow noopener noreferrer"
|
||||
class={`card link no-image`}
|
||||
lang={language}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div class="meta-container">
|
||||
<p class="meta domain">
|
||||
|
@ -2106,6 +2125,7 @@ function Card({ card, selfReferential, instance }) {
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function EditedAtModal({
|
||||
statusID,
|
||||
|
|
|
@ -50,6 +50,7 @@ const states = proxy({
|
|||
showKeyboardShortcutsHelp: false,
|
||||
showGenericAccounts: false,
|
||||
showMediaAlt: false,
|
||||
showEmbedModal: false,
|
||||
// Shortcuts
|
||||
shortcuts: [],
|
||||
// Settings
|
||||
|
@ -151,6 +152,7 @@ export function hideAllModals() {
|
|||
states.showKeyboardShortcutsHelp = false;
|
||||
states.showGenericAccounts = false;
|
||||
states.showMediaAlt = false;
|
||||
states.showEmbedModal = false;
|
||||
}
|
||||
|
||||
export function statusKey(id, instance) {
|
||||
|
|
Loading…
Reference in a new issue