forked from Kieran/snort
spotlight media & thread modals
This commit is contained in:
parent
fabf0f372f
commit
8dc0c28377
@ -3,12 +3,13 @@ import ProfileImage from "@/Element/User/ProfileImage";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import Icon from "@/Icons/Icon";
|
||||
import { NostrLink, TaggedNostrEvent } from "@snort/system";
|
||||
import { ReactNode } from "react";
|
||||
import { ReactNode, useState } from "react";
|
||||
import { TimelineFragment } from "@/Element/Feed/TimelineFragment";
|
||||
import { transformTextCached } from "@/Hooks/useTextTransformCache";
|
||||
import useImgProxy from "@/Hooks/useImgProxy";
|
||||
import { Link } from "react-router-dom";
|
||||
import { DisplayAs } from "@/Element/Feed/DisplayAsSelector";
|
||||
import { SpotlightThreadModal } from "@/Element/Spotlight/SpotlightThreadModal";
|
||||
|
||||
export interface TimelineRendererProps {
|
||||
frags: Array<TimelineFragment>;
|
||||
@ -27,6 +28,7 @@ export interface TimelineRendererProps {
|
||||
export function TimelineRenderer(props: TimelineRendererProps) {
|
||||
const { ref, inView } = useInView();
|
||||
const { proxy } = useImgProxy();
|
||||
const [modalThread, setModalThread] = useState<NostrLink | undefined>(undefined);
|
||||
|
||||
const renderNotes = () => {
|
||||
return props.frags.map(frag => (
|
||||
@ -57,6 +59,9 @@ export function TimelineRenderer(props: TimelineRendererProps) {
|
||||
if (props.noteOnClick) {
|
||||
props.noteOnClick(e);
|
||||
clickEvent.preventDefault();
|
||||
} else if (window.innerWidth >= 768) {
|
||||
setModalThread(NostrLink.fromEvent(e));
|
||||
clickEvent.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
@ -118,6 +123,13 @@ export function TimelineRenderer(props: TimelineRendererProps) {
|
||||
</>
|
||||
)}
|
||||
{props.displayAs === "grid" ? renderGrid() : renderNotes()}
|
||||
{modalThread && (
|
||||
<SpotlightThreadModal
|
||||
thread={modalThread}
|
||||
onClose={() => setModalThread(undefined)}
|
||||
onBack={() => setModalThread(undefined)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { ReactNode, useEffect } from "react";
|
||||
export interface ModalProps {
|
||||
id: string;
|
||||
className?: string;
|
||||
bodyClassName?: string;
|
||||
onClose?: (e: React.MouseEvent | KeyboardEvent) => void;
|
||||
onClick?: (e: React.MouseEvent) => void;
|
||||
children: ReactNode;
|
||||
@ -60,7 +61,7 @@ export default function Modal(props: ModalProps) {
|
||||
|
||||
return createPortal(
|
||||
<div className={`modal${props.className ? ` ${props.className}` : ""}`} onClick={props.onClose}>
|
||||
<div className="modal-body" onClick={props.onClose}>
|
||||
<div className={props.bodyClassName || "modal-body"} onClick={props.onClose}>
|
||||
<div
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
|
@ -1,46 +0,0 @@
|
||||
.modal.spotlight .modal-body {
|
||||
border: none;
|
||||
border-radius: unset;
|
||||
width: unset;
|
||||
height: unset;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.spotlight img,
|
||||
.spotlight video {
|
||||
max-width: 100vw !important;
|
||||
max-height: 99vh !important;
|
||||
aspect-ratio: unset !important;
|
||||
width: unset !important;
|
||||
}
|
||||
|
||||
.spotlight .details {
|
||||
text-align: right;
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
right: 28px;
|
||||
gap: 18px;
|
||||
display: flex;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.spotlight .left {
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
top: 50vh;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.spotlight .right {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
top: 50vh;
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
import "./SpotlightMedia.css";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import Modal from "@/Element/Modal";
|
||||
import Icon from "@/Icons/Icon";
|
||||
@ -60,16 +59,16 @@ export function SpotlightMedia(props: SpotlightMediaProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="spotlight">
|
||||
<ProxyImg src={image} />
|
||||
<div className="details">
|
||||
{props.images.length > 1 && `${idx + 1}/${props.images.length}`}
|
||||
<>
|
||||
<ProxyImg src={image} className="max-h-screen max-w-full" />
|
||||
<div className="select-none absolute flex flex-row items-center gap-4 cursor-pointer left-0 top-0 p-4">
|
||||
<Icon name="x-close" size={24} onClick={props.onClose} />
|
||||
{props.images.length > 1 && `${idx + 1}/${props.images.length}`}
|
||||
</div>
|
||||
{props.images.length > 1 && (
|
||||
<>
|
||||
<Icon
|
||||
className="left"
|
||||
className="absolute left-2 top-1/2 rotate-180 cursor-pointer"
|
||||
name="arrowFront"
|
||||
size={24}
|
||||
onClick={e => {
|
||||
@ -78,7 +77,7 @@ export function SpotlightMedia(props: SpotlightMediaProps) {
|
||||
}}
|
||||
/>
|
||||
<Icon
|
||||
className="right"
|
||||
className="absolute right-2 top-1/2 cursor-pointer"
|
||||
name="arrowFront"
|
||||
size={24}
|
||||
onClick={e => {
|
||||
@ -88,13 +87,18 @@ export function SpotlightMedia(props: SpotlightMediaProps) {
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function SpotlightMediaModal(props: SpotlightMediaProps) {
|
||||
return (
|
||||
<Modal id="spotlight" onClick={props.onClose} onClose={props.onClose} className="spotlight">
|
||||
<Modal
|
||||
id="spotlight"
|
||||
onClick={props.onClose}
|
||||
onClose={props.onClose}
|
||||
className="spotlight"
|
||||
bodyClassName="h-screen w-screen flex items-center justify-center">
|
||||
<SpotlightMedia {...props} />
|
||||
</Modal>
|
||||
);
|
||||
|
@ -11,11 +11,15 @@ export function SpotlightThreadModal(props: { thread: NostrLink; onClose?: () =>
|
||||
const onBack = () => props.onBack?.();
|
||||
|
||||
return (
|
||||
<Modal id="thread-overlay" onClose={onClose} className="thread-overlay thread">
|
||||
<Modal id="thread-overlay" onClose={onClose} bodyClassName={"flex flex-1"}>
|
||||
<ThreadContextWrapper link={props.thread}>
|
||||
<SpotlightFromThread onClose={onClose} />
|
||||
<div>
|
||||
<Thread onBack={onBack} disableSpotlight={true} />
|
||||
<div className="flex flex-row h-screen w-screen">
|
||||
<div className="flex w-2/3 items-center justify-center overflow-hidden">
|
||||
<SpotlightFromThread onClose={onClose} />
|
||||
</div>
|
||||
<div className="flex w-1/3 flex-shrink-0 overflow-y-auto bg-bg-color">
|
||||
<Thread onBack={onBack} disableSpotlight={true} />
|
||||
</div>
|
||||
</div>
|
||||
</ThreadContextWrapper>
|
||||
</Modal>
|
||||
|
@ -36,59 +36,3 @@
|
||||
.deck-layout .deck-cols > div > div:not(:first-of-type) {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.modal.thread-overlay > .modal-body {
|
||||
background-color: unset;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
--border-color: #3a3a3a;
|
||||
}
|
||||
|
||||
.modal.thread-overlay > .modal-body > div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-radius: unset;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.modal.thread-overlay.thread > .modal-body > div > div:last-of-type {
|
||||
width: 550px;
|
||||
min-width: 550px;
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
background-color: var(--gray-superdark);
|
||||
}
|
||||
|
||||
.modal.thread-overlay.long-form > .modal-body > div > div:last-of-type {
|
||||
width: 660px;
|
||||
height: calc(100vh - 48px);
|
||||
padding: 48px 56px 0 56px;
|
||||
overflow-y: auto;
|
||||
background-color: var(--gray-superdark);
|
||||
}
|
||||
|
||||
.thread-overlay .spotlight {
|
||||
flex-grow: 1;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.thread-overlay .spotlight .details {
|
||||
right: calc(28px + 550px + 16px);
|
||||
}
|
||||
|
||||
.thread-overlay .spotlight .right {
|
||||
right: calc(24px + 550px + 16px);
|
||||
}
|
||||
|
||||
.thread-overlay .spotlight img,
|
||||
.thread-overlay .spotlight video {
|
||||
max-width: calc(100vw - 550px - 16px);
|
||||
}
|
||||
|
||||
.thread-overlay .main-content {
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user