mirror of
https://github.com/spacebarchat/client.git
synced 2024-11-22 02:12:38 +01:00
implement image viewer modal
This commit is contained in:
parent
126eec5b64
commit
f720ce8975
@ -2,6 +2,7 @@
|
||||
// https://github.com/revoltchat/revite/blob/master/src/components/common/messaging/embed/Embed.tsx
|
||||
|
||||
import { APIEmbed, EmbedType } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import { modalController } from "../../controllers/modals";
|
||||
import styles from "./Embed.module.css";
|
||||
|
||||
interface Props {
|
||||
@ -111,7 +112,16 @@ function EmbedMedia({ embed, width, height, thumbnail }: Props) {
|
||||
src={url}
|
||||
loading="lazy"
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
onClick={() => window.open(url, "_blank")}
|
||||
onClick={() => {
|
||||
if (!embed.image) {
|
||||
console.error("embed has no image... wtf");
|
||||
return;
|
||||
}
|
||||
modalController.push({
|
||||
type: "image_viewer",
|
||||
attachment: embed.image,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else if (embed.thumbnail) {
|
||||
@ -123,7 +133,16 @@ function EmbedMedia({ embed, width, height, thumbnail }: Props) {
|
||||
src={url}
|
||||
loading="lazy"
|
||||
style={{ width, height }}
|
||||
onClick={() => window.open(url, "_blank")}
|
||||
onClick={() => {
|
||||
if (!embed.thumbnail) {
|
||||
console.error("embed has no thumbnail... wtf");
|
||||
return;
|
||||
}
|
||||
modalController.push({
|
||||
type: "image_viewer",
|
||||
attachment: embed.thumbnail,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { APIAttachment } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import styled from "styled-components";
|
||||
import { modalController } from "../../controllers/modals";
|
||||
import useLogger from "../../hooks/useLogger";
|
||||
import { calculateImageRatio, calculateScaledDimensions } from "../../utils/Message";
|
||||
import { getFileDetails, zoomFit } from "../../utils/Utils";
|
||||
@ -57,7 +58,12 @@ export default function MessageAttachment({ attachment, maxWidth, maxHeight }: A
|
||||
onClick={() => {
|
||||
if (!attachment.content_type?.startsWith("image")) return;
|
||||
const { width, height } = zoomFit(attachment.width!, attachment.height!);
|
||||
// TODO: preview modal
|
||||
modalController.push({
|
||||
type: "image_viewer",
|
||||
attachment,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{finalElement}
|
||||
|
@ -1,3 +0,0 @@
|
||||
export function AttachmentPreviewModal() {
|
||||
return null;
|
||||
}
|
36
src/components/modals/ImageViewerModal.tsx
Normal file
36
src/components/modals/ImageViewerModal.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import { APIAttachment, APIEmbedImage, APIEmbedThumbnail } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import styled from "styled-components";
|
||||
import { Modal } from "./ModalComponents";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
max-width: 90vw;
|
||||
max-height: 75vh;
|
||||
|
||||
img {
|
||||
width: auto;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
attachment: APIAttachment | APIEmbedImage | APIEmbedThumbnail;
|
||||
width?: number;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
export function ImageViewerModal(props: Props) {
|
||||
const width = props.width ?? props.attachment.width ?? 0;
|
||||
const height = props.height ?? props.attachment.height ?? 0;
|
||||
|
||||
return (
|
||||
<Modal {...props} transparent maxWidth="100vw" maxHeight="100vh" withoutCloseButton withEmptyActionBar>
|
||||
<Container>
|
||||
<img src={props.attachment.url} width={width} height={height} loading="eager" />
|
||||
</Container>
|
||||
</Modal>
|
||||
);
|
||||
}
|
@ -26,6 +26,7 @@ interface ModalProps {
|
||||
actions?: ModalAction[];
|
||||
disabled?: boolean;
|
||||
withEmptyActionBar?: boolean;
|
||||
withoutCloseButton?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -205,13 +206,15 @@ export function Modal({ title, description, ...props }: ModalProps) {
|
||||
<Portal>
|
||||
<ModalBase closing={closing} onClick={() => !props.nonDismissable && closeModal()}>
|
||||
<ModalWrapper {...props} onClick={(e) => e.stopPropagation()} actions={false}>
|
||||
<div style={{ position: "relative" }}>
|
||||
{!props.nonDismissable && (
|
||||
<ModalCloseWrapper onClick={closeModal}>
|
||||
<Icon icon="mdiClose" size={1} />
|
||||
</ModalCloseWrapper>
|
||||
)}
|
||||
</div>
|
||||
{!props.withoutCloseButton && (
|
||||
<div style={{ position: "relative" }}>
|
||||
{!props.nonDismissable && (
|
||||
<ModalCloseWrapper onClick={closeModal}>
|
||||
<Icon icon="mdiClose" size={1} />
|
||||
</ModalCloseWrapper>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{(title || description) && (
|
||||
<ModalHeader>
|
||||
{title && typeof title === "string" ? <ModalHeaderText>{title}</ModalHeaderText> : title}
|
||||
|
@ -1,11 +1,11 @@
|
||||
export * from "./AddServerModal";
|
||||
export * from "./AttachmentPreviewModal";
|
||||
export * from "./BanMemberModal";
|
||||
export * from "./CreateInviteModal";
|
||||
export * from "./CreateServerModal";
|
||||
export * from "./DeleteMessageModal";
|
||||
export * from "./ErrorModal";
|
||||
export * from "./ForgotPasswordModal";
|
||||
export * from "./ImageViewerModal";
|
||||
export * from "./JoinServerModal";
|
||||
export * from "./KickMemberModal";
|
||||
export * from "./LeaveServerModal";
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
CreateServerModal,
|
||||
DeleteMessageModal,
|
||||
ErrorModal,
|
||||
ImageViewerModal,
|
||||
JoinServerModal,
|
||||
KickMemberModal,
|
||||
LeaveServerModal,
|
||||
@ -162,7 +163,7 @@ export const modalController = new ModalControllerExtended({
|
||||
// custom_status: CustomStatus,
|
||||
delete_message: DeleteMessageModal,
|
||||
error: ErrorModal,
|
||||
// image_viewer: ImageViewer,
|
||||
image_viewer: ImageViewerModal,
|
||||
kick_member: KickMemberModal,
|
||||
// link_warning: LinkWarning,
|
||||
// mfa_flow: MFAFlow,
|
||||
|
@ -1,5 +1,6 @@
|
||||
// adapted from https://github.com/revoltchat/revite/blob/master/src/controllers/modals/types.ts
|
||||
|
||||
import { APIAttachment, APIEmbedImage, APIEmbedThumbnail } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import Channel from "../../stores/objects/Channel";
|
||||
import Guild from "../../stores/objects/Guild";
|
||||
import GuildMember from "../../stores/objects/GuildMember";
|
||||
@ -42,6 +43,12 @@ export type Modal = {
|
||||
type: "leave_server";
|
||||
target: Guild;
|
||||
}
|
||||
| {
|
||||
type: "image_viewer";
|
||||
attachment: APIAttachment | APIEmbedImage | APIEmbedThumbnail;
|
||||
width?: number;
|
||||
height?: number;
|
||||
}
|
||||
);
|
||||
|
||||
export type ModalProps<T extends Modal["type"]> = Modal & { type: T } & {
|
||||
|
Loading…
Reference in New Issue
Block a user