parent
5292b8880e
commit
8d306ce466
34
packages/app/src/Components/Embed/GenericPlayer.tsx
Normal file
34
packages/app/src/Components/Embed/GenericPlayer.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import Icon from "../Icons/Icon";
|
||||
import { ProxyImg } from "../ProxyImg";
|
||||
|
||||
export default function GenericPlayer({ url, poster }: { url: string; poster: string }) {
|
||||
const [play, setPlay] = useState(false);
|
||||
|
||||
if (!play) {
|
||||
return (
|
||||
<div
|
||||
className="relative aspect-video"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setPlay(true);
|
||||
}}>
|
||||
<ProxyImg className="absolute" src={poster} />
|
||||
<div className="absolute w-full h-full opacity-0 hover:opacity-100 hover:bg-black/30 flex items-center justify-center transition">
|
||||
<Icon name="play-square-outline" size={50} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<iframe
|
||||
className="aspect-video w-full"
|
||||
src={url}
|
||||
frameBorder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowFullScreen={true}
|
||||
/>
|
||||
);
|
||||
}
|
@ -38,7 +38,9 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.link-preview-image {
|
||||
.link-preview-container img,
|
||||
.link-preview-container video,
|
||||
.link-preview-container iframe {
|
||||
margin: 0 0 15px 0 !important;
|
||||
border-radius: 0 !important;
|
||||
background-image: var(--img-url);
|
||||
|
@ -1,12 +1,14 @@
|
||||
import "./LinkPreview.css";
|
||||
|
||||
import { CSSProperties, useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { LRUCache } from "typescript-lru-cache";
|
||||
|
||||
import { MediaElement } from "@/Components/Embed/MediaElement";
|
||||
import Spinner from "@/Components/Icons/Spinner";
|
||||
import { LinkPreviewData, NostrServices } from "@/External/NostrServices";
|
||||
import useImgProxy from "@/Hooks/useImgProxy";
|
||||
|
||||
import { ProxyImg } from "../ProxyImg";
|
||||
import GenericPlayer from "./GenericPlayer";
|
||||
|
||||
async function fetchUrlPreviewInfo(url: string) {
|
||||
const api = new NostrServices("https://nostr.api.v0l.io");
|
||||
@ -23,7 +25,6 @@ const cache = new LRUCache<string, LinkPreviewData>({
|
||||
|
||||
const LinkPreview = ({ url }: { url: string }) => {
|
||||
const [preview, setPreview] = useState<LinkPreviewData | null>(cache.get(url));
|
||||
const { proxy } = useImgProxy();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
@ -59,6 +60,9 @@ const LinkPreview = ({ url }: { url: string }) => {
|
||||
if (link && videoType.startsWith("video/")) {
|
||||
return <MediaElement url={link} mime={videoType} />;
|
||||
}
|
||||
if (link && videoType.startsWith("text/html") && preview?.image) {
|
||||
return <GenericPlayer url={link} poster={preview?.image} />;
|
||||
}
|
||||
}
|
||||
if (type?.startsWith("image")) {
|
||||
const urlTags = ["og:image:secure_url", "og:image:url", "og:image"];
|
||||
@ -69,9 +73,7 @@ const LinkPreview = ({ url }: { url: string }) => {
|
||||
}
|
||||
}
|
||||
if (preview?.image) {
|
||||
const backgroundImage = preview?.image ? `url(${proxy(preview?.image)})` : "";
|
||||
const style = { "--img-url": backgroundImage } as CSSProperties;
|
||||
return <div className="link-preview-image" style={style}></div>;
|
||||
return <ProxyImg src={preview?.image} />;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -4,13 +4,7 @@ const TwitchEmbed = ({ link }: { link: string }) => {
|
||||
const args = `?channel=${channel}&parent=${window.location.hostname}&muted=true`;
|
||||
return (
|
||||
<>
|
||||
<iframe
|
||||
src={`https://player.twitch.tv/${args}`}
|
||||
className="w-max"
|
||||
allowFullScreen={true}
|
||||
// eslint-disable-next-line react/no-unknown-property
|
||||
credentialless=""
|
||||
/>
|
||||
<iframe src={`https://player.twitch.tv/${args}`} className="w-max" allowFullScreen={true} />
|
||||
<a href={link} target="_blank" rel="noreferrer" onClick={e => e.stopPropagation()} className="ext">
|
||||
{link}
|
||||
</a>
|
||||
|
@ -83,7 +83,7 @@ export function Note(props: NoteProps) {
|
||||
<div className="body" onClick={e => goToEvent(e, ev)}>
|
||||
<NoteText {...props} translated={translated} showTranslation={showTranslation} />
|
||||
{translated && <TranslationInfo translated={translated} setShowTranslation={setShowTranslation} />}
|
||||
{ev.kind === EventKind.Polls && <Poll ev={ev} />}
|
||||
{ev.kind === EventKind.Polls && <Poll ev={ev} zaps={[]} />}
|
||||
{optionsMerged.showFooter && (
|
||||
<div className="mt-4">
|
||||
<NoteFooter ev={ev} replyCount={props.threadChains?.get(chainKey(ev))?.length} />
|
||||
|
@ -380,17 +380,25 @@ export class Query extends EventEmitter<QueryEvents> {
|
||||
}
|
||||
|
||||
#canSendQuery(c: Connection, q: BuiltRawReqFilter) {
|
||||
// query is not for this relay
|
||||
if (q.relay && q.relay !== c.Address) {
|
||||
return false;
|
||||
}
|
||||
// cannot send unless relay is tagged on ephemeral relay connection
|
||||
if (!q.relay && c.Ephemeral) {
|
||||
this.#log("Cant send non-specific REQ to ephemeral connection %O %O %O", q, q.relay, c);
|
||||
return false;
|
||||
}
|
||||
// search not supported, cant send
|
||||
if (q.filters.some(a => a.search) && !c.supportsNip(Nips.Search)) {
|
||||
this.#log("Cant send REQ to non-search relay", c.Address);
|
||||
return false;
|
||||
}
|
||||
// query already closed, cant send
|
||||
if (this.canRemove()) {
|
||||
this.#log("Cant send REQ when query is closed", this.id, q);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user