mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-02-25 01:08:50 +01:00
Handle cards with iframe embeds
This commit is contained in:
parent
16e2ac9bce
commit
147a12cbcb
5 changed files with 127 additions and 34 deletions
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 AccountSheet from './account-sheet';
|
||||||
import Compose from './compose';
|
import Compose from './compose';
|
||||||
import Drafts from './drafts';
|
import Drafts from './drafts';
|
||||||
|
import EmbedModal from './embed-modal';
|
||||||
import GenericAccounts from './generic-accounts';
|
import GenericAccounts from './generic-accounts';
|
||||||
import MediaAltModal from './media-alt-modal';
|
import MediaAltModal from './media-alt-modal';
|
||||||
import MediaModal from './media-modal';
|
import MediaModal from './media-modal';
|
||||||
|
@ -200,6 +201,21 @@ export default function Modals() {
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</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;
|
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))) {
|
if (hasText && (image || (type === 'photo' && blurhash))) {
|
||||||
const domain = new URL(url).hostname
|
const domain = new URL(url).hostname
|
||||||
.replace(/^www\./, '')
|
.replace(/^www\./, '')
|
||||||
|
@ -2016,6 +2030,7 @@ function Card({ card, selfReferential, instance }) {
|
||||||
'--average-color':
|
'--average-color':
|
||||||
rgbAverageColor && `rgb(${rgbAverageColor.join(',')})`,
|
rgbAverageColor && `rgb(${rgbAverageColor.join(',')})`,
|
||||||
}}
|
}}
|
||||||
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
<div class="card-image">
|
<div class="card-image">
|
||||||
<img
|
<img
|
||||||
|
@ -2054,6 +2069,7 @@ function Card({ card, selfReferential, instance }) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="nofollow noopener noreferrer"
|
rel="nofollow noopener noreferrer"
|
||||||
class="card photo"
|
class="card photo"
|
||||||
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={embedUrl}
|
src={embedUrl}
|
||||||
|
@ -2068,42 +2084,46 @@ function Card({ card, selfReferential, instance }) {
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
} else if (type === 'video') {
|
} else {
|
||||||
if (/youtube/i.test(providerName)) {
|
if (type === 'video') {
|
||||||
// Get ID from e.g. https://www.youtube.com/watch?v=[VIDEO_ID]
|
if (/youtube/i.test(providerName)) {
|
||||||
const videoID = url.match(/watch\?v=([^&]+)/)?.[1];
|
// Get ID from e.g. https://www.youtube.com/watch?v=[VIDEO_ID]
|
||||||
if (videoID) {
|
const videoID = url.match(/watch\?v=([^&]+)/)?.[1];
|
||||||
return <lite-youtube videoid={videoID} nocookie></lite-youtube>;
|
if (videoID) {
|
||||||
|
return <lite-youtube videoid={videoID} nocookie></lite-youtube>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// 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
|
||||||
|
href={cardStatusURL || url}
|
||||||
|
target={cardStatusURL ? null : '_blank'}
|
||||||
|
rel="nofollow noopener noreferrer"
|
||||||
|
class={`card link no-image`}
|
||||||
|
lang={language}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
<div class="meta-container">
|
||||||
|
<p class="meta domain">
|
||||||
|
<Icon icon="link" size="s" /> <span>{domain}</span>
|
||||||
|
</p>
|
||||||
|
<p class="title">{title}</p>
|
||||||
|
<p class="meta">{description || providerName || authorName}</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return (
|
|
||||||
<div
|
|
||||||
class="card video"
|
|
||||||
style={{
|
|
||||||
aspectRatio: `${width}/${height}`,
|
|
||||||
}}
|
|
||||||
dangerouslySetInnerHTML={{ __html: html }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else if (hasText && !image) {
|
|
||||||
const domain = new URL(url).hostname.replace(/^www\./, '');
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href={cardStatusURL || url}
|
|
||||||
target={cardStatusURL ? null : '_blank'}
|
|
||||||
rel="nofollow noopener noreferrer"
|
|
||||||
class={`card link no-image`}
|
|
||||||
lang={language}
|
|
||||||
>
|
|
||||||
<div class="meta-container">
|
|
||||||
<p class="meta domain">
|
|
||||||
<Icon icon="link" size="s" /> <span>{domain}</span>
|
|
||||||
</p>
|
|
||||||
<p class="title">{title}</p>
|
|
||||||
<p class="meta">{description || providerName || authorName}</p>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ const states = proxy({
|
||||||
showKeyboardShortcutsHelp: false,
|
showKeyboardShortcutsHelp: false,
|
||||||
showGenericAccounts: false,
|
showGenericAccounts: false,
|
||||||
showMediaAlt: false,
|
showMediaAlt: false,
|
||||||
|
showEmbedModal: false,
|
||||||
// Shortcuts
|
// Shortcuts
|
||||||
shortcuts: [],
|
shortcuts: [],
|
||||||
// Settings
|
// Settings
|
||||||
|
@ -151,6 +152,7 @@ export function hideAllModals() {
|
||||||
states.showKeyboardShortcutsHelp = false;
|
states.showKeyboardShortcutsHelp = false;
|
||||||
states.showGenericAccounts = false;
|
states.showGenericAccounts = false;
|
||||||
states.showMediaAlt = false;
|
states.showMediaAlt = false;
|
||||||
|
states.showEmbedModal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function statusKey(id, instance) {
|
export function statusKey(id, instance) {
|
||||||
|
|
Loading…
Reference in a new issue