...
 
Commits (8)
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -9,11 +9,34 @@ import classNames from 'classnames';
import { autoPlayGif, displaySensitiveMedia } from '../initial_state';
const messages = defineMessages({
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
hidden: {
defaultMessage: 'Media hidden',
id: 'status.media_hidden',
},
sensitive: {
defaultMessage: 'Sensitive',
id: 'media_gallery.sensitive',
},
toggle: {
defaultMessage: 'Click to view',
id: 'status.sensitive_toggle',
},
toggle_visible: {
defaultMessage: 'Toggle visibility',
id: 'media_gallery.toggle_visible',
},
warning: {
defaultMessage: 'Sensitive content',
id: 'status.sensitive_warning',
},
});
class Item extends React.PureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = {
attachment: ImmutablePropTypes.map.isRequired,
standalone: PropTypes.bool,
......@@ -49,7 +72,7 @@ class Item extends React.PureComponent {
handleClick = (e) => {
const { index, onClick } = this.props;
if (e.button === 0) {
if (this.context.router && e.button === 0) {
e.preventDefault();
onClick(index);
}
......@@ -145,6 +168,18 @@ class Item extends React.PureComponent {
/>
</a>
);
} else if (attachment.get('type') === 'audio') {
thumbnail = (
<div className='media-gallery__audio'>
<audio
className='media-gallery__item-audio-thumbnail'
aria-label={attachment.get('description')}
role='application'
src={attachment.get('url')}
loop
/>
</div>
);
} else if (attachment.get('type') === 'gifv') {
const autoPlay = !isIOS() && autoPlayGif;
......@@ -212,70 +247,77 @@ export default class MediaGallery extends React.PureComponent {
this.props.onOpenMedia(this.props.media, index);
}
handleRef = (node) => {
if (node /*&& this.isStandaloneEligible()*/) {
// offsetWidth triggers a layout, so only calculate when we need to
this.setState({
width: node.offsetWidth,
});
}
}
isStandaloneEligible() {
const { media, standalone } = this.props;
return standalone && media.size === 1 && media.getIn([0, 'meta', 'small', 'aspect']);
}
render () {
const { media, intl, sensitive, height } = this.props;
const { width, visible } = this.state;
let children;
const style = {};
if (this.isStandaloneEligible()) {
if (width) {
style.height = width / this.props.media.getIn([0, 'meta', 'small', 'aspect']);
}
} else if (width) {
style.height = width / (16/9);
} else {
style.height = height;
}
if (!visible) {
let warning;
if (sensitive) {
warning = <FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' />;
} else {
warning = <FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' />;
}
children = (
<button type='button' className='media-spoiler' onClick={this.handleOpen} style={style} ref={this.handleRef}>
<span className='media-spoiler__warning'>{warning}</span>
<span className='media-spoiler__trigger'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
</button>
);
} else {
const size = media.take(4).size;
if (this.isStandaloneEligible()) {
children = <Item standalone onClick={this.handleClick} attachment={media.get(0)} />;
} else {
children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} />);
}
}
const {
handleClick,
handleOpen,
} = this;
const {
fullwidth,
intl,
media,
sensitive,
standalone,
} = this.props;
const { visible } = this.state;
const size = media.take(4).size;
const computedClass = classNames('media-gallery', `size-${size}`, { 'full-width': fullwidth });
return (
<div className='media-gallery' style={style} ref={this.handleRef}>
<div className={classNames('spoiler-button', { 'spoiler-button--visible': visible })}>
<IconButton title={intl.formatMessage(messages.toggle_visible)} icon={visible ? 'eye' : 'eye-slash'} overlay onClick={this.handleOpen} />
</div>
{children}
<div className={computedClass}>
{visible ? (
<div className='sensitive-info'>
<IconButton
icon='eye'
onClick={handleOpen}
overlay
title={intl.formatMessage(messages.toggle_visible)}
/>
{sensitive ? (
<span className='sensitive-marker'>
<FormattedMessage {...messages.sensitive} />
</span>
) : null}
</div>
) : null}
{function () {
switch (true) {
case !visible:
return (
<button
className='media-spoiler'
onClick={handleOpen}
>
<span className='media-spoiler__warning'>
<FormattedMessage {...(sensitive ? messages.warning : messages.hidden)} />
</span>
<span className='media-spoiler__trigger'>
<FormattedMessage {...messages.toggle} />
</span>
</button>
);
case standalone && media.size === 1 && !!media.getIn([0, 'meta', 'small', 'aspect']):
return (
<Item
attachment={media.get(0)}
onClick={handleClick}
standalone
/>
);
default:
return media.take(4).map(
(attachment, i) => (
<Item
attachment={attachment}
index={i}
key={attachment.get('id')}
onClick={handleClick}
size={size}
/>
)
);
}
}()}
</div>
);
}
......
......@@ -3,6 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import IconButton from '../../../components/icon_button';
import Motion from '../../ui/util/optional_motion';
import spring from 'react-motion/lib/spring';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { autoPlayGif, me } from '../../../initial_state';
......@@ -40,20 +41,24 @@ class Avatar extends ImmutablePureComponent {
const { isHovered } = this.state;
return (
<a
href={account.get('url')}
className='account__header__avatar'
role='presentation'
target='_blank'
rel='noopener'
style={{ backgroundImage: `url(${autoPlayGif || isHovered ? account.get('avatar') : account.get('avatar_static')})` }}
onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
onFocus={this.handleMouseOver}
onBlur={this.handleMouseOut}
>
<span style={{ display: 'none' }}>{account.get('acct')}</span>
</a>
<Motion defaultStyle={{ radius: 90 }} style={{ radius: spring(isHovered ? 30 : 90, { stiffness: 180, damping: 12 }) }}>
{({ radius }) => (
<a
href={account.get('url')}
className='account__header__avatar'
role='presentation'
target='_blank'
rel='noopener'
style={{ borderRadius: `${radius}px`, backgroundImage: `url(${autoPlayGif || isHovered ? account.get('avatar') : account.get('avatar_static')})` }}
onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
onFocus={this.handleMouseOver}
onBlur={this.handleMouseOut}
>
<span style={{ display: 'none' }}>{account.get('acct')}</span>
</a>
)}
</Motion>
);
}
......
@import 'mastodon/mixins';
@import 'mastodon/variables';
@import 'fonts/roboto';
@import 'fonts/roboto-mono';
@import 'fonts/montserrat';
@import 'mastodon/reset';
@import 'mastodon/basics';
......
@import 'mastodon/variables';
@import 'fonts/roboto';
table,
td,
......
@mixin avatar-radius() {
border-radius: 50%;
border-radius: 4px;
background: transparent no-repeat;
background-position: 50%;
background-clip: padding-box;
-moz-transition: all 300ms;
-o-transition: all 300ms;
-webkit-transition: all 300ms;
transition: all 300ms;
&:hover {
border-radius: 10%;
}
}
@mixin avatar-size($size:48px) {
......
......@@ -180,7 +180,7 @@ $small-breakpoint: 960px;
p,
li {
font-family: 'mastodon-font-sans-serif', sans-serif;
font-family: sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
......@@ -229,7 +229,7 @@ $small-breakpoint: 960px;
}
h1 {
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
font-size: 26px;
line-height: 30px;
font-weight: 500;
......@@ -237,7 +237,7 @@ $small-breakpoint: 960px;
color: $ui-secondary-color;
small {
font-family: 'mastodon-font-sans-serif', sans-serif;
font-family: sans-serif;
display: block;
font-size: 18px;
font-weight: 400;
......@@ -246,7 +246,7 @@ $small-breakpoint: 960px;
}
h2 {
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
font-size: 22px;
line-height: 26px;
font-weight: 500;
......@@ -255,7 +255,7 @@ $small-breakpoint: 960px;
}
h3 {
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
font-size: 18px;
line-height: 24px;
font-weight: 500;
......@@ -264,7 +264,7 @@ $small-breakpoint: 960px;
}
h4 {
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 500;
......@@ -273,7 +273,7 @@ $small-breakpoint: 960px;
}
h5 {
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
font-size: 14px;
line-height: 24px;
font-weight: 500;
......@@ -282,7 +282,7 @@ $small-breakpoint: 960px;
}
h6 {
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
font-size: 12px;
line-height: 24px;
font-weight: 500;
......@@ -349,7 +349,7 @@ $small-breakpoint: 960px;
.hero .heading {
padding-bottom: 20px;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-family: sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
......@@ -400,7 +400,7 @@ $small-breakpoint: 960px;
text-decoration: none;
padding: 12px 16px;
line-height: 32px;
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
font-weight: 500;
font-size: 14px;
......@@ -473,7 +473,7 @@ $small-breakpoint: 960px;
.about-short {
background: darken($ui-base-color, 4%);
padding: 50px 0 30px;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-family: sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
......@@ -503,7 +503,7 @@ $small-breakpoint: 960px;
&__section {
flex: 1 0 0;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-family: sans-serif;
font-size: 16px;
line-height: 28px;
color: $primary-text-color;
......@@ -544,7 +544,7 @@ $small-breakpoint: 960px;
bottom: -40px;
.panel-header {
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
font-size: 14px;
line-height: 24px;
font-weight: 500;
......@@ -853,7 +853,7 @@ $small-breakpoint: 960px;
display: flex;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-family: sans-serif;
font-size: 13px;
line-height: 18px;
font-weight: 400;
......@@ -964,7 +964,7 @@ $small-breakpoint: 960px;
.extended-description {
padding: 50px 0;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-family: sans-serif;
font-size: 16px;
font-weight: 400;
font-size: 16px;
......
......@@ -170,7 +170,7 @@
font-weight: 500;
font-size: 18px;
color: $primary-text-color;
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
}
}
......
......@@ -460,7 +460,7 @@
border-radius: 0 0 4px 4px;
padding: 10px;
color: $ui-primary-color;
font-family: 'mastodon-font-monospace', monospace;
font-family: monospace;
font-size: 12px;
word-wrap: break-word;
min-height: 20px;
......
body {
font-family: 'mastodon-font-sans-serif', sans-serif;
font-family: sans-serif;
background: $ui-base-color;
background-size: cover;
background-attachment: fixed;
......@@ -14,21 +14,6 @@ body {
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-tap-highlight-color: transparent;
&.system-font {
// system-ui => standard property (Chrome/Android WebView 56+, Opera 43+, Safari 11+)
// -apple-system => Safari <11 specific
// BlinkMacSystemFont => Chrome <56 on macOS specific
// Segoe UI => Windows 7/8/10
// Oxygen => KDE
// Ubuntu => Unity/Ubuntu
// Cantarell => GNOME
// Fira Sans => Firefox OS
// Droid Sans => Older Androids (<4.0)
// Helvetica Neue => Older macOS <10.11
// mastodon-font-sans-serif => web-font (Roboto) fallback and newer Androids (>=4.0)
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", mastodon-font-sans-serif, sans-serif;
}
&.app-body {
position: absolute;
width: 100%;
......
......@@ -560,7 +560,7 @@
.character-counter {
cursor: default;
font-family: 'mastodon-font-sans-serif', sans-serif;
font-family: sans-serif;
font-size: 14px;
font-weight: 600;
color: lighten($ui-base-color, 12%);
......@@ -644,6 +644,7 @@
overflow: hidden;
white-space: pre-wrap;
padding-top: 2px;
overflow-y: auto;
&:focus {
outline: 0;
......@@ -714,6 +715,23 @@
display: block;
}
}
em {
font-style: italic;
}
strong {
font-weight: bold;
}
ul li:before {
content: "• ";
}
}
.reply-indicator__content {
max-height: 20ch;
}
.status__content {
max-height: 30ch;
}
.status__content__spoiler-link {
......@@ -760,7 +778,6 @@
padding: 8px 10px;
padding-left: 68px;
position: relative;
min-height: 48px;
border-bottom: 1px solid lighten($ui-base-color, 8%);
cursor: default;
......@@ -828,13 +845,22 @@
}
}
.notification-favourite {
.status.status-direct {
background: transparent;
.icon-button.disabled {
color: lighten($ui-base-color, 13%);
}
.notification-favourite,
.notification-reblog {
.status__action-bar,
.status__display-name,
.status__display-name .account__avatar-overlay,
.status__display-name .display-name {
display: none;
}
.notification__message {
margin-left: 42px;
}
.status {
padding-left: 10px;
}
.status__content {
max-height: 5ch;
}
}
......@@ -1271,14 +1297,6 @@
margin: 0 auto 10px;
overflow: hidden;
width: 90px;
border-radius: 50%;
-moz-transition: all 300ms;
-o-transition: all 300ms;
-webkit-transition: all 300ms;
transition: all 300ms;
&:hover {
border-radius: 10%;
}
}
.account-authorize {
......@@ -4948,7 +4966,7 @@ noscript {
width: 100%;
border: none;
padding: 10px;
font-family: 'mastodon-font-monospace', monospace;
font-family: monospace;
background: $ui-base-color;
color: $ui-primary-color;
font-size: 14px;
......
......@@ -37,7 +37,7 @@
outline: 0;
padding: 12px 16px;
line-height: 32px;
font-family: 'mastodon-font-display', sans-serif;
font-family: sans-serif;
font-weight: 500;
font-size: 14px;
}
......
code {
font-family: 'mastodon-font-monospace', monospace;
font-family: monospace;
font-weight: 400;
}
......@@ -385,7 +385,7 @@ code {
width: 100%;
border: none;
padding: 10px;
font-family: 'mastodon-font-monospace', monospace;
font-family: monospace;
background: $ui-base-color;
color: $ui-primary-color;
font-size: 14px;
......
......@@ -60,7 +60,7 @@
}
samp {
font-family: 'mastodon-font-monospace', monospace;
font-family: monospace;
}
a.table-action-link {
......
#!/bin/sh
# Assuming pleroma sits in the upper directory under the dir "pleroma"
TARGET="../pleroma" # Where pleroma’s repository is sitting
rm -rf public/packs public/assets
env -i "PATH=$PATH" npm run build
cp public/assets/sw.js ../pleroma/priv/static/sw.js
rm -rf ../pleroma/priv/static/packs
cp -r public/packs ../pleroma/priv/static/packs
cp public/assets/sw.js "${TARGET}/priv/static/sw.js"
rm -rf "${TARGET}/priv/static/packs"
cp -r public/packs "${TARGET}/priv/static/packs"