logo

mastofe

My custom branche(s) on git.pleroma.social/pleroma/mastofe
commit: 2bbf987a0a352a36ef0cc7f06fe366b60593e89c
parent: af00220d795670e10bc8c7378837c4a5a287b556
Author: Eugen Rochko <eugen@zeonfederated.com>
Date:   Thu, 14 Sep 2017 03:39:10 +0200

Redesign video player (#4911)

* Redesign video player

* Use new video player on static public pages too

* Use media gallery component on static public pages too

* Pause video when hiding it

* Full-screen sizing on WebKit

* Add aria labels to video player buttons

* Display link card on public status page

* Fix fullscreen from modal sizing issue

* Remove contain: strict property to fix fullscreen from columns

Diffstat:

Mapp/javascript/mastodon/components/status.js19++++++++++++++++---
Aapp/javascript/mastodon/containers/card_container.js18++++++++++++++++++
Aapp/javascript/mastodon/containers/media_gallery_container.js34++++++++++++++++++++++++++++++++++
Aapp/javascript/mastodon/containers/video_container.js26++++++++++++++++++++++++++
Mapp/javascript/mastodon/features/status/components/card.js10++++++++--
Mapp/javascript/mastodon/features/status/components/detailed_status.js19+++++++++++++++++--
Mapp/javascript/mastodon/features/ui/components/video_modal.js22++++++++--------------
Mapp/javascript/mastodon/features/ui/util/async-components.js4++++
Aapp/javascript/mastodon/features/video/index.js304+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapp/javascript/mastodon/locales/ar.json11+++++++++++
Mapp/javascript/mastodon/locales/bg.json11+++++++++++
Mapp/javascript/mastodon/locales/ca.json11+++++++++++
Mapp/javascript/mastodon/locales/de.json11+++++++++++
Mapp/javascript/mastodon/locales/defaultMessages.json62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapp/javascript/mastodon/locales/en.json13+++++++++++--
Mapp/javascript/mastodon/locales/eo.json11+++++++++++
Mapp/javascript/mastodon/locales/es.json11+++++++++++
Mapp/javascript/mastodon/locales/fa.json13+++++++++++--
Mapp/javascript/mastodon/locales/fi.json11+++++++++++
Mapp/javascript/mastodon/locales/fr.json13+++++++++++--
Mapp/javascript/mastodon/locales/he.json11+++++++++++
Mapp/javascript/mastodon/locales/hr.json12+++++++++++-
Mapp/javascript/mastodon/locales/hu.json11+++++++++++
Mapp/javascript/mastodon/locales/id.json11+++++++++++
Mapp/javascript/mastodon/locales/io.json11+++++++++++
Mapp/javascript/mastodon/locales/it.json11+++++++++++
Mapp/javascript/mastodon/locales/ja.json13+++++++++++--
Mapp/javascript/mastodon/locales/ko.json13+++++++++++--
Mapp/javascript/mastodon/locales/nl.json11+++++++++++
Mapp/javascript/mastodon/locales/no.json11+++++++++++
Mapp/javascript/mastodon/locales/oc.json13+++++++++++--
Mapp/javascript/mastodon/locales/pl.json9+++++++++
Mapp/javascript/mastodon/locales/pt-BR.json13+++++++++++--
Mapp/javascript/mastodon/locales/pt.json11+++++++++++
Mapp/javascript/mastodon/locales/ru.json11+++++++++++
Mapp/javascript/mastodon/locales/th.json11+++++++++++
Mapp/javascript/mastodon/locales/tr.json11+++++++++++
Mapp/javascript/mastodon/locales/uk.json11+++++++++++
Mapp/javascript/mastodon/locales/zh-CN.json11+++++++++++
Mapp/javascript/mastodon/locales/zh-HK.json11+++++++++++
Mapp/javascript/mastodon/locales/zh-TW.json11+++++++++++
Mapp/javascript/packs/public.js30+++++++++++++++++-------------
Mapp/javascript/styles/components.scss197++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mapp/javascript/styles/stream_entries.scss150++++++-------------------------------------------------------------------------
Mapp/views/stream_entries/_detailed_status.html.haml15++++++---------
Mapp/views/stream_entries/_simple_status.html.haml17+++++------------
46 files changed, 1064 insertions(+), 217 deletions(-)

diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js @@ -9,7 +9,7 @@ import StatusContent from './status_content'; import StatusActionBar from './status_action_bar'; import { FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { MediaGallery, VideoPlayer } from '../features/ui/util/async-components'; +import { MediaGallery, Video } from '../features/ui/util/async-components'; // We use the component (and not the container) since we do not want // to use the progress bar to show download progress @@ -88,6 +88,10 @@ export default class Status extends ImmutablePureComponent { return <div className='media-spoiler-video' style={{ height: '110px' }} />; } + handleOpenVideo = startTime => { + this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), startTime); + } + render () { let media = null; let statusAvatar; @@ -127,9 +131,18 @@ export default class Status extends ImmutablePureComponent { if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) { } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { + const video = status.getIn(['media_attachments', 0]); + media = ( - <Bundle fetchComponent={VideoPlayer} loading={this.renderLoadingVideoPlayer} > - {Component => <Component media={status.getIn(['media_attachments', 0])} sensitive={status.get('sensitive')} onOpenVideo={this.props.onOpenVideo} />} + <Bundle fetchComponent={Video} loading={this.renderLoadingVideoPlayer} > + {Component => <Component + preview={video.get('preview_url')} + src={video.get('url')} + width={239} + height={110} + sensitive={status.get('sensitive')} + onOpenVideo={this.handleOpenVideo} + />} </Bundle> ); } else { diff --git a/app/javascript/mastodon/containers/card_container.js b/app/javascript/mastodon/containers/card_container.js @@ -0,0 +1,18 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Card from '../features/status/components/card'; +import { fromJS } from 'immutable'; + +export default class CardContainer extends React.PureComponent { + + static propTypes = { + locale: PropTypes.string, + card: PropTypes.array.isRequired, + }; + + render () { + const { card, ...props } = this.props; + return <Card card={fromJS(card)} {...props} />; + } + +} diff --git a/app/javascript/mastodon/containers/media_gallery_container.js b/app/javascript/mastodon/containers/media_gallery_container.js @@ -0,0 +1,34 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { IntlProvider, addLocaleData } from 'react-intl'; +import { getLocale } from '../locales'; +import MediaGallery from '../components/media_gallery'; +import { fromJS } from 'immutable'; + +const { localeData, messages } = getLocale(); +addLocaleData(localeData); + +export default class MediaGalleryContainer extends React.PureComponent { + + static propTypes = { + locale: PropTypes.string.isRequired, + media: PropTypes.array.isRequired, + }; + + handleOpenMedia = () => {} + + render () { + const { locale, media, ...props } = this.props; + + return ( + <IntlProvider locale={locale} messages={messages}> + <MediaGallery + {...props} + media={fromJS(media)} + onOpenMedia={this.handleOpenMedia} + /> + </IntlProvider> + ); + } + +} diff --git a/app/javascript/mastodon/containers/video_container.js b/app/javascript/mastodon/containers/video_container.js @@ -0,0 +1,26 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { IntlProvider, addLocaleData } from 'react-intl'; +import { getLocale } from '../locales'; +import Video from '../features/video'; + +const { localeData, messages } = getLocale(); +addLocaleData(localeData); + +export default class VideoContainer extends React.PureComponent { + + static propTypes = { + locale: PropTypes.string.isRequired, + }; + + render () { + const { locale, ...props } = this.props; + + return ( + <IntlProvider locale={locale} messages={messages}> + <Video {...props} /> + </IntlProvider> + ); + } + +} diff --git a/app/javascript/mastodon/features/status/components/card.js b/app/javascript/mastodon/features/status/components/card.js @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import punycode from 'punycode'; import classnames from 'classnames'; @@ -22,10 +23,15 @@ export default class Card extends React.PureComponent { static propTypes = { card: ImmutablePropTypes.map, + maxDescription: PropTypes.number, + }; + + static defaultProps = { + maxDescription: 50, }; renderLink () { - const { card } = this.props; + const { card, maxDescription } = this.props; let image = ''; let provider = card.get('provider_name'); @@ -52,7 +58,7 @@ export default class Card extends React.PureComponent { <div className='status-card__content'> <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong> - <p className='status-card__description'>{(card.get('description') || '').substring(0, 50)}</p> + <p className='status-card__description'>{(card.get('description') || '').substring(0, maxDescription)}</p> <span className='status-card__host'>{provider}</span> </div> </a> diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js @@ -5,12 +5,12 @@ import Avatar from '../../../components/avatar'; import DisplayName from '../../../components/display_name'; import StatusContent from '../../../components/status_content'; import MediaGallery from '../../../components/media_gallery'; -import VideoPlayer from '../../../components/video_player'; import AttachmentList from '../../../components/attachment_list'; import Link from 'react-router-dom/Link'; import { FormattedDate, FormattedNumber } from 'react-intl'; import CardContainer from '../containers/card_container'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import Video from '../../video'; export default class DetailedStatus extends ImmutablePureComponent { @@ -34,6 +34,10 @@ export default class DetailedStatus extends ImmutablePureComponent { e.stopPropagation(); } + handleOpenVideo = startTime => { + this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), startTime); + } + render () { const status = this.props.status.get('reblog') ? this.props.status.get('reblog') : this.props.status; @@ -44,7 +48,18 @@ export default class DetailedStatus extends ImmutablePureComponent { if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) { media = <AttachmentList media={status.get('media_attachments')} />; } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { - media = <VideoPlayer sensitive={status.get('sensitive')} media={status.getIn(['media_attachments', 0])} width={300} height={150} onOpenVideo={this.props.onOpenVideo} autoplay />; + const video = status.getIn(['media_attachments', 0]); + + media = ( + <Video + preview={video.get('preview_url')} + src={video.get('url')} + width={300} + height={150} + onOpenVideo={this.handleOpenVideo} + sensitive={status.get('sensitive')} + /> + ); } else { media = <MediaGallery sensitive={status.get('sensitive')} media={status.get('media_attachments')} height={300} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />; } diff --git a/app/javascript/mastodon/features/ui/components/video_modal.js b/app/javascript/mastodon/features/ui/components/video_modal.js @@ -1,35 +1,29 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; -import ExtendedVideoPlayer from '../../../components/extended_video_player'; -import { defineMessages, injectIntl } from 'react-intl'; -import IconButton from '../../../components/icon_button'; +import Video from '../../video'; import ImmutablePureComponent from 'react-immutable-pure-component'; -const messages = defineMessages({ - close: { id: 'lightbox.close', defaultMessage: 'Close' }, -}); - -@injectIntl export default class VideoModal extends ImmutablePureComponent { static propTypes = { media: ImmutablePropTypes.map.isRequired, time: PropTypes.number, onClose: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, }; render () { - const { media, intl, time, onClose } = this.props; - - const url = media.get('url'); + const { media, time, onClose } = this.props; return ( <div className='modal-root__modal media-modal'> <div> - <div className='media-modal__close'><IconButton title={intl.formatMessage(messages.close)} icon='times' overlay onClick={onClose} /></div> - <ExtendedVideoPlayer src={url} muted={false} controls time={time} /> + <Video + preview={media.get('preview_url')} + src={media.get('url')} + startTime={time} + onCloseVideo={onClose} + /> </div> </div> ); diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js @@ -98,6 +98,10 @@ export function VideoPlayer () { return import(/* webpackChunkName: "status/video_player" */'../../../components/video_player'); } +export function Video () { + return import(/* webpackChunkName: "features/video" */'../../video'); +} + export function EmbedModal () { return import(/* webpackChunkName: "modals/embed_modal" */'../components/embed_modal'); } diff --git a/app/javascript/mastodon/features/video/index.js b/app/javascript/mastodon/features/video/index.js @@ -0,0 +1,304 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { throttle } from 'lodash'; +import classNames from 'classnames'; + +const messages = defineMessages({ + play: { id: 'video.play', defaultMessage: 'Play' }, + pause: { id: 'video.pause', defaultMessage: 'Pause' }, + mute: { id: 'video.mute', defaultMessage: 'Mute sound' }, + unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' }, + hide: { id: 'video.hide', defaultMessage: 'Hide video' }, + expand: { id: 'video.expand', defaultMessage: 'Expand video' }, + close: { id: 'video.close', defaultMessage: 'Close video' }, + fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' }, + exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' }, +}); + +const findElementPosition = el => { + let box; + + if (el.getBoundingClientRect && el.parentNode) { + box = el.getBoundingClientRect(); + } + + if (!box) { + return { + left: 0, + top: 0, + }; + } + + const docEl = document.documentElement; + const body = document.body; + + const clientLeft = docEl.clientLeft || body.clientLeft || 0; + const scrollLeft = window.pageXOffset || body.scrollLeft; + const left = (box.left + scrollLeft) - clientLeft; + + const clientTop = docEl.clientTop || body.clientTop || 0; + const scrollTop = window.pageYOffset || body.scrollTop; + const top = (box.top + scrollTop) - clientTop; + + return { + left: Math.round(left), + top: Math.round(top), + }; +}; + +const getPointerPosition = (el, event) => { + const position = {}; + const box = findElementPosition(el); + const boxW = el.offsetWidth; + const boxH = el.offsetHeight; + const boxY = box.top; + const boxX = box.left; + + let pageY = event.pageY; + let pageX = event.pageX; + + if (event.changedTouches) { + pageX = event.changedTouches[0].pageX; + pageY = event.changedTouches[0].pageY; + } + + position.y = Math.max(0, Math.min(1, ((boxY - pageY) + boxH) / boxH)); + position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW)); + + return position; +}; + +const isFullscreen = () => document.fullscreenElement || + document.webkitFullscreenElement || + document.mozFullScreenElement || + document.msFullscreenElement; + +const exitFullscreen = () => { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } +}; + +const requestFullscreen = el => { + if (el.requestFullscreen) { + el.requestFullscreen(); + } else if (el.webkitRequestFullscreen) { + el.webkitRequestFullscreen(); + } else if (el.mozRequestFullScreen) { + el.mozRequestFullScreen(); + } else if (el.msRequestFullscreen) { + el.msRequestFullscreen(); + } +}; + +@injectIntl +export default class Video extends React.PureComponent { + + static propTypes = { + preview: PropTypes.string, + src: PropTypes.string.isRequired, + width: PropTypes.number, + height: PropTypes.number, + sensitive: PropTypes.bool, + startTime: PropTypes.number, + onOpenVideo: PropTypes.func, + onCloseVideo: PropTypes.func, + intl: PropTypes.object.isRequired, + }; + + state = { + progress: 0, + paused: true, + dragging: false, + fullscreen: false, + hovered: false, + muted: false, + revealed: !this.props.sensitive, + }; + + setPlayerRef = c => { + this.player = c; + } + + setVideoRef = c => { + this.video = c; + } + + setSeekRef = c => { + this.seek = c; + } + + handlePlay = () => { + this.setState({ paused: false }); + } + + handlePause = () => { + this.setState({ paused: true }); + } + + handleTimeUpdate = () => { + this.setState({ progress: 100 * (this.video.currentTime / this.video.duration) }); + } + + handleMouseDown = e => { + document.addEventListener('mousemove', this.handleMouseMove, true); + document.addEventListener('mouseup', this.handleMouseUp, true); + document.addEventListener('touchmove', this.handleMouseMove, true); + document.addEventListener('touchend', this.handleMouseUp, true); + + this.setState({ dragging: true }); + this.video.pause(); + this.handleMouseMove(e); + } + + handleMouseUp = () => { + document.removeEventListener('mousemove', this.handleMouseMove, true); + document.removeEventListener('mouseup', this.handleMouseUp, true); + document.removeEventListener('touchmove', this.handleMouseMove, true); + document.removeEventListener('touchend', this.handleMouseUp, true); + + this.setState({ dragging: false }); + this.video.play(); + } + + handleMouseMove = throttle(e => { + const { x } = getPointerPosition(this.seek, e); + this.video.currentTime = this.video.duration * x; + this.setState({ progress: x * 100 }); + }, 60); + + togglePlay = () => { + if (this.state.paused) { + this.video.play(); + } else { + this.video.pause(); + } + } + + toggleFullscreen = () => { + if (isFullscreen()) { + exitFullscreen(); + } else { + requestFullscreen(this.player); + } + } + + componentDidMount () { + document.addEventListener('fullscreenchange', this.handleFullscreenChange, true); + document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange, true); + document.addEventListener('mozfullscreenchange', this.handleFullscreenChange, true); + document.addEventListener('MSFullscreenChange', this.handleFullscreenChange, true); + } + + componentWillUnmount () { + document.removeEventListener('fullscreenchange', this.handleFullscreenChange, true); + document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange, true); + document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange, true); + document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange, true); + } + + handleFullscreenChange = () => { + this.setState({ fullscreen: isFullscreen() }); + } + + handleMouseEnter = () => { + this.setState({ hovered: true }); + } + + handleMouseLeave = () => { + this.setState({ hovered: false }); + } + + toggleMute = () => { + this.video.muted = !this.video.muted; + this.setState({ muted: this.video.muted }); + } + + toggleReveal = () => { + if (this.state.revealed) { + this.video.pause(); + } + + this.setState({ revealed: !this.state.revealed }); + } + + handleLoadedData = () => { + if (this.props.startTime) { + this.video.currentTime = this.props.startTime; + this.video.play(); + } + } + + handleOpenVideo = () => { + this.video.pause(); + this.props.onOpenVideo(this.video.currentTime); + } + + handleCloseVideo = () => { + this.video.pause(); + this.props.onCloseVideo(); + } + + render () { + const { preview, src, width, height, startTime, onOpenVideo, onCloseVideo, intl } = this.props; + const { progress, dragging, paused, fullscreen, hovered, muted, revealed } = this.state; + + return ( + <div className={classNames('video-player', { inactive: !revealed, inline: width && height && !fullscreen, fullscreen })} style={{ width, height }} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}> + <video + ref={this.setVideoRef} + src={src} + poster={preview} + preload={!!startTime} + loop + role='button' + tabIndex='0' + width={width} + height={height} + onClick={this.togglePlay} + onPlay={this.handlePlay} + onPause={this.handlePause} + onTimeUpdate={this.handleTimeUpdate} + onLoadedData={this.handleLoadedData} + /> + + <button className={classNames('video-player__spoiler', { active: !revealed })} onClick={this.toggleReveal}> + <span className='video-player__spoiler__title'><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span> + <span className='video-player__spoiler__subtitle'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span> + </button> + + <div className={classNames('video-player__controls', { active: paused || hovered })}> + <div className='video-player__seek' onMouseDown={this.handleMouseDown} ref={this.setSeekRef}> + <div className='video-player__seek__progress' style={{ width: `${progress}%` }} /> + + <span + className={classNames('video-player__seek__handle', { active: dragging })} + tabIndex='0' + style={{ left: `${progress}%` }} + /> + </div> + + <div className='video-player__buttons left'> + <button aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button> + <button aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button> + {!onCloseVideo && <button aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><i className='fa fa-fw fa-eye' /></button>} + </div> + + <div className='video-player__buttons right'> + {(!fullscreen && onOpenVideo) && <button aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><i className='fa fa-fw fa-expand' /></button>} + {onCloseVideo && <button aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><i className='fa fa-fw fa-times' /></button>} + <button aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><i className={classNames('fa fa-fw', { 'fa-arrows-alt': !fullscreen, 'fa-compress': fullscreen })} /></button> + </div> + </div> + </div> + ); + } + +} diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json @@ -33,6 +33,7 @@ "column.home": "الرئيسية", "column.mutes": "الحسابات المكتومة", "column.notifications": "الإشعارات", + "column.pins": "Pinned toot", "column.public": "الخيط العام الموحد", "column_back_button.label": "العودة", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "معلومات إضافية", "navigation_bar.logout": "خروج", "navigation_bar.mutes": "الحسابات المكتومة", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "التفضيلات", "navigation_bar.public_timeline": "الخيط العام الموحد", "notification.favourite": "{name} أعجب بمنشورك", @@ -193,6 +195,15 @@ "upload_button.label": "إضافة وسائط", "upload_form.undo": "إلغاء", "upload_progress.label": "يرفع...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "وسّع الفيديو", "video_player.toggle_sound": "تبديل الصوت", "video_player.toggle_visible": "إظهار / إخفاء الفيديو", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json @@ -33,6 +33,7 @@ "column.home": "Начало", "column.mutes": "Muted users", "column.notifications": "Известия", + "column.pins": "Pinned toot", "column.public": "Публичен канал", "column_back_button.label": "Назад", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Extended information", "navigation_bar.logout": "Излизане", "navigation_bar.mutes": "Muted users", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Предпочитания", "navigation_bar.public_timeline": "Публичен канал", "notification.favourite": "{name} хареса твоята публикация", @@ -193,6 +195,15 @@ "upload_button.label": "Добави медия", "upload_form.undo": "Отмяна", "upload_progress.label": "Uploading...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Expand video", "video_player.toggle_sound": "Звук", "video_player.toggle_visible": "Toggle visibility", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json @@ -33,6 +33,7 @@ "column.home": "Inici", "column.mutes": "Usuaris silenciats", "column.notifications": "Notificacions", + "column.pins": "Pinned toot", "column.public": "Línia de temps federada", "column_back_button.label": "Enrere", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Informació addicional", "navigation_bar.logout": "Tancar sessió", "navigation_bar.mutes": "Usuaris silenciats", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Preferències", "navigation_bar.public_timeline": "Línia de temps federada", "notification.favourite": "{name} ha afavorit el teu estat", @@ -193,6 +195,15 @@ "upload_button.label": "Afegir multimèdia", "upload_form.undo": "Desfer", "upload_progress.label": "Pujant...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Ampliar el vídeo", "video_player.toggle_sound": "Alternar so", "video_player.toggle_visible": "Alternar visibilitat", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json @@ -33,6 +33,7 @@ "column.home": "Startseite", "column.mutes": "Stummgeschaltete Profile", "column.notifications": "Mitteilungen", + "column.pins": "Pinned toot", "column.public": "Gesamtes bekanntes Netz", "column_back_button.label": "Zurück", "column_header.hide_settings": "Einstellungen verbergen", @@ -109,6 +110,7 @@ "navigation_bar.info": "Erweiterte Informationen", "navigation_bar.logout": "Abmelden", "navigation_bar.mutes": "Stummgeschaltete Profile", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Einstellungen", "navigation_bar.public_timeline": "Föderierte Zeitleiste", "notification.favourite": "{name} favorisierte deinen Status", @@ -193,6 +195,15 @@ "upload_button.label": "Mediendatei hinzufügen", "upload_form.undo": "Entfernen", "upload_progress.label": "Lade hoch…", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Videoanzeige vergrößern", "video_player.toggle_sound": "Ton umschalten", "video_player.toggle_visible": "Sichtbarkeit umschalten", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json @@ -813,6 +813,10 @@ "id": "navigation_bar.info" }, { + "defaultMessage": "Pinned toots", + "id": "navigation_bar.pins" + }, + { "defaultMessage": "FAQ", "id": "getting_started.faq" }, @@ -995,6 +999,15 @@ { "descriptors": [ { + "defaultMessage": "Pinned toot", + "id": "column.pins" + } + ], + "path": "app/javascript/mastodon/features/pinned_statuses/index.json" + }, + { + "descriptors": [ + { "defaultMessage": "Federated timeline", "id": "column.public" }, @@ -1326,5 +1339,54 @@ } ], "path": "app/javascript/mastodon/features/ui/components/video_modal.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Play", + "id": "video.play" + }, + { + "defaultMessage": "Pause", + "id": "video.pause" + }, + { + "defaultMessage": "Mute sound", + "id": "video.mute" + }, + { + "defaultMessage": "Unmute sound", + "id": "video.unmute" + }, + { + "defaultMessage": "Hide video", + "id": "video.hide" + }, + { + "defaultMessage": "Expand video", + "id": "video.expand" + }, + { + "defaultMessage": "Close video", + "id": "video.close" + }, + { + "defaultMessage": "Full screen", + "id": "video.fullscreen" + }, + { + "defaultMessage": "Exit full screen", + "id": "video.exit_fullscreen" + }, + { + "defaultMessage": "Sensitive content", + "id": "status.sensitive_warning" + }, + { + "defaultMessage": "Click to view", + "id": "status.sensitive_toggle" + } + ], + "path": "app/javascript/mastodon/features/video/index.json" } ] \ No newline at end of file diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json @@ -33,8 +33,8 @@ "column.home": "Home", "column.mutes": "Muted users", "column.notifications": "Notifications", - "column.public": "Federated timeline", "column.pins": "Pinned toots", + "column.public": "Federated timeline", "column_back_button.label": "Back", "column_header.hide_settings": "Hide settings", "column_header.moveLeft_settings": "Move column to the left", @@ -110,9 +110,9 @@ "navigation_bar.info": "About this instance", "navigation_bar.logout": "Logout", "navigation_bar.mutes": "Muted users", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Preferences", "navigation_bar.public_timeline": "Federated timeline", - "navigation_bar.pins": "Pinned toots", "notification.favourite": "{name} favourited your status", "notification.follow": "{name} followed you", "notification.mention": "{name} mentioned you", @@ -195,6 +195,15 @@ "upload_button.label": "Add media", "upload_form.undo": "Undo", "upload_progress.label": "Uploading...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Expand video", "video_player.toggle_sound": "Toggle sound", "video_player.toggle_visible": "Toggle visibility", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json @@ -33,6 +33,7 @@ "column.home": "Hejmo", "column.mutes": "Muted users", "column.notifications": "Sciigoj", + "column.pins": "Pinned toot", "column.public": "Fratara tempolinio", "column_back_button.label": "Reveni", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Extended information", "navigation_bar.logout": "Elsaluti", "navigation_bar.mutes": "Muted users", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Preferoj", "navigation_bar.public_timeline": "Fratara tempolinio", "notification.favourite": "{name} favoris vian mesaĝon", @@ -193,6 +195,15 @@ "upload_button.label": "Aldoni enhavaĵon", "upload_form.undo": "Malfari", "upload_progress.label": "Uploading...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Expand video", "video_player.toggle_sound": "Aktivigi sonojn", "video_player.toggle_visible": "Toggle visibility", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json @@ -33,6 +33,7 @@ "column.home": "Inicio", "column.mutes": "Usuarios silenciados", "column.notifications": "Notificaciones", + "column.pins": "Pinned toot", "column.public": "Historia federada", "column_back_button.label": "Atrás", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Información adicional", "navigation_bar.logout": "Cerrar sesión", "navigation_bar.mutes": "Usuarios silenciados", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Preferencias", "navigation_bar.public_timeline": "Historia federada", "notification.favourite": "{name} marcó tu estado como favorito", @@ -193,6 +195,15 @@ "upload_button.label": "Subir multimedia", "upload_form.undo": "Deshacer", "upload_progress.label": "Uploading...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Expand video", "video_player.toggle_sound": "Act/Desac. sonido", "video_player.toggle_visible": "Toggle visibility", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json @@ -33,8 +33,8 @@ "column.home": "خانه", "column.mutes": "کاربران بی‌صداشده", "column.notifications": "اعلان‌ها", - "column.public": "نوشته‌های همه‌جا", "column.pins": "نوشته‌های ثابت", + "column.public": "نوشته‌های همه‌جا", "column_back_button.label": "بازگشت", "column_header.hide_settings": "نهفتن تنظیمات", "column_header.moveLeft_settings": "انتقال ستون به چپ", @@ -110,9 +110,9 @@ "navigation_bar.info": "اطلاعات تکمیلی", "navigation_bar.logout": "خروج", "navigation_bar.mutes": "کاربران بی‌صداشده", + "navigation_bar.pins": "نوشته‌های ثابت", "navigation_bar.preferences": "ترجیحات", "navigation_bar.public_timeline": "نوشته‌های همه‌جا", - "navigation_bar.pins": "نوشته‌های ثابت", "notification.favourite": "‫{name}‬ نوشتهٔ شما را پسندید", "notification.follow": "‫{name}‬ پیگیر شما شد", "notification.mention": "‫{name}‬ از شما نام برد", @@ -195,6 +195,15 @@ "upload_button.label": "افزودن تصویر", "upload_form.undo": "واگردانی", "upload_progress.label": "بارگذاری...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "بازکردن ویدیو", "video_player.toggle_sound": "تغییر صداداری", "video_player.toggle_visible": "تغییر پیدایی", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json @@ -33,6 +33,7 @@ "column.home": "Koti", "column.mutes": "Muted users", "column.notifications": "Ilmoitukset", + "column.pins": "Pinned toot", "column.public": "Yleinen aikajana", "column_back_button.label": "Takaisin", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Extended information", "navigation_bar.logout": "Kirjaudu ulos", "navigation_bar.mutes": "Muted users", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Ominaisuudet", "navigation_bar.public_timeline": "Yleinen aikajana", "notification.favourite": "{name} tykkäsi statuksestasi", @@ -193,6 +195,15 @@ "upload_button.label": "Lisää mediaa", "upload_form.undo": "Peru", "upload_progress.label": "Uploading...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Expand video", "video_player.toggle_sound": "Äänet päälle/pois", "video_player.toggle_visible": "Toggle visibility", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json @@ -33,8 +33,8 @@ "column.home": "Accueil", "column.mutes": "Comptes masqués", "column.notifications": "Notifications", - "column.public": "Fil public global", "column.pins": "Pouets épinglés", + "column.public": "Fil public global", "column_back_button.label": "Retour", "column_header.hide_settings": "Masquer les paramètres", "column_header.moveLeft_settings": "Déplacer la colonne vers la gauche", @@ -110,9 +110,9 @@ "navigation_bar.info": "Plus d’informations", "navigation_bar.logout": "Déconnexion", "navigation_bar.mutes": "Comptes masqués", + "navigation_bar.pins": "Pouets épinglés", "navigation_bar.preferences": "Préférences", "navigation_bar.public_timeline": "Fil public global", - "navigation_bar.pins": "Pouets épinglés", "notification.favourite": "{name} a ajouté à ses favoris :", "notification.follow": "{name} vous suit.", "notification.mention": "{name} vous a mentionné⋅e :", @@ -195,6 +195,15 @@ "upload_button.label": "Joindre un média", "upload_form.undo": "Annuler", "upload_progress.label": "Envoi en cours…", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Agrandir la vidéo", "video_player.toggle_sound": "Activer/Désactiver le son", "video_player.toggle_visible": "Afficher/Cacher la vidéo", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json @@ -33,6 +33,7 @@ "column.home": "בבית", "column.mutes": "השתקות", "column.notifications": "התראות", + "column.pins": "Pinned toot", "column.public": "בפרהסיה", "column_back_button.label": "חזרה", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "מידע נוסף", "navigation_bar.logout": "יציאה", "navigation_bar.mutes": "השתקות", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "העדפות", "navigation_bar.public_timeline": "ציר זמן בין-קהילתי", "notification.favourite": "חצרוצך חובב על ידי {name}", @@ -193,6 +195,15 @@ "upload_button.label": "הוספת מדיה", "upload_form.undo": "ביטול", "upload_progress.label": "עולה...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "הרחבת וידאו", "video_player.toggle_sound": "הפעלת\\ביטול שמע", "video_player.toggle_visible": "הפעלת\\ביטול תצוגה", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json @@ -33,6 +33,7 @@ "column.home": "Dom", "column.mutes": "Utišani korisnici", "column.notifications": "Notifikacije", + "column.pins": "Pinned toot", "column.public": "Federalni timeline", "column_back_button.label": "Natrag", "column_header.hide_settings": "Hide settings", @@ -61,7 +62,6 @@ "confirmations.domain_block.message": "Jesi li zaista, zaista siguran da želiš potpuno blokirati {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Utišaj", "confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?", - "confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -110,6 +110,7 @@ "navigation_bar.info": "Više informacija", "navigation_bar.logout": "Odjavi se", "navigation_bar.mutes": "Utišani korisnici", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Postavke", "navigation_bar.public_timeline": "Federalni timeline", "notification.favourite": "{name} je lajkao tvoj status", @@ -194,6 +195,15 @@ "upload_button.label": "Dodaj media", "upload_form.undo": "Poništi", "upload_progress.label": "Uploadam...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Proširi video", "video_player.toggle_sound": "Toggle zvuk", "video_player.toggle_visible": "Preklopi vidljivost", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json @@ -33,6 +33,7 @@ "column.home": "Kezdőlap", "column.mutes": "Muted users", "column.notifications": "Értesítések", + "column.pins": "Pinned toot", "column.public": "Nyilvános", "column_back_button.label": "Vissza", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Extended information", "navigation_bar.logout": "Kijelentkezés", "navigation_bar.mutes": "Muted users", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Beállítások", "navigation_bar.public_timeline": "Nyilvános időfolyam", "notification.favourite": "{name} kedvencnek jelölte az állapotod", @@ -193,6 +195,15 @@ "upload_button.label": "Média hozzáadása", "upload_form.undo": "Mégsem", "upload_progress.label": "Uploading...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Expand video", "video_player.toggle_sound": "Hang kapcsolása", "video_player.toggle_visible": "Toggle visibility", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json @@ -33,6 +33,7 @@ "column.home": "Beranda", "column.mutes": "Pengguna dibisukan", "column.notifications": "Notifikasi", + "column.pins": "Pinned toot", "column.public": "Linimasa gabunggan", "column_back_button.label": "Kembali", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Informasi selengkapnya", "navigation_bar.logout": "Keluar", "navigation_bar.mutes": "Pengguna dibisukan", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Pengaturan", "navigation_bar.public_timeline": "Linimasa gabungan", "notification.favourite": "{name} menyukai status anda", @@ -193,6 +195,15 @@ "upload_button.label": "Tambahkan media", "upload_form.undo": "Undo", "upload_progress.label": "Mengunggah...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Tampilkan video", "video_player.toggle_sound": "Suara", "video_player.toggle_visible": "Tampilan", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json @@ -33,6 +33,7 @@ "column.home": "Hemo", "column.mutes": "Celita uzeri", "column.notifications": "Savigi", + "column.pins": "Pinned toot", "column.public": "Federata tempolineo", "column_back_button.label": "Retro", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Detaloza informi", "navigation_bar.logout": "Ekirar", "navigation_bar.mutes": "Celita uzeri", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Preferi", "navigation_bar.public_timeline": "Federata tempolineo", "notification.favourite": "{name} favorizis tua mesajo", @@ -193,6 +195,15 @@ "upload_button.label": "Adjuntar kontenajo", "upload_form.undo": "Desfacar", "upload_progress.label": "Kargante...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Extensar video", "video_player.toggle_sound": "Acendar sono", "video_player.toggle_visible": "Chanjar videbleso", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json @@ -33,6 +33,7 @@ "column.home": "Home", "column.mutes": "Utenti silenziati", "column.notifications": "Notifiche", + "column.pins": "Pinned toot", "column.public": "Timeline federata", "column_back_button.label": "Indietro", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Informazioni estese", "navigation_bar.logout": "Logout", "navigation_bar.mutes": "Utenti silenziati", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Impostazioni", "navigation_bar.public_timeline": "Timeline federata", "notification.favourite": "{name} ha apprezzato il tuo post", @@ -193,6 +195,15 @@ "upload_button.label": "Aggiungi file multimediale", "upload_form.undo": "Annulla", "upload_progress.label": "Sto caricando...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Espandi video", "video_player.toggle_sound": "Attiva suono", "video_player.toggle_visible": "Attiva visibilità", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json @@ -33,8 +33,8 @@ "column.home": "ホーム", "column.mutes": "ミュートしたユーザー", "column.notifications": "通知", - "column.public": "連合タイムライン", "column.pins": "固定されたトゥート", + "column.public": "連合タイムライン", "column_back_button.label": "戻る", "column_header.hide_settings": "設定を隠す", "column_header.moveLeft_settings": "カラムを左に移動する", @@ -110,9 +110,9 @@ "navigation_bar.info": "このインスタンスについて", "navigation_bar.logout": "ログアウト", "navigation_bar.mutes": "ミュートしたユーザー", + "navigation_bar.pins": "固定されたトゥート", "navigation_bar.preferences": "ユーザー設定", "navigation_bar.public_timeline": "連合タイムライン", - "navigation_bar.pins": "固定されたトゥート", "notification.favourite": "{name}さんがあなたのトゥートをお気に入りに登録しました", "notification.follow": "{name}さんにフォローされました", "notification.mention": "{name}さんがあなたに返信しました", @@ -195,6 +195,15 @@ "upload_button.label": "メディアを追加", "upload_form.undo": "やり直す", "upload_progress.label": "アップロード中...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "動画の詳細", "video_player.toggle_sound": "音の切り替え", "video_player.toggle_visible": "表示切り替え", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json @@ -33,8 +33,8 @@ "column.home": "홈", "column.mutes": "뮤트 중인 사용자", "column.notifications": "알림", - "column.public": "연합 타임라인", "column.pins": "고정된 Toot", + "column.public": "연합 타임라인", "column_back_button.label": "돌아가기", "column_header.hide_settings": "Hide settings", "column_header.moveLeft_settings": "Move column to the left", @@ -110,9 +110,9 @@ "navigation_bar.info": "이 인스턴스에 대해서", "navigation_bar.logout": "로그아웃", "navigation_bar.mutes": "뮤트 중인 사용자", + "navigation_bar.pins": "고정된 Toot", "navigation_bar.preferences": "사용자 설정", "navigation_bar.public_timeline": "연합 타임라인", - "navigation_bar.pins": "고정된 Toot", "notification.favourite": "{name}님이 즐겨찾기 했습니다", "notification.follow": "{name}님이 나를 팔로우 했습니다", "notification.mention": "{name}님이 답글을 보냈습니다", @@ -195,6 +195,15 @@ "upload_button.label": "미디어 추가", "upload_form.undo": "재시도", "upload_progress.label": "업로드 중...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "동영상 자세히 보기", "video_player.toggle_sound": "소리 토글하기", "video_player.toggle_visible": "표시 전환", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json @@ -33,6 +33,7 @@ "column.home": "Start", "column.mutes": "Genegeerde gebruikers", "column.notifications": "Meldingen", + "column.pins": "Pinned toot", "column.public": "Globale tijdlijn", "column.pins": "Vastgezette toots", "column_back_button.label": "terug", @@ -111,6 +112,7 @@ "navigation_bar.info": "Uitgebreide informatie", "navigation_bar.logout": "Afmelden", "navigation_bar.mutes": "Genegeerde gebruikers", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Instellingen", "navigation_bar.public_timeline": "Globale tijdlijn", "navigation_bar.pins": "Vastgezette toots", @@ -196,6 +198,15 @@ "upload_button.label": "Media toevoegen", "upload_form.undo": "Ongedaan maken", "upload_progress.label": "Uploaden...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Video groter maken", "video_player.toggle_sound": "Geluid in-/uitschakelen", "video_player.toggle_visible": "Video wel/niet tonen", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json @@ -33,6 +33,7 @@ "column.home": "Hjem", "column.mutes": "Dempede brukere", "column.notifications": "Varsler", + "column.pins": "Pinned toot", "column.public": "Felles tidslinje", "column_back_button.label": "Tilbake", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Utvidet informasjon", "navigation_bar.logout": "Logg ut", "navigation_bar.mutes": "Dempede brukere", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Preferanser", "navigation_bar.public_timeline": "Felles tidslinje", "notification.favourite": "{name} likte din status", @@ -193,6 +195,15 @@ "upload_button.label": "Legg til media", "upload_form.undo": "Angre", "upload_progress.label": "Laster opp...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Utvid video", "video_player.toggle_sound": "Veksle lyd", "video_player.toggle_visible": "Veksle synlighet", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json @@ -33,8 +33,8 @@ "column.home": "Acuèlh", "column.mutes": "Personas en silenci", "column.notifications": "Notificacions", - "column.public": "Flux public global", "column.pins": "Tuts penjats", + "column.public": "Flux public global", "column_back_button.label": "Tornar", "column_header.hide_settings": "Amagar los paramètres", "column_header.moveLeft_settings": "Desplaçar la colomna a man drecha", @@ -110,9 +110,9 @@ "navigation_bar.info": "Mai informacions", "navigation_bar.logout": "Desconnexion", "navigation_bar.mutes": "Personas rescondudas", + "navigation_bar.pins": "Tuts penjats", "navigation_bar.preferences": "Preferéncias", "navigation_bar.public_timeline": "Flux public global", - "navigation_bar.pins": "Tuts penjats", "notification.favourite": "{name} a ajustat a sos favorits :", "notification.follow": "{name} vos sèc", "notification.mention": "{name} vos a mencionat :", @@ -195,6 +195,15 @@ "upload_button.label": "Ajustar un mèdia", "upload_form.undo": "Anullar", "upload_progress.label": "Mandadís…", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Mostrar la vidèo", "video_player.toggle_sound": "Activar/Desactivar lo son", "video_player.toggle_visible": "Mostrar/Rescondre la vidèo", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json @@ -195,6 +195,15 @@ "upload_button.label": "Dodaj zawartość multimedialną", "upload_form.undo": "Cofnij", "upload_progress.label": "Wysyłanie", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Przełącz wideo", "video_player.toggle_sound": "Przełącz dźwięk", "video_player.toggle_visible": "Przełącz widoczność", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json @@ -33,8 +33,8 @@ "column.home": "Página inicial", "column.mutes": "Usuários silenciados", "column.notifications": "Notificações", - "column.public": "Global", "column.pins": "Postagens fixadas", + "column.public": "Global", "column_back_button.label": "Voltar", "column_header.hide_settings": "Esconder configurações", "column_header.moveLeft_settings": "Mover coluna para a esquerda", @@ -110,9 +110,9 @@ "navigation_bar.info": "Mais informações", "navigation_bar.logout": "Sair", "navigation_bar.mutes": "Usuários silenciados", + "navigation_bar.pins": "Postagens fixadas", "navigation_bar.preferences": "Preferências", "navigation_bar.public_timeline": "Global", - "navigation_bar.pins": "Postagens fixadas", "notification.favourite": "{name} adicionou a sua postagem aos favoritos", "notification.follow": "{name} te seguiu", "notification.mention": "{name} te mencionou", @@ -195,6 +195,15 @@ "upload_button.label": "Adicionar mídia", "upload_form.undo": "Anular", "upload_progress.label": "Salvando...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Expandir vídeo", "video_player.toggle_sound": "Ligar/Desligar som", "video_player.toggle_visible": "Ligar/Desligar vídeo", diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json @@ -33,6 +33,7 @@ "column.home": "Home", "column.mutes": "Utilizadores silenciados", "column.notifications": "Notificações", + "column.pins": "Pinned toot", "column.public": "Global", "column_back_button.label": "Voltar", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Mais informações", "navigation_bar.logout": "Sair", "navigation_bar.mutes": "Utilizadores silenciados", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Preferências", "navigation_bar.public_timeline": "Global", "notification.favourite": "{name} adicionou o teu post aos favoritos", @@ -193,6 +195,15 @@ "upload_button.label": "Adicionar media", "upload_form.undo": "Anular", "upload_progress.label": "A gravar...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Expandir vídeo", "video_player.toggle_sound": "Ligar/Desligar som", "video_player.toggle_visible": "Ligar/Desligar vídeo", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json @@ -33,6 +33,7 @@ "column.home": "Главная", "column.mutes": "Список глушения", "column.notifications": "Уведомления", + "column.pins": "Pinned toot", "column.public": "Глобальная лента", "column_back_button.label": "Назад", "column_header.hide_settings": "Скрыть настройки", @@ -109,6 +110,7 @@ "navigation_bar.info": "Об узле", "navigation_bar.logout": "Выйти", "navigation_bar.mutes": "Список глушения", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Опции", "navigation_bar.public_timeline": "Глобальная лента", "notification.favourite": "{name} понравился Ваш статус", @@ -193,6 +195,15 @@ "upload_button.label": "Добавить медиаконтент", "upload_form.undo": "Отменить", "upload_progress.label": "Загрузка...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Развернуть видео", "video_player.toggle_sound": "Вкл./выкл. звук", "video_player.toggle_visible": "Показать/скрыть", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json @@ -33,6 +33,7 @@ "column.home": "Home", "column.mutes": "Muted users", "column.notifications": "Notifications", + "column.pins": "Pinned toot", "column.public": "Federated timeline", "column_back_button.label": "Back", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "About this instance", "navigation_bar.logout": "Logout", "navigation_bar.mutes": "Muted users", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Preferences", "navigation_bar.public_timeline": "Federated timeline", "notification.favourite": "{name} favourited your status", @@ -193,6 +195,15 @@ "upload_button.label": "Add media", "upload_form.undo": "Undo", "upload_progress.label": "Uploading...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Expand video", "video_player.toggle_sound": "Toggle sound", "video_player.toggle_visible": "Toggle visibility", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json @@ -33,6 +33,7 @@ "column.home": "Anasayfa", "column.mutes": "Susturulmuş kullanıcılar", "column.notifications": "Bildirimler", + "column.pins": "Pinned toot", "column.public": "Federe zaman tüneli", "column_back_button.label": "Geri", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Genişletilmiş bilgi", "navigation_bar.logout": "Çıkış", "navigation_bar.mutes": "Sessize alınmış kullanıcılar", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Tercihler", "navigation_bar.public_timeline": "Federe zaman tüneli", "notification.favourite": "{name} senin durumunu favorilere ekledi", @@ -193,6 +195,15 @@ "upload_button.label": "Görsel ekle", "upload_form.undo": "Geri al", "upload_progress.label": "Yükleniyor...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Videoyu genişlet", "video_player.toggle_sound": "Sesi aç/kapa", "video_player.toggle_visible": "Göster/gizle", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json @@ -33,6 +33,7 @@ "column.home": "Головна", "column.mutes": "Заглушені користувачі", "column.notifications": "Сповіщення", + "column.pins": "Pinned toot", "column.public": "Глобальна стрічка", "column_back_button.label": "Назад", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "Про інстанцію", "navigation_bar.logout": "Вийти", "navigation_bar.mutes": "Заглушені користувачі", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "Налаштування", "navigation_bar.public_timeline": "Глобальна стрічка", "notification.favourite": "{name} сподобався ваш допис", @@ -193,6 +195,15 @@ "upload_button.label": "Додати медіаконтент", "upload_form.undo": "Відмінити", "upload_progress.label": "Завантаження...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "Розгорнути ", "video_player.toggle_sound": "Увімкнути/вимкнути звук", "video_player.toggle_visible": "Показати/приховати", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json @@ -33,6 +33,7 @@ "column.home": "主页", "column.mutes": "被静音的用户", "column.notifications": "通知", + "column.pins": "Pinned toot", "column.public": "跨站公共时间轴", "column_back_button.label": "返回", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "关于本站", "navigation_bar.logout": "注销", "navigation_bar.mutes": "被静音的用户", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "首选项", "navigation_bar.public_timeline": "跨站公共时间轴", "notification.favourite": "{name} 赞了你的嘟文", @@ -193,6 +195,15 @@ "upload_button.label": "上传媒体文件", "upload_form.undo": "还原", "upload_progress.label": "上传中……", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "展开影片", "video_player.toggle_sound": "开关音效", "video_player.toggle_visible": "打开或关上", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json @@ -33,6 +33,7 @@ "column.home": "主頁", "column.mutes": "靜音名單", "column.notifications": "通知", + "column.pins": "Pinned toot", "column.public": "跨站時間軸", "column_back_button.label": "返回", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "關於本服務站", "navigation_bar.logout": "登出", "navigation_bar.mutes": "被你靜音的用戶", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "偏好設定", "navigation_bar.public_timeline": "跨站時間軸", "notification.favourite": "{name} 喜歡你的文章", @@ -193,6 +195,15 @@ "upload_button.label": "上載媒體檔案", "upload_form.undo": "還原", "upload_progress.label": "上載中……", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "展開影片", "video_player.toggle_sound": "開關音效", "video_player.toggle_visible": "打開或關上", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json @@ -33,6 +33,7 @@ "column.home": "家", "column.mutes": "消音的使用者", "column.notifications": "通知", + "column.pins": "Pinned toot", "column.public": "聯盟時間軸", "column_back_button.label": "上一頁", "column_header.hide_settings": "Hide settings", @@ -109,6 +110,7 @@ "navigation_bar.info": "關於本站", "navigation_bar.logout": "登出", "navigation_bar.mutes": "消音的使用者", + "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "偏好設定", "navigation_bar.public_timeline": "聯盟時間軸", "notification.favourite": "{name}喜歡你的狀態", @@ -193,6 +195,15 @@ "upload_button.label": "增加媒體", "upload_form.undo": "復原", "upload_progress.label": "上傳中...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound", "video_player.expand": "展開影片", "video_player.toggle_sound": "切換音效", "video_player.toggle_visible": "切換可見性", diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js @@ -24,6 +24,11 @@ function main() { const emojify = require('../mastodon/emoji').default; const { getLocale } = require('../mastodon/locales'); const { localeData } = getLocale(); + const VideoContainer = require('../mastodon/containers/video_container').default; + const MediaGalleryContainer = require('../mastodon/containers/media_gallery_container').default; + const CardContainer = require('../mastodon/containers/card_container').default; + const React = require('react'); + const ReactDOM = require('react-dom'); localeData.forEach(IntlRelativeFormat.__addLocaleData); @@ -65,22 +70,21 @@ function main() { window.open(e.target.href, 'mastodon-intent', 'width=400,height=400,resizable=no,menubar=no,status=no,scrollbars=yes'); }); }); - }); - delegate(document, '.video-player video', 'click', ({ target }) => { - if (target.paused) { - target.play(); - } else { - target.pause(); - } - }); + [].forEach.call(document.querySelectorAll('[data-component="Video"]'), (content) => { + const props = JSON.parse(content.getAttribute('data-props')); + ReactDOM.render(<VideoContainer locale={locale} {...props} />, content); + }); - delegate(document, '.activity-stream .media-spoiler-wrapper .media-spoiler', 'click', function() { - this.parentNode.classList.add('media-spoiler-wrapper__visible'); - }); + [].forEach.call(document.querySelectorAll('[data-component="MediaGallery"]'), (content) => { + const props = JSON.parse(content.getAttribute('data-props')); + ReactDOM.render(<MediaGalleryContainer locale={locale} {...props} />, content); + }); - delegate(document, '.activity-stream .media-spoiler-wrapper .spoiler-button', 'click', function() { - this.parentNode.classList.remove('media-spoiler-wrapper__visible'); + [].forEach.call(document.querySelectorAll('[data-component="Card"]'), (content) => { + const props = JSON.parse(content.getAttribute('data-props')); + ReactDOM.render(<CardContainer locale={locale} {...props} />, content); + }); }); delegate(document, '.webapp-btn', 'click', ({ target, button }) => { diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss @@ -566,6 +566,10 @@ opacity: 1; animation: fade 150ms linear; + .video-player { + margin-top: 8px; + } + &.status-direct { background: lighten($ui-base-color, 8%); @@ -734,6 +738,10 @@ height: 22px; } } + + .video-player { + margin-top: 8px; + } } .detailed-status__meta { @@ -1404,9 +1412,6 @@ .drawer { flex: 1 1 100%; overflow: hidden; - @supports(display: grid) { // hack to fix Chrome <57 - contain: strict; - } } @media screen and (min-width: 360px) { @@ -1582,9 +1587,6 @@ overflow-x: hidden; flex: 1 1 auto; -webkit-overflow-scrolling: touch; - @supports(display: grid) { // hack to fix Chrome <57 - contain: strict; - } &.optionally-scrollable { overflow-y: auto; @@ -2341,10 +2343,16 @@ button.icon-button.active i.fa-retweet { .media-spoiler { background: $base-overlay-background; - color: $primary-text-color; + color: $ui-primary-color; border: 0; width: 100%; height: 100%; + + &:hover, + &:active, + &:focus { + color: lighten($ui-primary-color, 8%); + } } .media-spoiler__warning { @@ -3798,6 +3806,181 @@ button.icon-button.active i.fa-retweet { z-index: 5; } +.video-player { + overflow: hidden; + position: relative; + background: $base-shadow-color; + + video { + height: 100%; + width: 100%; + z-index: 1; + } + + &.fullscreen { + width: 100% !important; + height: 100% !important; + margin: 0; + + video { + max-width: 100% !important; + max-height: 100% !important; + } + } + + &.inline { + video { + object-fit: cover; + position: relative; + top: 50%; + transform: translateY(-50%); + } + } + + &__controls { + position: absolute; + z-index: 2; + bottom: 0; + left: 0; + right: 0; + box-sizing: border-box; + background: linear-gradient(0deg, rgba($base-shadow-color, 0.8) 0, rgba($base-shadow-color, 0.35) 60%, transparent); + padding: 0 10px; + opacity: 0; + transition: opacity .1s ease; + + &.active { + opacity: 1; + } + } + + &.inactive { + video, + .video-player__controls { + visibility: hidden; + } + } + + &__spoiler { + display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 4; + border: 0; + background: $base-shadow-color; + color: $ui-primary-color; + transition: none; + pointer-events: none; + + &.active { + display: block; + pointer-events: auto; + + &:hover, + &:active, + &:focus { + color: lighten($ui-primary-color, 8%); + } + } + + &__title { + display: block; + font-size: 14px; + } + + &__subtitle { + display: block; + font-size: 11px; + font-weight: 500; + } + } + + &__buttons { + padding-bottom: 10px; + font-size: 16px; + + &.left { + float: left; + + button { + padding-right: 10px; + } + } + + &.right { + float: right; + + button { + padding-left: 10px; + } + } + + button { + background: transparent; + padding: 0; + border: 0; + color: $white; + + &:active, + &:hover, + &:focus { + color: $ui-highlight-color; + } + } + } + + &__seek { + cursor: pointer; + height: 24px; + position: relative; + + &::before { + content: ""; + width: 100%; + background: rgba($white, 0.35); + display: block; + position: absolute; + height: 4px; + top: 10px; + } + + &__progress { + display: block; + position: absolute; + height: 4px; + top: 10px; + background: $ui-highlight-color; + } + + &__handle { + position: absolute; + z-index: 3; + opacity: 0; + border-radius: 50%; + width: 12px; + height: 12px; + top: 6px; + margin-left: -6px; + transition: opacity .1s ease; + background: $ui-highlight-color; + pointer-events: none; + + &.active { + opacity: 1; + } + } + + &:hover { + .video-player__seek__handle { + opacity: 1; + } + } + } +} + .media-spoiler-video { background-size: cover; background-repeat: no-repeat; diff --git a/app/javascript/styles/stream_entries.scss b/app/javascript/styles/stream_entries.scss @@ -143,19 +143,6 @@ } } } - - .status__attachments { - margin-top: 8px; - overflow: hidden; - width: 100%; - box-sizing: border-box; - position: relative; - - .status__attachments__inner { - display: flex; - height: 214px; - } - } } .detailed-status.light { @@ -237,139 +224,22 @@ } } - .detailed-status__attachments { - margin-top: 8px; - overflow: hidden; - width: 100%; - box-sizing: border-box; - position: relative; + .status-card { + border-color: lighten($ui-secondary-color, 4%); + color: darken($ui-primary-color, 4%); - .status__attachments__inner { - display: flex; - height: 360px; - } - } - - .video-player { - margin-top: 8px; - height: 300px; - overflow: hidden; - position: relative; - - video { - position: relative; - z-index: 1; - width: 100%; - height: 100%; - object-fit: cover; - top: 50%; - transform: translateY(-50%); + &:hover { + background: lighten($ui-secondary-color, 4%); } } - } - .media-item, - .video-item { - box-sizing: border-box; - position: relative; - left: auto; - top: auto; - right: auto; - bottom: auto; - float: left; - border: medium none; - display: block; - flex: 1 1 auto; - width: 100%; - height: 100%; - overflow: hidden; - margin-right: 2px; - - &:last-child { - margin-right: 0; - } - - a { - display: block; - width: 100%; - height: 100%; - background: no-repeat scroll center center / cover; - text-decoration: none; - cursor: zoom-in; - } - - video { - position: relative; - z-index: 1; - width: 100%; - height: 100%; - object-fit: cover; - top: 50%; - transform: translateY(-50%); - } - } - - .video-item { - a { - cursor: pointer; - } - - .video-item__play { - position: absolute; - top: 50%; - left: 50%; - font-size: 36px; - transform: translate(-50%, -50%); - padding: 5px; - border-radius: 100px; - color: rgba($primary-text-color, 0.8); - z-index: 1; - } - } - - .media-spoiler { - background: $ui-primary-color; - width: 100%; - height: 100%; - cursor: pointer; - position: absolute; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - text-align: center; - transition: all 100ms linear; - z-index: 2; - - &:hover { - background: darken($ui-primary-color, 5%); - } - - span { - display: block; - - &:first-child { - font-size: 14px; - } - - &:last-child { - font-size: 11px; - font-weight: 500; - } + .status-card__title, + .status-card__description { + color: $ui-base-color; } - } - - .media-spoiler-wrapper { - &.media-spoiler-wrapper__visible { - .media-spoiler { - display: none; - } - .spoiler-button { - display: block; - } + .status-card__image { + background: $ui-secondary-color; } } diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml @@ -19,17 +19,14 @@ %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status) - - unless status.media_attachments.empty? + - if !status.media_attachments.empty? - if status.media_attachments.first.video? - .video-player - = render partial: 'stream_entries/content_spoiler', locals: { sensitive: status.sensitive? } - %video.u-video{ src: status.media_attachments.first.file.url(:original), loop: true } + - video = status.media_attachments.first + %div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive?, width: 670, height: 380) }} - else - .detailed-status__attachments - = render partial: 'stream_entries/content_spoiler', locals: { sensitive: status.sensitive? } - .status__attachments__inner - - status.media_attachments.each do |media| - = render partial: 'stream_entries/media', locals: { media: media } + %div{ data: { component: 'MediaGallery', props: Oj.dump(height: 380, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }) }} + - elsif status.preview_cards.first + %div{ data: { component: 'Card', props: Oj.dump('maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_cards.first, serializer: REST::PreviewCardSerializer).as_json) }} .detailed-status__meta %data.dt-published{ value: status.created_at.to_time.iso8601 } diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml @@ -21,15 +21,8 @@ .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status) - unless status.media_attachments.empty? - .status__attachments - = render partial: 'stream_entries/content_spoiler', locals: { sensitive: status.sensitive? } - - if status.media_attachments.first.video? - .status__attachments__inner - .video-item - = link_to (status.media_attachments.first.remote_url.blank? ? status.media_attachments.first.file.url(:original) : status.media_attachments.first.remote_url), style: "background-image: url(#{status.media_attachments.first.file.url(:small)})", target: '_blank', rel: 'noopener', class: 'u-video' do - .video-item__play - = fa_icon('play') - - else - .status__attachments__inner - - status.media_attachments.each do |media| - = render partial: 'stream_entries/media', locals: { media: media } + - if status.media_attachments.first.video? + - video = status.media_attachments.first + %div{ data: { component: 'Video', props: Oj.dump(src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive?, width: 610, height: 343) }} + - else + %div{ data: { component: 'MediaGallery', props: Oj.dump(height: 343, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }) }}