You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nostrweb/src/media.ts

115 lines
2.6 KiB
TypeScript

import { elem } from './utils/dom';
import { getNoxyUrl } from './utils/url';
export const parseJSON = (content: string): unknown => {
try {
return JSON.parse(content);
} catch(err) {
console.warn(err, content);
return null;
}
}
type FetchItem = {
href: string;
id: string;
relay: string;
};
type NoxyData = {
title: string;
descr: string;
images: string[];
};
const fetchQue: Array<FetchItem> = [];
let fetchPending: (null | Promise<NoxyData>) = null;
const fetchNext = (
href: string,
id: string,
relay: string,
) => {
const noxy = getNoxyUrl('meta', href, id, relay);
if (!noxy) {
return false;
}
const previewId = noxy.searchParams.toString();
if (fetchPending) {
fetchQue.push({href, id, relay});
return previewId;
}
fetchPending = fetch(noxy.href)
.then(data => {
if (data.status === 200) {
return data.json();
}
// fetchQue.push({href, id, relay}); // could try one more time
return Promise.reject(data);
})
.then(meta => {
const container = document.getElementById(previewId);
const content: Array<HTMLElement> = [];
if (meta.images[0]) {
const img = getNoxyUrl('data', meta.images[0], id, relay);
img && content.push(
elem('img', {
className: 'preview-image',
loading: 'lazy',
src: img.href,
})
);
}
if (meta.title) {
content.push(elem('h2', {className: 'preview-title'}, meta.title));
}
if (meta.descr) {
content.push(elem('p', {className: 'preview-descr'}, meta.descr))
}
if (container && content.length) {
container.append(elem('a', {href, rel: 'noopener noreferrer', target: '_blank'}, content));
container.classList.add('preview-loaded');
}
})
.finally(() => {
fetchPending = null;
if (fetchQue.length) {
const {href, id, relay} = fetchQue.shift() as FetchItem;
return fetchNext(href, id, relay);
}
})
.catch(err => err.text && err.text())
.then(errMsg => errMsg && console.warn(errMsg));
return previewId;
};
export const linkPreview = (
href: string,
id: string,
relay: string,
) => {
if ((/\.(gif|jpe?g|png)$/i).test(href)) {
const img = getNoxyUrl('data', href, id, relay);
if (!img) {
return null;
}
return elem('div', {},
[elem('img', {
className: 'preview-image-only',
loading: 'lazy',
src: img.href,
})]
);
}
const previewId = fetchNext(href, id, relay);
if (!previewId) {
return null;
}
return elem('div', {
className: 'preview',
id: previewId,
});
};