replied note auto height, resized feed imgs

This commit is contained in:
Martti Malmi 2024-01-11 08:55:43 +02:00
parent 21e1202b97
commit 76d3c78c0a
5 changed files with 26 additions and 9 deletions

View File

@ -11,6 +11,7 @@ interface MediaElementProps {
url: string; url: string;
meta?: IMeta; meta?: IMeta;
onMediaClick?: (e: React.MouseEvent<HTMLImageElement>) => void; onMediaClick?: (e: React.MouseEvent<HTMLImageElement>) => void;
size?: number;
} }
interface AudioElementProps { interface AudioElementProps {
@ -25,6 +26,7 @@ interface VideoElementProps {
interface ImageElementProps { interface ImageElementProps {
url: string; url: string;
meta?: IMeta; meta?: IMeta;
size?: number;
onMediaClick?: (e: React.MouseEvent<HTMLImageElement>) => void; onMediaClick?: (e: React.MouseEvent<HTMLImageElement>) => void;
} }
@ -32,7 +34,7 @@ const AudioElement = ({ url }: AudioElementProps) => {
return <audio key={url} src={url} controls />; return <audio key={url} src={url} controls />;
}; };
const ImageElement = ({ url, meta, onMediaClick }: ImageElementProps) => { const ImageElement = ({ url, meta, onMediaClick, size }: ImageElementProps) => {
const imageRef = useRef<HTMLImageElement | null>(null); const imageRef = useRef<HTMLImageElement | null>(null);
const style = useMemo(() => { const style = useMemo(() => {
const style = {} as CSSProperties; const style = {} as CSSProperties;
@ -51,6 +53,7 @@ const ImageElement = ({ url, meta, onMediaClick }: ImageElementProps) => {
<ProxyImg <ProxyImg
key={url} key={url}
src={url} src={url}
size={size}
sha256={meta?.sha256} sha256={meta?.sha256}
onClick={onMediaClick} onClick={onMediaClick}
className={classNames("max-h-[80vh] w-full h-full object-contain object-center", { className={classNames("max-h-[80vh] w-full h-full object-contain object-center", {
@ -102,7 +105,7 @@ const VideoElement = ({ url }: VideoElementProps) => {
export function MediaElement(props: MediaElementProps) { export function MediaElement(props: MediaElementProps) {
if (props.mime.startsWith("image/")) { if (props.mime.startsWith("image/")) {
return <ImageElement url={props.url} meta={props.meta} onMediaClick={props.onMediaClick} />; return <ImageElement url={props.url} meta={props.meta} onMediaClick={props.onMediaClick} size={props.size} />;
} else if (props.mime.startsWith("audio/")) { } else if (props.mime.startsWith("audio/")) {
return <AudioElement url={props.url} />; return <AudioElement url={props.url} />;
} else if (props.mime.startsWith("video/")) { } else if (props.mime.startsWith("video/")) {

View File

@ -612,7 +612,7 @@ export function NoteCreator() {
<h4> <h4>
<FormattedMessage defaultMessage="Reply To" id="8ED/4u" /> <FormattedMessage defaultMessage="Reply To" id="8ED/4u" />
</h4> </h4>
<div className="h-64 overflow-y-auto"> <div className="max-h-64 overflow-y-auto">
<Note data={note.replyTo} options={replyToNoteOptions} /> <Note data={note.replyTo} options={replyToNoteOptions} />
</div> </div>
<hr className="border-border-color border-1 -mx-6" /> <hr className="border-border-color border-1 -mx-6" />
@ -623,7 +623,7 @@ export function NoteCreator() {
<h4> <h4>
<FormattedMessage defaultMessage="Quote Repost" id="C7642/" /> <FormattedMessage defaultMessage="Quote Repost" id="C7642/" />
</h4> </h4>
<div className="h-64 overflow-y-auto"> <div className="max-h-64 overflow-y-auto">
<Note data={note.quote} options={quoteNoteOptions} /> <Note data={note.quote} options={quoteNoteOptions} />
</div> </div>
<hr className="border-border-color border-1 -mx-6" /> <hr className="border-border-color border-1 -mx-6" />

View File

@ -12,6 +12,7 @@ interface RevealMediaProps {
link: string; link: string;
onMediaClick?: (e: React.MouseEvent<HTMLImageElement>) => void; onMediaClick?: (e: React.MouseEvent<HTMLImageElement>) => void;
meta?: IMeta; meta?: IMeta;
size?: number;
} }
export default function RevealMedia(props: RevealMediaProps) { export default function RevealMedia(props: RevealMediaProps) {
@ -73,6 +74,7 @@ export default function RevealMedia(props: RevealMediaProps) {
url={url.toString()} url={url.toString()}
onMediaClick={props.onMediaClick} onMediaClick={props.onMediaClick}
meta={props.meta} meta={props.meta}
size={props.size}
/> />
</Reveal> </Reveal>
); );
@ -83,6 +85,7 @@ export default function RevealMedia(props: RevealMediaProps) {
url={url.toString()} url={url.toString()}
onMediaClick={props.onMediaClick} onMediaClick={props.onMediaClick}
meta={props.meta} meta={props.meta}
size={props.size}
/> />
); );
} }

View File

@ -30,6 +30,8 @@ export interface TextProps {
onClick?: (e: React.MouseEvent) => void; onClick?: (e: React.MouseEvent) => void;
} }
const baseImageWidth = 910;
const gridConfigMap = new Map<number, number[][]>([ const gridConfigMap = new Map<number, number[][]>([
[1, [[4, 3]]], [1, [[4, 3]]],
[ [
@ -137,14 +139,16 @@ export default function Text({
</a> </a>
); );
const RevealMediaInstance = ({ content, data }: { content: string; data?: object }) => { const RevealMediaInstance = ({ content, data, size }: { content: string; data?: object; size?: number }) => {
const imeta = data as IMeta | undefined; const imeta = data as IMeta | undefined;
return ( return (
<RevealMedia <RevealMedia
key={content} key={content}
link={content} link={content}
creator={creator} creator={creator}
meta={imeta} meta={imeta}
size={size}
onMediaClick={e => { onMediaClick={e => {
if (!disableMediaSpotlight) { if (!disableMediaSpotlight) {
e.stopPropagation(); e.stopPropagation();
@ -196,7 +200,13 @@ export default function Text({
} }
} }
if (galleryImages.length === 1) { if (galleryImages.length === 1) {
chunks.push(<RevealMediaInstance content={galleryImages[0].content} data={galleryImages[0].data} />); chunks.push(
<RevealMediaInstance
content={galleryImages[0].content}
data={galleryImages[0].data}
size={baseImageWidth}
/>,
);
} else { } else {
// We build a grid layout to render the grouped images // We build a grid layout to render the grouped images
const imagesWithGridConfig = galleryImages.map((gi, index) => { const imagesWithGridConfig = galleryImages.map((gi, index) => {
@ -215,6 +225,7 @@ export default function Text({
height, height,
}; };
}); });
const size = Math.floor(baseImageWidth / Math.min(4, Math.floor(Math.sqrt(galleryImages.length))));
const gallery = ( const gallery = (
<div className="-mx-4 md:mx-0 my-2 gallery"> <div className="-mx-4 md:mx-0 my-2 gallery">
{imagesWithGridConfig.map(img => ( {imagesWithGridConfig.map(img => (
@ -226,7 +237,7 @@ export default function Text({
gridColumn: `span ${img.gridColumn}`, gridColumn: `span ${img.gridColumn}`,
gridRow: `span ${img.gridRow}`, gridRow: `span ${img.gridRow}`,
}}> }}>
<RevealMediaInstance content={img.content} data={img.data} /> <RevealMediaInstance content={img.content} data={img.data} size={size} />
</div> </div>
))} ))}
</div> </div>
@ -243,7 +254,7 @@ export default function Text({
if (disableMedia ?? false) { if (disableMedia ?? false) {
chunks.push(<DisableMedia content={element.content} />); chunks.push(<DisableMedia content={element.content} />);
} else { } else {
chunks.push(<RevealMediaInstance content={element.content} data={element.data} />); chunks.push(<RevealMediaInstance content={element.content} data={element.data} size={baseImageWidth} />);
} }
} }
if (element.type === "invoice") { if (element.type === "invoice") {

View File

@ -69,7 +69,7 @@ export default function FollowedBy({ pubkey }: { pubkey: HexKey }) {
<FormattedMessage defaultMessage="Not followed by anyone you follow" id="IgsWFG" /> <FormattedMessage defaultMessage="Not followed by anyone you follow" id="IgsWFG" />
</div> </div>
)} )}
{followDistance === 3 && ( {followDistance === 3 && ( // TODO "followed by friends of {n} friends"
<div className="text-gray-light"> <div className="text-gray-light">
<FormattedMessage defaultMessage="Followed by friends of friends" id="2oCF7O" /> <FormattedMessage defaultMessage="Followed by friends of friends" id="2oCF7O" />
</div> </div>