From 83311b1b15f5472a068088b1bc308a5f1d73bf20 Mon Sep 17 00:00:00 2001 From: samdd Date: Mon, 14 May 2018 17:38:58 +0100 Subject: [PATCH] Proper image scaler --- .../Message/Embed/elements/thumbnail.ts | 4 - .../Messages/Message/Embed/index.tsx | 25 ++++-- .../Message/Markdown/elements/media.ts | 38 ++------ .../ExpandableImage/elements.ts | 11 ++- .../styled-elements/ExpandableImage/index.tsx | 25 +++++- .../styled-elements/ScaledImage/elements.ts | 6 ++ .../styled-elements/ScaledImage/index.tsx | 86 +++++++++++++++++++ 7 files changed, 151 insertions(+), 44 deletions(-) create mode 100644 src/modules/styled-elements/ScaledImage/elements.ts create mode 100644 src/modules/styled-elements/ScaledImage/index.tsx diff --git a/src/components/Messages/Message/Embed/elements/thumbnail.ts b/src/components/Messages/Message/Embed/elements/thumbnail.ts index 502a70a0a..f91e1f385 100644 --- a/src/components/Messages/Message/Embed/elements/thumbnail.ts +++ b/src/components/Messages/Message/Embed/elements/thumbnail.ts @@ -20,12 +20,8 @@ export const Thumbnail = styled(ExpandableImage)` : /^article|image$/.test(theme.embed.type) ? css` margin-top: 8px; - width: 400px; - height: auto; ` : css` - max-height: 80px; margin-left: 20px; - max-width: 80px; `}; ` diff --git a/src/components/Messages/Message/Embed/index.tsx b/src/components/Messages/Message/Embed/index.tsx index cc4708206..7903ff7f8 100644 --- a/src/components/Messages/Message/Embed/index.tsx +++ b/src/components/Messages/Message/Embed/index.tsx @@ -119,13 +119,28 @@ const EmbedField = ({ name, value, inline }) => { ) } -const EmbedThumbnail = ({ proxyURL, height, width }) => - proxyURL ? : null +const EmbedThumbnail = ({ type, proxyURL, height, width }) => + proxyURL ? ( + + ) : null -const EmbedImage = ({ proxyURL, height }) => +const EmbedImage = ({ proxyURL, height, width }) => proxyURL ? ( - + ) : null @@ -190,7 +205,7 @@ const Embed = ({ - + diff --git a/src/components/Messages/Message/Markdown/elements/media.ts b/src/components/Messages/Message/Markdown/elements/media.ts index e2fa5f1b7..e5033a3f7 100644 --- a/src/components/Messages/Message/Markdown/elements/media.ts +++ b/src/components/Messages/Message/Markdown/elements/media.ts @@ -1,47 +1,23 @@ import ExpandableImage from 'styled-elements/ExpandableImage' import styled, { css } from 'typed-emotion' - -enum Max { - height = 300, - width = 400 -} +import { Scale } from 'styled-elements/ScaledImage' interface ImageProps { height: number width: number } -/** - * Scales an image to a selected max values - */ -const scale = (Image: ImageProps) => { - if (Image.width && Image.height) { - const ratio = - Image.height < Image.width ? ['width', 'height'] : ['height', 'width'] - - const factor = - Image[ratio[0]] > Max[ratio[0]] - ? ratio[0] - : Image[ratio[1]] > Max[ratio[1]] - ? ratio[1] - : null - - const scale = factor ? Max[factor] / Image[factor] : 1 - - return css` - width: ${Image.width * scale}px; - height: ${Image.height * scale}px; - ` - } - return null -} - export const Image = styled(ExpandableImage)` display: block; margin: 10px 0; cursor: pointer; border-radius: 3px; - ${scale}; + ${props => + new Scale({ + ...props, + maxWidth: 400, + maxHeight: 300 + }).css}; @media (max-width: 700px) { width: 65%; diff --git a/src/modules/styled-elements/ExpandableImage/elements.ts b/src/modules/styled-elements/ExpandableImage/elements.ts index e0a2a426f..cccfef63a 100644 --- a/src/modules/styled-elements/ExpandableImage/elements.ts +++ b/src/modules/styled-elements/ExpandableImage/elements.ts @@ -1,10 +1,19 @@ import styled from 'typed-emotion' import { Loading } from '../../../components/Overlays' +import { Scale } from 'styled-elements/ScaledImage' -export const Root = styled('div')` +interface Props { + maxHeight: number + maxWidth: number + height: number + width: number +} + +export const Root = styled('div')` position: relative; overflow: hidden; + ${props => new Scale(props).css}; ` export const Image = styled('img')` diff --git a/src/modules/styled-elements/ExpandableImage/index.tsx b/src/modules/styled-elements/ExpandableImage/index.tsx index fa4337f13..3e41d43cf 100644 --- a/src/modules/styled-elements/ExpandableImage/index.tsx +++ b/src/modules/styled-elements/ExpandableImage/index.tsx @@ -6,6 +6,11 @@ import { Image, Loader, Root } from './elements' interface Props { src: string className?: string + + height?: number + width?: number + maxWidth?: number + maxHeight?: number } /** @@ -22,7 +27,7 @@ const ExpandableImage = connect() type: 'loading' } - open = () => { + open() { const { src, toggle } = this.props if (src) { toggle({ @@ -34,10 +39,24 @@ const ExpandableImage = connect() } render() { - const { className, src } = this.props + const { + className, + height, + width, + maxHeight, + maxWidth, + src + } = this.props return ( - + this.setState({ type: 'loaded' })} diff --git a/src/modules/styled-elements/ScaledImage/elements.ts b/src/modules/styled-elements/ScaledImage/elements.ts new file mode 100644 index 000000000..1f10cc583 --- /dev/null +++ b/src/modules/styled-elements/ScaledImage/elements.ts @@ -0,0 +1,6 @@ +import styled from 'typed-emotion' + +export const Root = styled('img')` + width: ${({ width }) => (width ? `${width}px` : null)}; + width: ${({ height }) => (height ? `${height}px` : null)}; +` diff --git a/src/modules/styled-elements/ScaledImage/index.tsx b/src/modules/styled-elements/ScaledImage/index.tsx new file mode 100644 index 000000000..c450d563a --- /dev/null +++ b/src/modules/styled-elements/ScaledImage/index.tsx @@ -0,0 +1,86 @@ +import * as React from 'react' +import { css } from 'typed-emotion' +import { Root } from './elements' + +interface Scaler { + width?: number + height?: number + maxWidth?: number + maxHeight?: number +} +interface Props extends Scaler { + src: string + className?: string +} + +class ScaledImage extends React.PureComponent { + render() { + const { className, src } = this.props + + const { width, height } = new Scale(this.props) + + return ( + + ) + } +} + +export default ScaledImage + +export class Scale { + public width: number + public height: number + public scale: number + + public css: string + + private Image: { width: number; height: number } + private Max: { width: number; height: number } + + constructor({ width, height, maxWidth, maxHeight }: Scaler) { + this.Image = { + width, + height + } + this.Max = { + height: maxHeight, + width: maxWidth + } + + this.scaleImage() + + this.css = css` + ${this.width && `width: ${this.width}px`}; + ${this.height && `height: ${this.height}px`}; + ` + } + + scaleImage() { + const { Image, Max } = this + + if (!(Image.width && Image.height)) { + return {} + } + + const ratio = + Image.height < Image.width ? ['width', 'height'] : ['height', 'width'] + + const factor = + Image[ratio[0]] > Max[ratio[0]] + ? ratio[0] + : Image[ratio[1]] > Max[ratio[1]] + ? ratio[1] + : null + + const scale = factor ? Max[factor] / Image[factor] : 1 + + this.scale = scale + this.width = Image.width * scale + this.height = Image.height * scale + } +}