From 0a2b95c4f5412e7b422464f0960a1fb9843f4da8 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 19 Feb 2024 22:47:01 +0100 Subject: [PATCH] Adopt upstream's design for preview cards (#2634) Co-authored-by: Eugen Rochko Co-authored-by: Christian Schmidt --- .../flavours/glitch/components/status.jsx | 1 - .../features/status/components/card.jsx | 95 ++++------ .../flavours/glitch/styles/components.scss | 179 +++++++++++------- 3 files changed, 139 insertions(+), 136 deletions(-) diff --git a/app/javascript/flavours/glitch/components/status.jsx b/app/javascript/flavours/glitch/components/status.jsx index 02d4adf015..62b58a5ec9 100644 --- a/app/javascript/flavours/glitch/components/status.jsx +++ b/app/javascript/flavours/glitch/components/status.jsx @@ -729,7 +729,6 @@ class Status extends ImmutablePureComponent { , ); diff --git a/app/javascript/flavours/glitch/features/status/components/card.jsx b/app/javascript/flavours/glitch/features/status/components/card.jsx index 3d5522ab61..c4461f4378 100644 --- a/app/javascript/flavours/glitch/features/status/components/card.jsx +++ b/app/javascript/flavours/glitch/features/status/components/card.jsx @@ -8,12 +8,12 @@ import classNames from 'classnames'; import Immutable from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; - import DescriptionIcon from '@/material-icons/400-24px/description-fill.svg?react'; import OpenInNewIcon from '@/material-icons/400-24px/open_in_new.svg?react'; import PlayArrowIcon from '@/material-icons/400-24px/play_arrow-fill.svg?react'; import { Blurhash } from 'flavours/glitch/components/blurhash'; import { Icon } from 'flavours/glitch/components/icon'; +import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp'; import { useBlurhash } from 'flavours/glitch/initial_state'; import { decode as decodeIDNA } from 'flavours/glitch/utils/idna'; @@ -51,14 +51,9 @@ export default class Card extends PureComponent { static propTypes = { card: ImmutablePropTypes.map, onOpenMedia: PropTypes.func.isRequired, - compact: PropTypes.bool, sensitive: PropTypes.bool, }; - static defaultProps = { - compact: false, - }; - state = { previewLoaded: false, embedded: false, @@ -69,6 +64,7 @@ export default class Card extends PureComponent { if (!Immutable.is(this.props.card, nextProps.card)) { this.setState({ embedded: false, previewLoaded: false }); } + if (this.props.sensitive !== nextProps.sensitive) { this.setState({ revealed: !nextProps.sensitive }); } @@ -82,35 +78,8 @@ export default class Card extends PureComponent { window.removeEventListener('resize', this.handleResize); } - handlePhotoClick = () => { - const { card, onOpenMedia } = this.props; - - onOpenMedia( - Immutable.fromJS([ - { - type: 'image', - url: card.get('embed_url'), - description: card.get('title'), - meta: { - original: { - width: card.get('width'), - height: card.get('height'), - }, - }, - }, - ]), - 0, - ); - }; - handleEmbedClick = () => { - const { card } = this.props; - - if (card.get('type') === 'photo') { - this.handlePhotoClick(); - } else { - this.setState({ embedded: true }); - } + this.setState({ embedded: true }); }; setRef = c => { @@ -128,21 +97,21 @@ export default class Card extends PureComponent { }; renderVideo () { - const { card } = this.props; - const content = { __html: addAutoPlay(card.get('html')) }; + const { card } = this.props; + const content = { __html: addAutoPlay(card.get('html')) }; return (
); } render () { - const { card, compact } = this.props; + const { card } = this.props; const { embedded, revealed } = this.state; if (card === null) { @@ -150,29 +119,37 @@ export default class Card extends PureComponent { } const provider = card.get('provider_name').length === 0 ? decodeIDNA(getHostname(card.get('url'))) : card.get('provider_name'); - const horizontal = (!compact && card.get('width') > card.get('height')) || card.get('type') !== 'link' || embedded; - const interactive = card.get('type') !== 'link'; - const className = classNames('status-card', { horizontal, compact, interactive }); - const title = interactive ? {card.get('title')} : {card.get('title')}; + const interactive = card.get('type') === 'video'; const language = card.get('language') || ''; + const largeImage = (card.get('image')?.length > 0 && card.get('width') > card.get('height')) || interactive; const description = ( -
- {title} - {!(horizontal || compact) &&

{card.get('description')}

} - {provider} +
+ + {provider} + {card.get('published_at') && <> ยท } + + + {card.get('title')} + + {card.get('author_name').length > 0 ? {card.get('author_name')} }} /> : {card.get('description')}}
); const thumbnailStyle = { - visibility: revealed? null : 'hidden', + visibility: revealed ? null : 'hidden', }; - if (horizontal) { - thumbnailStyle.aspectRatio = (compact && !embedded) ? '16 / 9' : `${card.get('width')} / ${card.get('height')}`; + if (largeImage && card.get('type') === 'video') { + thumbnailStyle.aspectRatio = `16 / 9`; + } else if (largeImage) { + thumbnailStyle.aspectRatio = '1.91 / 1'; + } else { + thumbnailStyle.aspectRatio = 1; } - let embed = ''; + let embed; + let canvas = ( {canvas} {thumbnail} {revealed ? ( -
+
- - {horizontal && } + +
) : spoilerButton} @@ -229,9 +200,9 @@ export default class Card extends PureComponent { } return ( -
+
{embed} - {!compact && description} + {description}
); } else if (card.get('image')) { @@ -250,7 +221,7 @@ export default class Card extends PureComponent { } return ( - + {embed} {description} diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 30366b938f..f2decf9b53 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -3486,15 +3486,16 @@ input.glitch-setting-text { } .status-card { - position: relative; display: flex; + align-items: center; + position: relative; font-size: 14px; - border: 1px solid lighten($ui-base-color, 8%); - border-radius: 4px; - color: $dark-text-color; + color: $darker-text-color; margin-top: 14px; text-decoration: none; overflow: hidden; + border: 1px solid lighten($ui-base-color, 8%); + border-radius: 8px; &__actions { bottom: 0; @@ -3505,11 +3506,13 @@ input.glitch-setting-text { display: flex; justify-content: center; align-items: center; + cursor: pointer; & > div { background: rgba($base-shadow-color, 0.6); border-radius: 8px; padding: 12px 9px; + backdrop-filter: blur(10px) saturate(180%) contrast(75%) brightness(70%); flex: 0 0 auto; display: flex; justify-content: center; @@ -3539,19 +3542,37 @@ input.glitch-setting-text { position: relative; bottom: -1px; } - - a .fa, - a:hover .fa { - color: inherit; - } } } a.status-card { cursor: pointer; - &:hover { - background: lighten($ui-base-color, 8%); + &:hover, + &:focus, + &:active { + .status-card__title, + .status-card__host, + .status-card__author, + .status-card__description { + color: $highlight-text-color; + } + } +} + +.status-card a { + color: inherit; + text-decoration: none; + + &:hover, + &:focus, + &:active { + .status-card__title, + .status-card__host, + .status-card__author, + .status-card__description { + color: $highlight-text-color; + } } } @@ -3577,41 +3598,66 @@ a.status-card { .status-card__title { display: block; - font-weight: 500; - margin-bottom: 5px; - color: $darker-text-color; + font-weight: 700; + font-size: 19px; + line-height: 24px; + color: $primary-text-color; overflow: hidden; - text-overflow: ellipsis; white-space: nowrap; - text-decoration: none; + text-overflow: ellipsis; +} + +.status-card.expanded .status-card__title { + white-space: normal; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; } .status-card__content { flex: 1 1 auto; overflow: hidden; - padding: 14px; - padding-inline-start: 8px; -} - -.status-card__description { - color: $darker-text-color; - overflow: hidden; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; + padding: 8px 10px; // intentional glitch-soc change to reduce padding + box-sizing: border-box; + max-width: 100%; } .status-card__host { display: block; - margin-top: 5px; - font-size: 13px; + font-size: 14px; + margin-bottom: 8px; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} + +.status-card__author { + display: block; + margin-top: 8px; + font-size: 14px; + color: $primary-text-color; white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + strong { + font-weight: 500; + } +} + +.status-card__description { + display: block; + margin-top: 8px; + font-size: 14px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .status-card__image { - flex: 0 0 100px; + flex: 0 0 auto; + width: 96px; // intentional glitch-soc change to better use space + aspect-ratio: 1; background: lighten($ui-base-color, 8%); position: relative; @@ -3626,50 +3672,7 @@ a.status-card { } } -.status-card.horizontal { - display: block; - - .status-card__image { - width: 100%; - } - - .status-card__image-image, - .status-card__image-preview { - border-radius: 4px 4px 0 0; - } - - .status-card__title { - white-space: inherit; - } -} - -.status-card.compact { - border-color: lighten($ui-base-color, 4%); - - &.interactive { - border: 0; - } - - .status-card__content { - padding: 8px; - padding-top: 10px; - } - - .status-card__title { - white-space: nowrap; - } - - .status-card__image { - flex: 0 0 60px; - } -} - -a.status-card.compact:hover { - background-color: lighten($ui-base-color, 4%); -} - .status-card__image-image { - border-radius: 4px 0 0 4px; display: block; margin: 0; width: 100%; @@ -3680,7 +3683,6 @@ a.status-card.compact:hover { } .status-card__image-preview { - border-radius: 4px 0 0 4px; display: block; margin: 0; width: 100%; @@ -3697,6 +3699,37 @@ a.status-card.compact:hover { } } +.status-card.expanded { + flex-direction: column; + align-items: flex-start; +} + +.status-card.expanded .status-card__image { + width: 100%; + aspect-ratio: auto; +} + +.status-card__image, +.status-card__image-image, +.status-card__image-preview { + border-start-start-radius: 8px; + border-start-end-radius: 0; + border-end-end-radius: 0; + border-end-start-radius: 8px; +} + +.status-card.expanded .status-card__image, +.status-card.expanded .status-card__image-image, +.status-card.expanded .status-card__image-preview { + border-start-end-radius: 8px; + border-end-end-radius: 0; + border-end-start-radius: 0; +} + +.status-card.expanded > a { + width: 100%; +} + .notification, .status { position: relative;