mirror of
https://github.com/spacebarchat/client.git
synced 2024-11-25 19:52:31 +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
|
// https://github.com/revoltchat/revite/blob/master/src/components/common/messaging/embed/Embed.tsx
|
||||||
|
|
||||||
import { APIEmbed, EmbedType } from "@spacebarchat/spacebar-api-types/v9";
|
import { APIEmbed, EmbedType } from "@spacebarchat/spacebar-api-types/v9";
|
||||||
|
import { modalController } from "../../controllers/modals";
|
||||||
import styles from "./Embed.module.css";
|
import styles from "./Embed.module.css";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -111,7 +112,16 @@ function EmbedMedia({ embed, width, height, thumbnail }: Props) {
|
|||||||
src={url}
|
src={url}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
style={{ width: "100%", height: "100%" }}
|
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) {
|
} else if (embed.thumbnail) {
|
||||||
@ -123,7 +133,16 @@ function EmbedMedia({ embed, width, height, thumbnail }: Props) {
|
|||||||
src={url}
|
src={url}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
style={{ width, height }}
|
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 { APIAttachment } from "@spacebarchat/spacebar-api-types/v9";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
import { modalController } from "../../controllers/modals";
|
||||||
import useLogger from "../../hooks/useLogger";
|
import useLogger from "../../hooks/useLogger";
|
||||||
import { calculateImageRatio, calculateScaledDimensions } from "../../utils/Message";
|
import { calculateImageRatio, calculateScaledDimensions } from "../../utils/Message";
|
||||||
import { getFileDetails, zoomFit } from "../../utils/Utils";
|
import { getFileDetails, zoomFit } from "../../utils/Utils";
|
||||||
@ -57,7 +58,12 @@ export default function MessageAttachment({ attachment, maxWidth, maxHeight }: A
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!attachment.content_type?.startsWith("image")) return;
|
if (!attachment.content_type?.startsWith("image")) return;
|
||||||
const { width, height } = zoomFit(attachment.width!, attachment.height!);
|
const { width, height } = zoomFit(attachment.width!, attachment.height!);
|
||||||
// TODO: preview modal
|
modalController.push({
|
||||||
|
type: "image_viewer",
|
||||||
|
attachment,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{finalElement}
|
{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[];
|
actions?: ModalAction[];
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
withEmptyActionBar?: boolean;
|
withEmptyActionBar?: boolean;
|
||||||
|
withoutCloseButton?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,13 +206,15 @@ export function Modal({ title, description, ...props }: ModalProps) {
|
|||||||
<Portal>
|
<Portal>
|
||||||
<ModalBase closing={closing} onClick={() => !props.nonDismissable && closeModal()}>
|
<ModalBase closing={closing} onClick={() => !props.nonDismissable && closeModal()}>
|
||||||
<ModalWrapper {...props} onClick={(e) => e.stopPropagation()} actions={false}>
|
<ModalWrapper {...props} onClick={(e) => e.stopPropagation()} actions={false}>
|
||||||
<div style={{ position: "relative" }}>
|
{!props.withoutCloseButton && (
|
||||||
{!props.nonDismissable && (
|
<div style={{ position: "relative" }}>
|
||||||
<ModalCloseWrapper onClick={closeModal}>
|
{!props.nonDismissable && (
|
||||||
<Icon icon="mdiClose" size={1} />
|
<ModalCloseWrapper onClick={closeModal}>
|
||||||
</ModalCloseWrapper>
|
<Icon icon="mdiClose" size={1} />
|
||||||
)}
|
</ModalCloseWrapper>
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{(title || description) && (
|
{(title || description) && (
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
{title && typeof title === "string" ? <ModalHeaderText>{title}</ModalHeaderText> : title}
|
{title && typeof title === "string" ? <ModalHeaderText>{title}</ModalHeaderText> : title}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
export * from "./AddServerModal";
|
export * from "./AddServerModal";
|
||||||
export * from "./AttachmentPreviewModal";
|
|
||||||
export * from "./BanMemberModal";
|
export * from "./BanMemberModal";
|
||||||
export * from "./CreateInviteModal";
|
export * from "./CreateInviteModal";
|
||||||
export * from "./CreateServerModal";
|
export * from "./CreateServerModal";
|
||||||
export * from "./DeleteMessageModal";
|
export * from "./DeleteMessageModal";
|
||||||
export * from "./ErrorModal";
|
export * from "./ErrorModal";
|
||||||
export * from "./ForgotPasswordModal";
|
export * from "./ForgotPasswordModal";
|
||||||
|
export * from "./ImageViewerModal";
|
||||||
export * from "./JoinServerModal";
|
export * from "./JoinServerModal";
|
||||||
export * from "./KickMemberModal";
|
export * from "./KickMemberModal";
|
||||||
export * from "./LeaveServerModal";
|
export * from "./LeaveServerModal";
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
CreateServerModal,
|
CreateServerModal,
|
||||||
DeleteMessageModal,
|
DeleteMessageModal,
|
||||||
ErrorModal,
|
ErrorModal,
|
||||||
|
ImageViewerModal,
|
||||||
JoinServerModal,
|
JoinServerModal,
|
||||||
KickMemberModal,
|
KickMemberModal,
|
||||||
LeaveServerModal,
|
LeaveServerModal,
|
||||||
@ -162,7 +163,7 @@ export const modalController = new ModalControllerExtended({
|
|||||||
// custom_status: CustomStatus,
|
// custom_status: CustomStatus,
|
||||||
delete_message: DeleteMessageModal,
|
delete_message: DeleteMessageModal,
|
||||||
error: ErrorModal,
|
error: ErrorModal,
|
||||||
// image_viewer: ImageViewer,
|
image_viewer: ImageViewerModal,
|
||||||
kick_member: KickMemberModal,
|
kick_member: KickMemberModal,
|
||||||
// link_warning: LinkWarning,
|
// link_warning: LinkWarning,
|
||||||
// mfa_flow: MFAFlow,
|
// mfa_flow: MFAFlow,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// adapted from https://github.com/revoltchat/revite/blob/master/src/controllers/modals/types.ts
|
// 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 Channel from "../../stores/objects/Channel";
|
||||||
import Guild from "../../stores/objects/Guild";
|
import Guild from "../../stores/objects/Guild";
|
||||||
import GuildMember from "../../stores/objects/GuildMember";
|
import GuildMember from "../../stores/objects/GuildMember";
|
||||||
@ -42,6 +43,12 @@ export type Modal = {
|
|||||||
type: "leave_server";
|
type: "leave_server";
|
||||||
target: Guild;
|
target: Guild;
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: "image_viewer";
|
||||||
|
attachment: APIAttachment | APIEmbedImage | APIEmbedThumbnail;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export type ModalProps<T extends Modal["type"]> = Modal & { type: T } & {
|
export type ModalProps<T extends Modal["type"]> = Modal & { type: T } & {
|
||||||
|
Loading…
Reference in New Issue
Block a user