Progress
This commit is contained in:
parent
389b189d64
commit
cdde454915
@ -132,8 +132,8 @@ class Account extends ImmutablePureComponent {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={[styles.default, styles.marginLeftAuto].join(' ')}>
|
<div className={[styles.default, styles.marginLeftAuto].join(' ')}>
|
||||||
<button className={[styles.default, styles.circle, styles.backgroundSubtle2, styles.paddingVertical5PX, styles.paddingHorizontal5PX, styles.cursorPointer].join(' ')}>
|
<button className={[styles.default, styles.circle, styles.backgroundTransparent, styles.paddingVertical5PX, styles.paddingHorizontal5PX, styles.cursorPointer].join(' ')}>
|
||||||
<Icon id='close' width='8px' height='8px' />
|
<Icon className={styles.fillColorSubtle} id='close' width='8px' height='8px' />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,33 +1,20 @@
|
|||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
|
|
||||||
export default class Button extends PureComponent {
|
export default class Button extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
text: PropTypes.node,
|
text: PropTypes.node,
|
||||||
|
to: PropTypes.string,
|
||||||
href: PropTypes.string,
|
href: PropTypes.string,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
block: PropTypes.bool,
|
block: PropTypes.bool,
|
||||||
secondary: PropTypes.bool,
|
secondary: PropTypes.bool,
|
||||||
children: PropTypes.node,
|
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
|
||||||
hovering: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOnMouseEnter = () => {
|
|
||||||
this.setState({
|
|
||||||
hovering: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOnMouseLeave = () => {
|
|
||||||
this.setState({
|
|
||||||
hovering: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick = (e) => {
|
handleClick = (e) => {
|
||||||
if (!this.props.disabled && this.props.onClick) {
|
if (!this.props.disabled && this.props.onClick) {
|
||||||
@ -44,8 +31,7 @@ export default class Button extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { secondary, block, className, disabled, text, children, href } = this.props
|
const { block, className, disabled, text, to, children, href } = this.props
|
||||||
const { hovering } = this.state
|
|
||||||
|
|
||||||
const cx = classNames.bind(styles)
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
@ -60,21 +46,22 @@ export default class Button extends PureComponent {
|
|||||||
paddingVertical10PX: 1,
|
paddingVertical10PX: 1,
|
||||||
paddingHorizontal15PX: 1,
|
paddingHorizontal15PX: 1,
|
||||||
width100PC: block,
|
width100PC: block,
|
||||||
backgroundColorBrand: !hovering,
|
backgroundColorBrand: 1,
|
||||||
backgroundColorBrandDark: hovering,
|
backgroundColorBrandDark_onHover: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (href) {
|
if (href) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a className={classes} href={href}>
|
||||||
className={classes}
|
|
||||||
href={href}
|
|
||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
|
||||||
>
|
|
||||||
{text || children}
|
{text || children}
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
|
} else if (to) {
|
||||||
|
return (
|
||||||
|
<NavLink className={classes} to={to}>
|
||||||
|
{text || children}
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -83,8 +70,6 @@ export default class Button extends PureComponent {
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
className={classes}
|
className={classes}
|
||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
|
||||||
>
|
>
|
||||||
{text || children}
|
{text || children}
|
||||||
</button>
|
</button>
|
||||||
|
@ -26,7 +26,7 @@ export default class Column extends PureComponent {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div role='region' aria-labelledby={columnHeaderId} className='column'>
|
<div role='region' aria-labelledby={columnHeaderId} className={[styles.default].join(' ')}>
|
||||||
{ backBtn && <ColumnBackButton slim={backBtn === 'slim'} />}
|
{ backBtn && <ColumnBackButton slim={backBtn === 'slim'} />}
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
145
app/javascript/gabsocial/components/column_header.js
Normal file
145
app/javascript/gabsocial/components/column_header.js
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import Icon from './icon'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
||||||
|
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
||||||
|
})
|
||||||
|
|
||||||
|
export default @injectIntl
|
||||||
|
class ColumnHeader extends PureComponent {
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
router: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
title: PropTypes.node,
|
||||||
|
icon: PropTypes.string,
|
||||||
|
active: PropTypes.bool,
|
||||||
|
children: PropTypes.node,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
collapsed: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
historyBack = () => {
|
||||||
|
if (window.history && window.history.length === 1) {
|
||||||
|
this.context.router.history.push('/home') // homehack
|
||||||
|
} else {
|
||||||
|
this.context.router.history.goBack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleToggleClick = (e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
this.setState({
|
||||||
|
collapsed: !this.state.collapsed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBackClick = () => {
|
||||||
|
this.historyBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { title, icon, active, children, intl: { formatMessage } } = this.props
|
||||||
|
const { collapsed } = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[styles.default, styles.height100PC, styles.flexRow].join(' ')}>
|
||||||
|
{ /* <button className={[styles.default, styles.cursorPointer, styles.backgroundTransparent, styles.alignItemsCenter, styles.marginRight10PX, styles.justifyContentCenter].join(' ')}>
|
||||||
|
<Icon className={[styles.marginRight5PX, styles.fillColorBrand].join(' ')} id='back' width='24px' height='24px' />
|
||||||
|
</button> */ }
|
||||||
|
<h1 className={[styles.default, styles.height100PC, styles.justifyContentCenter].join(' ')}>
|
||||||
|
<span className={[styles.default, styles.text, styles.fontSize24PX, styles.fontWeight500, styles.colorBlack].join(' ')}>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
<div className={[styles.default, styles.backgroundTransparent, styles.flexRow, styles.alignItemsCenter, styles.justifyContentCenter, styles.marginLeftAuto].join(' ')}>
|
||||||
|
<button className={[styles.default, styles.marginLeft5PX, styles.cursorPointer, styles.backgroundSubtle2, styles.paddingHorizontal10PX, styles.paddingVertical5PX, styles.radiusSmall].join(' ')}>
|
||||||
|
<Icon className={styles.fillColorSubtle} id='ellipsis' width='24px' height='24px' />
|
||||||
|
</button>
|
||||||
|
<button className={[styles.default, styles.marginLeft5PX, styles.cursorPointer, styles.backgroundSubtle2, styles.paddingHorizontal10PX, styles.paddingVertical5PX, styles.radiusSmall].join(' ')}>
|
||||||
|
<Icon className={styles.fillColorSubtle} id='ellipsis' width='24px' height='24px' />
|
||||||
|
</button>
|
||||||
|
<button className={[styles.default, styles.marginLeft5PX, styles.cursorPointer, styles.backgroundSubtle2, styles.paddingHorizontal10PX, styles.paddingVertical5PX, styles.radiusSmall].join(' ')}>
|
||||||
|
<Icon className={styles.fillColorSubtle} id='ellipsis' width='24px' height='24px' />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
// const wrapperClassName = classNames('column-header__wrapper', {
|
||||||
|
// 'column-header__wrapper--active': active,
|
||||||
|
// })
|
||||||
|
|
||||||
|
// const buttonClassName = classNames('column-header', {
|
||||||
|
// 'column-header--active': active,
|
||||||
|
// })
|
||||||
|
|
||||||
|
// const btnTitle = formatMessage(collapsed ? messages.show : messages.hide)
|
||||||
|
// const hasTitle = icon && title
|
||||||
|
// const hasChildren = !!children
|
||||||
|
|
||||||
|
// if (!hasChildren && !hasTitle) {
|
||||||
|
// return null
|
||||||
|
// } else if (!hasChildren && hasTitle) {
|
||||||
|
// return (
|
||||||
|
// <div className={wrapperClassName}>
|
||||||
|
// <h1 className={buttonClassName}>
|
||||||
|
// <Icon id={icon} fixedWidth className='column-header__icon' />
|
||||||
|
// {title}
|
||||||
|
// </h1>
|
||||||
|
// </div>
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const collapsibleClassName = classNames('column-header__collapsible', {
|
||||||
|
// 'column-header__collapsible--collapsed': collapsed,
|
||||||
|
// })
|
||||||
|
|
||||||
|
// const collapsibleButtonClassName = classNames('column-header__button', {
|
||||||
|
// 'column-header__button--active': !collapsed,
|
||||||
|
// })
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div className={wrapperClassName}>
|
||||||
|
// <h1 className={buttonClassName}>
|
||||||
|
// {
|
||||||
|
// hasTitle && (
|
||||||
|
// <Fragment>
|
||||||
|
// <Icon id={icon} fixedWidth className='column-header__icon' />
|
||||||
|
// {title}
|
||||||
|
// </Fragment>
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
|
// <button
|
||||||
|
// className={collapsibleButtonClassName}
|
||||||
|
// title={btnTitle}
|
||||||
|
// aria-label={btnTitle}
|
||||||
|
// aria-pressed={!collapsed}
|
||||||
|
// onClick={this.handleToggleClick}
|
||||||
|
// >
|
||||||
|
// <Icon id='sliders' />
|
||||||
|
// </button>
|
||||||
|
// </h1>
|
||||||
|
|
||||||
|
// <div className={collapsibleClassName} tabIndex={collapsed ? -1 : null}>
|
||||||
|
// <div className='column-header__collapsible-inner'>
|
||||||
|
// {
|
||||||
|
// !collapsed &&
|
||||||
|
// <div key='extra-content' className='column-header__collapsible__extra'>
|
||||||
|
// {children}
|
||||||
|
// </div>
|
||||||
|
// }
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,123 +0,0 @@
|
|||||||
import { Fragment } from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { injectIntl, defineMessages } from 'react-intl';
|
|
||||||
import Icon from '../icon';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
|
||||||
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
|
||||||
});
|
|
||||||
|
|
||||||
export default @injectIntl
|
|
||||||
class ColumnHeader extends PureComponent {
|
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
title: PropTypes.node,
|
|
||||||
icon: PropTypes.string,
|
|
||||||
active: PropTypes.bool,
|
|
||||||
children: PropTypes.node,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
collapsed: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
historyBack = () => {
|
|
||||||
if (window.history && window.history.length === 1) {
|
|
||||||
this.context.router.history.push('/home'); // homehack
|
|
||||||
} else {
|
|
||||||
this.context.router.history.goBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleToggleClick = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
this.setState({
|
|
||||||
collapsed: !this.state.collapsed,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleBackClick = () => {
|
|
||||||
this.historyBack();
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { title, icon, active, children, intl: { formatMessage } } = this.props;
|
|
||||||
const { collapsed } = this.state;
|
|
||||||
|
|
||||||
const wrapperClassName = classNames('column-header__wrapper', {
|
|
||||||
'column-header__wrapper--active': active,
|
|
||||||
});
|
|
||||||
|
|
||||||
const buttonClassName = classNames('column-header', {
|
|
||||||
'column-header--active': active,
|
|
||||||
});
|
|
||||||
|
|
||||||
const btnTitle = formatMessage(collapsed ? messages.show : messages.hide);
|
|
||||||
const hasTitle = icon && title;
|
|
||||||
const hasChildren = !!children;
|
|
||||||
|
|
||||||
if (!hasChildren && !hasTitle) {
|
|
||||||
return null;
|
|
||||||
} else if (!hasChildren && hasTitle) {
|
|
||||||
return (
|
|
||||||
<div className={wrapperClassName}>
|
|
||||||
<h1 className={buttonClassName}>
|
|
||||||
<Icon id={icon} fixedWidth className='column-header__icon' />
|
|
||||||
{title}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const collapsibleClassName = classNames('column-header__collapsible', {
|
|
||||||
'column-header__collapsible--collapsed': collapsed,
|
|
||||||
});
|
|
||||||
|
|
||||||
const collapsibleButtonClassName = classNames('column-header__button', {
|
|
||||||
'column-header__button--active': !collapsed,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={wrapperClassName}>
|
|
||||||
<h1 className={buttonClassName}>
|
|
||||||
{
|
|
||||||
hasTitle && (
|
|
||||||
<Fragment>
|
|
||||||
<Icon id={icon} fixedWidth className='column-header__icon' />
|
|
||||||
{title}
|
|
||||||
</Fragment>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
<button
|
|
||||||
className={collapsibleButtonClassName}
|
|
||||||
title={btnTitle}
|
|
||||||
aria-label={btnTitle}
|
|
||||||
aria-pressed={!collapsed}
|
|
||||||
onClick={this.handleToggleClick}
|
|
||||||
>
|
|
||||||
<Icon id='sliders' />
|
|
||||||
</button>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<div className={collapsibleClassName} tabIndex={collapsed ? -1 : null}>
|
|
||||||
<div className='column-header__collapsible-inner'>
|
|
||||||
{
|
|
||||||
!collapsed &&
|
|
||||||
<div key='extra-content' className='column-header__collapsible__extra'>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,145 +0,0 @@
|
|||||||
.column-header {
|
|
||||||
display: flex;
|
|
||||||
font-size: 16px;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
outline: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
background: $gab-background-container;
|
|
||||||
|
|
||||||
body.theme-gabsocial-light & {
|
|
||||||
background: $gab-background-container-light;
|
|
||||||
color: $gab-default-text-light;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--active {
|
|
||||||
box-shadow: 0 1px 0 rgba($highlight-text-color, 0.3);
|
|
||||||
|
|
||||||
.column-header__icon {
|
|
||||||
color: $highlight-text-color;
|
|
||||||
text-shadow: 0 0 10px rgba($highlight-text-color, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__wrapper {
|
|
||||||
position: relative;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&--active {
|
|
||||||
&::before {
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 1;
|
|
||||||
background: radial-gradient(ellipse, rgba($ui-highlight-color, 0.23) 0%, rgba($ui-highlight-color, 0) 60%);
|
|
||||||
|
|
||||||
@include pseudo;
|
|
||||||
@include size(60%, 28px);
|
|
||||||
@include abs-position(35px, 0, auto, 0, false);
|
|
||||||
@include margin-center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__icon {
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__expansion {
|
|
||||||
overflow-x: scroll;
|
|
||||||
overflow-y: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
max-height: 0px;
|
|
||||||
|
|
||||||
&--open {
|
|
||||||
max-height: 55px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__button {
|
|
||||||
margin-left: auto;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 0;
|
|
||||||
padding: 0 15px;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #fff;
|
|
||||||
background: $gab-background-container;
|
|
||||||
|
|
||||||
body.theme-gabsocial-light & {
|
|
||||||
color: $gab-default-text-light;
|
|
||||||
background: $gab-background-container-light;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: lighten($darker-text-color, 7%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&--active {
|
|
||||||
color: $primary-text-color;
|
|
||||||
background: lighten($ui-base-color, 8%);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $primary-text-color;
|
|
||||||
background: lighten($ui-base-color, 8%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__collapsible-inner {
|
|
||||||
background: #3f3f3f;
|
|
||||||
padding: 15px;
|
|
||||||
|
|
||||||
body.theme-gabsocial-light & {
|
|
||||||
background: #e6e6e6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__collapsible {
|
|
||||||
max-height: 70vh;
|
|
||||||
overflow: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
color: $darker-text-color;
|
|
||||||
transition: max-height 150ms linear;
|
|
||||||
|
|
||||||
&--collapsed {
|
|
||||||
max-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
height: 0;
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
border-top: 1px solid lighten($ui-base-color, 12%);
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.column-header-btn {
|
|
||||||
padding: 15px;
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
&--sub {
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 6px s10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--grouped {
|
|
||||||
margin: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--active {
|
|
||||||
color: $primary-text-color;
|
|
||||||
border-radius: 10px;
|
|
||||||
background-color: rgba($highlight-text-color, .1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,168 +0,0 @@
|
|||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { injectIntl, defineMessages } from 'react-intl';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
import { fetchLists } from '../../actions/lists';
|
|
||||||
import Icon from '../icon';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
|
||||||
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
|
||||||
homeTitle: { id: 'home_column_header.home', defaultMessage: 'Home' },
|
|
||||||
allTitle: { id: 'home_column_header.all', defaultMessage: 'All' },
|
|
||||||
listTitle: { id: 'home_column.lists', defaultMessage: 'Lists' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const getOrderedLists = createSelector([state => state.get('lists')], lists => {
|
|
||||||
if (!lists) {
|
|
||||||
return lists;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lists.toList().filter(item => !!item).sort((a, b) => a.get('title').localeCompare(b.get('title')));
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
return {
|
|
||||||
lists: getOrderedLists(state),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
|
||||||
@injectIntl
|
|
||||||
class HomeColumnHeader extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
dispatch: PropTypes.func.isRequired,
|
|
||||||
active: PropTypes.bool,
|
|
||||||
children: PropTypes.node,
|
|
||||||
activeItem: PropTypes.string,
|
|
||||||
activeSubItem: PropTypes.string,
|
|
||||||
lists: ImmutablePropTypes.list,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
collapsed: true,
|
|
||||||
listsExpanded: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.props.dispatch(fetchLists());
|
|
||||||
}
|
|
||||||
|
|
||||||
handleToggleClick = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
this.setState({ collapsed: !this.state.collapsed });
|
|
||||||
}
|
|
||||||
|
|
||||||
expandLists = () => {
|
|
||||||
this.setState({ listsExpanded: !this.state.listsExpanded });
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { active, children, intl: { formatMessage }, activeItem, activeSubItem, lists } = this.props;
|
|
||||||
const { collapsed, listsExpanded } = this.state;
|
|
||||||
|
|
||||||
const wrapperClassName = classNames('column-header__wrapper', {
|
|
||||||
'column-header__wrapper--active': active,
|
|
||||||
});
|
|
||||||
|
|
||||||
const buttonClassName = classNames('column-header', {
|
|
||||||
'column-header--active': active,
|
|
||||||
});
|
|
||||||
|
|
||||||
const collapsibleClassName = classNames('column-header__collapsible', {
|
|
||||||
'column-header__collapsible--collapsed': collapsed,
|
|
||||||
});
|
|
||||||
|
|
||||||
const collapsibleButtonClassName = classNames('column-header__button', {
|
|
||||||
'column-header__button--active': !collapsed,
|
|
||||||
});
|
|
||||||
|
|
||||||
const expansionClassName = classNames('column-header column-header__expansion', {
|
|
||||||
'column-header__expansion--open': listsExpanded,
|
|
||||||
});
|
|
||||||
|
|
||||||
const btnTitle = formatMessage(collapsed ? messages.show : messages.hide);
|
|
||||||
|
|
||||||
let expandedContent = null;
|
|
||||||
if ((listsExpanded || activeItem === 'lists') && lists) {
|
|
||||||
expandedContent = lists.map((list) => {
|
|
||||||
const listId = list.get('id');
|
|
||||||
const linkUrl = `/list/${listId}`;
|
|
||||||
const classes = classNames('column-header-btn column-header-btn--sub column-header-btn--grouped', {
|
|
||||||
'column-header-btn--active': listId === activeSubItem,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link key={listId} to={linkUrl} className={classes}>
|
|
||||||
{list.get('title')}
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={wrapperClassName}>
|
|
||||||
<h1 className={buttonClassName}>
|
|
||||||
<Link to='/home' className={classNames('column-header-btn column-header-btn--grouped', { 'column-header-btn--active': 'home' === activeItem })}>
|
|
||||||
<Icon id='home' fixedWidth className='column-header__icon' />
|
|
||||||
{formatMessage(messages.homeTitle)}
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Link to='/timeline/all' className={classNames('column-header-btn column-header-btn--grouped', { 'column-header-btn--active': 'all' === activeItem })}>
|
|
||||||
<Icon id='globe' fixedWidth className='column-header__icon' />
|
|
||||||
{formatMessage(messages.allTitle)}
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
{ lists.size > 0 &&
|
|
||||||
<a onClick={this.expandLists} className={classNames('column-header-btn column-header-btn--grouped', { 'column-header-btn--active': 'lists' === activeItem })}>
|
|
||||||
<Icon id='list' fixedWidth className='column-header__icon' />
|
|
||||||
{formatMessage(messages.listTitle)}
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
{ lists.size == 0 &&
|
|
||||||
<Link to='/lists' className='column-header-btn column-header-btn--grouped'>
|
|
||||||
<Icon id='list' fixedWidth className='column-header__icon' />
|
|
||||||
{formatMessage(messages.listTitle)}
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className='column-header__buttons'>
|
|
||||||
<button
|
|
||||||
className={collapsibleButtonClassName}
|
|
||||||
title={btnTitle}
|
|
||||||
aria-label={btnTitle}
|
|
||||||
aria-pressed={collapsed ? 'false' : 'true'}
|
|
||||||
onClick={this.handleToggleClick}
|
|
||||||
>
|
|
||||||
<Icon id='sliders' />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<h1 className={expansionClassName}>
|
|
||||||
{expandedContent}
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<div className={collapsibleClassName} tabIndex={collapsed ? -1 : null}>
|
|
||||||
<div className='column-header__collapsible-inner'>
|
|
||||||
{
|
|
||||||
!collapsed &&
|
|
||||||
<div key='extra-content' className='column-header__collapsible__extra'>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import ColumnHeader from './column_header';
|
|
||||||
import HomeColumnHeader from './home_column_header';
|
|
||||||
|
|
||||||
export {
|
|
||||||
ColumnHeader,
|
|
||||||
HomeColumnHeader,
|
|
||||||
}
|
|
43
app/javascript/gabsocial/components/column_indicator.js
Normal file
43
app/javascript/gabsocial/components/column_indicator.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import Icon from './icon'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
loading: { id: 'loading_indicator.label', defaultMessage: 'Loading..' },
|
||||||
|
missing: { id: 'missing_indicator.sublabel', defaultMessage: 'This resource could not be found.' },
|
||||||
|
})
|
||||||
|
|
||||||
|
export default @injectIntl
|
||||||
|
class ColumnIndicator extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
type: PropTypes.oneOf([
|
||||||
|
'loading',
|
||||||
|
'missing',
|
||||||
|
'error',
|
||||||
|
]),
|
||||||
|
message: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.object,
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { type, message, intl } = this.props
|
||||||
|
|
||||||
|
const title = type !== 'error' ? intl.formatMessage(messages[type]) : message
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[styles.default, styles.width100PC, styles.justifyContentCenter, styles.alignItemsCenter, styles.paddingVertical15PX].join(' ')}>
|
||||||
|
<Icon id={type} width='52px' height='52px' />
|
||||||
|
{
|
||||||
|
type !== 'loading' &&
|
||||||
|
<span className={[styles.default, styles.marginTop10PX, styles.text, styles.displayFlex, styles.colorBrand, styles.fontWeightNormal, styles.fontSize14PX].join(' ')}>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,40 +0,0 @@
|
|||||||
import { defineMessages, injectIntl } from 'react-intl';
|
|
||||||
import Column from '../column';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
loading: { id: 'loading_indicator.label', defaultMessage: 'Loading...' },
|
|
||||||
missing: { id: 'missing_indicator.sublabel', defaultMessage: 'This resource could not be found.' },
|
|
||||||
});
|
|
||||||
|
|
||||||
export default @injectIntl
|
|
||||||
class ColumnIndicator extends PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
type: PropTypes.oneOf([
|
|
||||||
'loading',
|
|
||||||
'missing',
|
|
||||||
'error',
|
|
||||||
]),
|
|
||||||
message: PropTypes.oneOfType([
|
|
||||||
PropTypes.string,
|
|
||||||
PropTypes.object,
|
|
||||||
]),
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { type, message, intl } = this.props;
|
|
||||||
|
|
||||||
const title = type !== 'error' ? intl.formatMessage(messages[type]) : message;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Column>
|
|
||||||
<div className={`column-indicator column-indicator--${type}`}>
|
|
||||||
<div className='column-indicator__figure' />
|
|
||||||
<span className='column-indicator__title'>{title}</span>
|
|
||||||
</div>
|
|
||||||
</Column>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
@ -1,93 +0,0 @@
|
|||||||
.column-indicator {
|
|
||||||
overflow: visible;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
|
|
||||||
@include abs-position(50%, auto, auto, 50%);
|
|
||||||
|
|
||||||
&--loading & {
|
|
||||||
&__figure {
|
|
||||||
border: 6px solid lighten($ui-base-color, 26%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--missing & {
|
|
||||||
&__figure {
|
|
||||||
&:before {
|
|
||||||
@include pseudo('!');
|
|
||||||
@include text-sizing(40px, 600, 1, center);
|
|
||||||
@include abs-position(0, 0, 0, 0, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__figure {
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
@include circle(42px);
|
|
||||||
@include abs-position(50%, auto, auto, 50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
display: block;
|
|
||||||
float: left;
|
|
||||||
margin-left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
margin: 82px 0 0 50%;
|
|
||||||
white-space: nowrap;
|
|
||||||
color: $dark-text-color;
|
|
||||||
|
|
||||||
@include text-sizing(14px, 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-reduce-motion .column-indicator--loading span {
|
|
||||||
animation: loader-label 1.15s infinite cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-reduce-motion .column-indicator--loading .column-indicator__figure {
|
|
||||||
animation: loader-figure 1.15s infinite cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes loader-label {
|
|
||||||
0% {
|
|
||||||
opacity: 0.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
30% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 0.25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes loader-figure {
|
|
||||||
0% {
|
|
||||||
background-color: lighten($ui-base-color, 26%);
|
|
||||||
|
|
||||||
@include size(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
29% {
|
|
||||||
background-color: lighten($ui-base-color, 26%);
|
|
||||||
}
|
|
||||||
|
|
||||||
30% {
|
|
||||||
background-color: transparent;
|
|
||||||
border-width: 21px;
|
|
||||||
opacity: 1;
|
|
||||||
|
|
||||||
@include size(42px);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
border-width: 0;
|
|
||||||
opacity: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
@include size(42px);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export { default } from './column_indicator';
|
|
@ -105,32 +105,39 @@ class Header extends ImmutablePureComponent {
|
|||||||
const menuItems = [
|
const menuItems = [
|
||||||
{
|
{
|
||||||
title: 'Home',
|
title: 'Home',
|
||||||
icon: <Icon id='home' />,
|
icon: 'home',
|
||||||
to: '/',
|
to: '/',
|
||||||
|
count: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Notifications',
|
title: 'Notifications',
|
||||||
icon: <Icon id='notifications' />,
|
icon: 'notifications',
|
||||||
to: '/notifications',
|
to: '/notifications',
|
||||||
|
count: 40,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Groups',
|
title: 'Groups',
|
||||||
icon: <Icon id='groups' />,
|
icon: 'group',
|
||||||
to: '/groups',
|
to: '/groups',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Lists',
|
title: 'Lists',
|
||||||
icon: <Icon id='lists' />,
|
icon: 'lists',
|
||||||
to: '/lists',
|
to: '/lists',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Chat',
|
title: 'Chat',
|
||||||
icon: <Icon id='chat' />,
|
icon: 'chat',
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Profile',
|
title: 'Profile',
|
||||||
icon: <Icon id='profile' />,
|
icon: 'profile',
|
||||||
|
to: '/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'More',
|
||||||
|
icon: 'plus',
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -138,70 +145,88 @@ class Header extends ImmutablePureComponent {
|
|||||||
const shortcutItems = [
|
const shortcutItems = [
|
||||||
{
|
{
|
||||||
title: 'Meme Group',
|
title: 'Meme Group',
|
||||||
icon: <Icon id='group' />,
|
icon: 'group',
|
||||||
to: '/',
|
to: '/',
|
||||||
|
count: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Andrew',
|
title: 'Andrew',
|
||||||
icon: <Icon id='user' />,
|
icon: 'user',
|
||||||
to: '/',
|
to: '/',
|
||||||
|
count: 3,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const exploreItems = [
|
const exploreItems = [
|
||||||
{
|
{
|
||||||
title: 'Trends',
|
title: 'Trends',
|
||||||
icon: <Icon id='trends' />,
|
icon: 'trends',
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Dissenter',
|
title: 'Dissenter',
|
||||||
icon: <Icon id='dissenter' />,
|
icon: 'dissenter',
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Apps',
|
title: 'Apps',
|
||||||
icon: <Icon id='apps' />,
|
icon: 'apps',
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Shop',
|
title: 'Shop',
|
||||||
icon: <Icon id='shop' />,
|
icon: 'shop',
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
|
const titleClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
text: 1,
|
||||||
|
colorSubtle: 1,
|
||||||
|
displayBlock: 1,
|
||||||
|
fontSize13PX: 1,
|
||||||
|
paddingVertical5PX: 1,
|
||||||
|
marginTop10PX: 1,
|
||||||
|
paddingHorizontal10PX: 1,
|
||||||
|
fontWeightBold: 1,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header role='banner' className={[styles.default, styles.flexGrow1, styles.z3, styles.alignItemsEnd].join(' ')}>
|
<header role='banner' className={[styles.default, styles.flexGrow1, styles.z3, styles.alignItemsEnd].join(' ')}>
|
||||||
<div className={[styles.default, styles.width250PX].join(' ')}>
|
<div className={[styles.default, styles.width250PX].join(' ')}>
|
||||||
<div className={[styles.default, styles.positionFixed, styles.top0, styles.height100PC].join(' ')}>
|
<div className={[styles.default, styles.positionFixed, styles.top0, styles.height100PC].join(' ')}>
|
||||||
<div className={[styles.default, styles.height100PC, styles.width250PX, styles.paddingHorizontal20PX, styles.marginVertical10PX].join(' ')}>
|
<div className={[styles.default, styles.height100PC, styles.width250PX, styles.paddingHorizontal15PX, styles.marginVertical10PX].join(' ')}>
|
||||||
<h1 className={[styles.default].join(' ')}>
|
<h1 className={[styles.default].join(' ')}>
|
||||||
<NavLink to='/' aria-label='Gab' className={[styles.default, styles.noSelect, styles.noUnderline, styles.height50PX, styles.justifyContentCenter, styles.cursorPointer, styles.paddingHorizontal10PX].join(' ')}>
|
<NavLink to='/' aria-label='Gab' className={[styles.default, styles.noSelect, styles.noUnderline, styles.height50PX, styles.justifyContentCenter, styles.cursorPointer, styles.paddingHorizontal10PX].join(' ')}>
|
||||||
<GabLogo />
|
<GabLogo />
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</h1>
|
</h1>
|
||||||
<nav aria-label='Primary' role='navigation' className={[styles.default, styles.width100PC, styles.marginBottom15PX].join(' ')}>
|
<nav aria-label='Primary' role='navigation' className={[styles.default, styles.width100PC, styles.marginBottom15PX].join(' ')}>
|
||||||
<span className={[styles.default, styles.text, styles.colorSubtle, styles.displayBlock, styles.fontSize13PX, styles.paddingVertical5PX, styles.marginTop10PX, styles.paddingHorizontal10PX, styles.fontWeight500].join(' ')}>Menu</span>
|
<span className={titleClasses}>Menu</span>
|
||||||
{
|
{
|
||||||
menuItems.map((menuItem, i) => (
|
menuItems.map((menuItem, i) => (
|
||||||
<HeaderMenuItem {...menuItem} key={`header-item-menu-${i}`} />
|
<HeaderMenuItem {...menuItem} key={`header-item-menu-${i}`} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
<span className={[styles.default, styles.text, styles.colorSubtle, styles.displayBlock, styles.fontSize13PX, styles.paddingVertical5PX, styles.marginTop10PX, styles.paddingHorizontal10PX, styles.fontWeight500].join(' ')}>Shortcuts</span>
|
<span className={titleClasses}>Shortcuts</span>
|
||||||
{
|
{
|
||||||
shortcutItems.map((shortcutItem, i) => (
|
shortcutItems.map((shortcutItem, i) => (
|
||||||
<HeaderMenuItem {...shortcutItem} key={`header-item-shortcut-${i}`} />
|
<HeaderMenuItem {...shortcutItem} key={`header-item-shortcut-${i}`} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
<span className={[styles.default, styles.text, styles.colorSubtle, styles.displayBlock, styles.fontSize13PX, styles.paddingVertical5PX, styles.marginTop10PX, styles.paddingHorizontal10PX, styles.fontWeight500].join(' ')}>Explore</span>
|
<span className={titleClasses}>Explore</span>
|
||||||
{
|
{
|
||||||
exploreItems.map((exploreItem, i) => (
|
exploreItems.map((exploreItem, i) => (
|
||||||
<HeaderMenuItem {...exploreItem} key={`header-item-explore-${i}`} />
|
<HeaderMenuItem {...exploreItem} key={`header-item-explore-${i}`} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</nav>
|
</nav>
|
||||||
<Button className={[styles.paddingVertical15PX, styles.fontSize15PX, styles.fontWeightBold].join(' ')}>Gab</Button>
|
<Button block className={[styles.paddingVertical15PX, styles.fontSize15PX, styles.fontWeightBold].join(' ')}>
|
||||||
|
Gab
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -215,7 +240,7 @@ class HeaderMenuItem extends PureComponent {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
to: PropTypes.string,
|
to: PropTypes.string,
|
||||||
active: PropTypes.bool,
|
active: PropTypes.bool,
|
||||||
icon: PropTypes.node,
|
icon: PropTypes.string,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,9 +272,10 @@ class HeaderMenuItem extends PureComponent {
|
|||||||
paddingVertical5PX: 1,
|
paddingVertical5PX: 1,
|
||||||
paddingHorizontal10PX: 1,
|
paddingHorizontal10PX: 1,
|
||||||
alignItemsCenter: 1,
|
alignItemsCenter: 1,
|
||||||
|
radiusSmall: 1,
|
||||||
// border1PX: shouldShowActive,
|
// border1PX: shouldShowActive,
|
||||||
// borderColorSubtle: shouldShowActive,
|
// borderColorSubtle: shouldShowActive,
|
||||||
backgroundWhite: shouldShowActive,
|
backgroundColorBrandLightOpaque: shouldShowActive,
|
||||||
})
|
})
|
||||||
|
|
||||||
const textClasses = cx({
|
const textClasses = cx({
|
||||||
@ -257,6 +283,7 @@ class HeaderMenuItem extends PureComponent {
|
|||||||
fontWeightNormal: 1,
|
fontWeightNormal: 1,
|
||||||
fontSize15PX: 1,
|
fontSize15PX: 1,
|
||||||
text: 1,
|
text: 1,
|
||||||
|
fontWeight500: shouldShowActive,
|
||||||
colorBrand: shouldShowActive,
|
colorBrand: shouldShowActive,
|
||||||
colorBlack: !hovering && !active,
|
colorBlack: !hovering && !active,
|
||||||
})
|
})
|
||||||
@ -275,7 +302,7 @@ class HeaderMenuItem extends PureComponent {
|
|||||||
>
|
>
|
||||||
<div className={containerClasses}>
|
<div className={containerClasses}>
|
||||||
<div className={[styles.default]}>
|
<div className={[styles.default]}>
|
||||||
<Icon className={iconClasses} width='16px' height='16px' />
|
<Icon id={icon} className={iconClasses} width='15px' height='15px' />
|
||||||
</div>
|
</div>
|
||||||
<div className={[styles.default, styles.paddingHorizontal10PX, styles.textOverflowEllipsis, styles.overflowWrapBreakWord, styles.displayInline].join(' ')}>
|
<div className={[styles.default, styles.paddingHorizontal10PX, styles.textOverflowEllipsis, styles.overflowWrapBreakWord, styles.displayInline].join(' ')}>
|
||||||
<span className={textClasses}>{title}</span>
|
<span className={textClasses}>{title}</span>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import BackIcon from './svgs/back_icon'
|
||||||
|
import CalendarIcon from './svgs/calendar_icon'
|
||||||
import CloseIcon from './svgs/close_icon'
|
import CloseIcon from './svgs/close_icon'
|
||||||
import CommentIcon from './svgs/comment_icon'
|
import CommentIcon from './svgs/comment_icon'
|
||||||
import EllipsisIcon from './svgs/ellipsis_icon'
|
import EllipsisIcon from './svgs/ellipsis_icon'
|
||||||
@ -5,11 +7,15 @@ import GlobeIcon from './svgs/globe_icon'
|
|||||||
import GroupIcon from './svgs/group_icon'
|
import GroupIcon from './svgs/group_icon'
|
||||||
import HomeIcon from './svgs/home_icon'
|
import HomeIcon from './svgs/home_icon'
|
||||||
import LikeIcon from './svgs/like_icon'
|
import LikeIcon from './svgs/like_icon'
|
||||||
|
import LoadingIcon from './svgs/loading_icon'
|
||||||
|
import MediaIcon from './svgs/media_icon'
|
||||||
import NotificationsIcon from './svgs/notifications_icon'
|
import NotificationsIcon from './svgs/notifications_icon'
|
||||||
|
import PollIcon from './svgs/poll_icon'
|
||||||
import RepostIcon from './svgs/repost_icon'
|
import RepostIcon from './svgs/repost_icon'
|
||||||
import SearchIcon from './svgs/search_icon'
|
import SearchIcon from './svgs/search_icon'
|
||||||
import ShareIcon from './svgs/share_icon'
|
import ShareIcon from './svgs/share_icon'
|
||||||
import VerifiedIcon from './svgs/verified_icon'
|
import VerifiedIcon from './svgs/verified_icon'
|
||||||
|
import WarningIcon from './svgs/warning_icon'
|
||||||
|
|
||||||
export default class Icon extends PureComponent {
|
export default class Icon extends PureComponent {
|
||||||
|
|
||||||
@ -23,9 +29,11 @@ export default class Icon extends PureComponent {
|
|||||||
render() {
|
render() {
|
||||||
const { id, ...options } = this.props
|
const { id, ...options } = this.props
|
||||||
|
|
||||||
console.log("id:", id)
|
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
case 'back':
|
||||||
|
return <BackIcon {...options} />
|
||||||
|
case 'calendar':
|
||||||
|
return <CalendarIcon {...options} />
|
||||||
case 'close':
|
case 'close':
|
||||||
return <CloseIcon {...options} />
|
return <CloseIcon {...options} />
|
||||||
case 'comment':
|
case 'comment':
|
||||||
@ -40,17 +48,24 @@ export default class Icon extends PureComponent {
|
|||||||
return <HomeIcon {...options} />
|
return <HomeIcon {...options} />
|
||||||
case 'like':
|
case 'like':
|
||||||
return <LikeIcon {...options} />
|
return <LikeIcon {...options} />
|
||||||
|
case 'loading':
|
||||||
|
return <LoadingIcon {...options} />
|
||||||
|
case 'media':
|
||||||
|
return <MediaIcon {...options} />
|
||||||
case 'notifications':
|
case 'notifications':
|
||||||
return <NotificationsIcon {...options} />
|
return <NotificationsIcon {...options} />
|
||||||
|
case 'poll':
|
||||||
|
return <PollIcon {...options} />
|
||||||
case 'repost':
|
case 'repost':
|
||||||
return <RepostIcon {...options} />
|
return <RepostIcon {...options} />
|
||||||
case 'search':
|
case 'search':
|
||||||
return <SearchIcon {...options} />
|
return <SearchIcon {...options} />
|
||||||
case 'share':
|
case 'share':
|
||||||
return <ShareIcon {...options} />
|
return <ShareIcon {...options} />
|
||||||
case 'verified':
|
case 'verified':
|
||||||
return <VerifiedIcon {...options} />
|
return <VerifiedIcon {...options} />
|
||||||
|
case 'warning':
|
||||||
|
return <WarningIcon {...options} />
|
||||||
default:
|
default:
|
||||||
return <NotificationsIcon {...options} />
|
return <NotificationsIcon {...options} />
|
||||||
}
|
}
|
||||||
|
26
app/javascript/gabsocial/components/icon/svgs/back_icon.js
Normal file
26
app/javascript/gabsocial/components/icon/svgs/back_icon.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const BackIcon = ({
|
||||||
|
className = '',
|
||||||
|
width = '16px',
|
||||||
|
height = '16px',
|
||||||
|
viewBox = '0 0 60 60',
|
||||||
|
title = 'Back',
|
||||||
|
}) => (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
version='1.1'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
x='0px'
|
||||||
|
y='0px'
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
viewBox={viewBox}
|
||||||
|
xmlSpace='preserve'
|
||||||
|
aria-label={title}
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path d="M 19.570312 9.542969 C 20.417969 8.695312 21.75 8.695312 22.59375 9.542969 C 23.410156 10.359375 23.410156 11.71875 22.59375 12.535156 L 7.265625 27.867188 L 57.851562 27.867188 C 59.03125 27.867188 60 28.804688 60 29.984375 C 60 31.164062 59.03125 32.128906 57.851562 32.128906 L 7.265625 32.128906 L 22.59375 47.433594 C 23.410156 48.277344 23.410156 49.640625 22.59375 50.457031 C 21.75 51.300781 20.417969 51.300781 19.570312 50.457031 L 0.613281 31.496094 C -0.207031 30.679688 -0.207031 29.316406 0.613281 28.503906 Z M 19.570312 9.542969" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default BackIcon
|
@ -0,0 +1,26 @@
|
|||||||
|
const CalendarIcon = ({
|
||||||
|
className = '',
|
||||||
|
width = '26px',
|
||||||
|
height = '26px',
|
||||||
|
viewBox = '0 0 48 48',
|
||||||
|
title = 'Calendar',
|
||||||
|
}) => (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
version='1.1'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
x='0px'
|
||||||
|
y='0px'
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
viewBox={viewBox}
|
||||||
|
xmlSpace='preserve'
|
||||||
|
aria-label={title}
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path d="M 45.234375 7.871094 C 44.558594 7.191406 43.753906 6.851562 42.828125 6.851562 L 39.402344 6.851562 L 39.402344 4.28125 C 39.402344 3.105469 38.980469 2.097656 38.144531 1.257812 C 37.304688 0.417969 36.296875 0 35.117188 0 L 33.40625 0 C 32.226562 0 31.21875 0.417969 30.378906 1.257812 C 29.542969 2.097656 29.121094 3.105469 29.121094 4.28125 L 29.121094 6.851562 L 18.84375 6.851562 L 18.84375 4.28125 C 18.84375 3.105469 18.425781 2.097656 17.585938 1.257812 C 16.746094 0.417969 15.738281 0 14.5625 0 L 12.847656 0 C 11.671875 0 10.664062 0.417969 9.824219 1.257812 C 8.984375 2.097656 8.566406 3.105469 8.566406 4.28125 L 8.566406 6.851562 L 5.140625 6.851562 C 4.210938 6.851562 3.410156 7.191406 2.730469 7.871094 C 2.050781 8.546875 1.714844 9.351562 1.714844 10.277344 L 1.714844 44.539062 C 1.714844 45.46875 2.050781 46.269531 2.730469 46.949219 C 3.410156 47.625 4.210938 47.964844 5.140625 47.964844 L 42.824219 47.964844 C 43.753906 47.964844 44.558594 47.625 45.234375 46.949219 C 45.914062 46.269531 46.253906 45.46875 46.253906 44.539062 L 46.253906 10.277344 C 46.253906 9.351562 45.914062 8.546875 45.234375 7.871094 Z M 12.847656 44.539062 L 5.140625 44.539062 L 5.140625 36.832031 L 12.847656 36.832031 Z M 12.847656 35.117188 L 5.140625 35.117188 L 5.140625 26.554688 L 12.847656 26.554688 Z M 12.847656 24.839844 L 5.140625 24.839844 L 5.140625 17.128906 L 12.847656 17.128906 Z M 12.246094 12.59375 C 12.078125 12.425781 11.992188 12.222656 11.992188 11.992188 L 11.992188 4.28125 C 11.992188 4.050781 12.078125 3.851562 12.246094 3.679688 C 12.414062 3.511719 12.617188 3.425781 12.847656 3.425781 L 14.5625 3.425781 C 14.792969 3.425781 14.996094 3.511719 15.164062 3.679688 C 15.332031 3.851562 15.417969 4.050781 15.417969 4.28125 L 15.417969 11.992188 C 15.417969 12.222656 15.332031 12.425781 15.164062 12.59375 C 14.992188 12.761719 14.792969 12.847656 14.5625 12.847656 L 12.847656 12.847656 C 12.617188 12.847656 12.414062 12.761719 12.246094 12.59375 Z M 23.125 44.539062 L 14.5625 44.539062 L 14.5625 36.832031 L 23.125 36.832031 Z M 23.125 35.117188 L 14.5625 35.117188 L 14.5625 26.554688 L 23.125 26.554688 Z M 23.125 24.839844 L 14.5625 24.839844 L 14.5625 17.128906 L 23.125 17.128906 Z M 33.40625 44.539062 L 24.839844 44.539062 L 24.839844 36.832031 L 33.40625 36.832031 Z M 33.40625 35.117188 L 24.839844 35.117188 L 24.839844 26.554688 L 33.40625 26.554688 Z M 33.40625 24.839844 L 24.839844 24.839844 L 24.839844 17.128906 L 33.40625 17.128906 Z M 32.804688 12.59375 C 32.632812 12.425781 32.550781 12.222656 32.550781 11.992188 L 32.550781 4.28125 C 32.550781 4.050781 32.632812 3.851562 32.804688 3.679688 C 32.972656 3.511719 33.171875 3.425781 33.40625 3.425781 L 35.117188 3.425781 C 35.351562 3.425781 35.550781 3.511719 35.71875 3.679688 C 35.890625 3.851562 35.972656 4.050781 35.972656 4.28125 L 35.972656 11.992188 C 35.972656 12.222656 35.890625 12.425781 35.71875 12.59375 C 35.550781 12.761719 35.351562 12.847656 35.117188 12.847656 L 33.40625 12.847656 C 33.171875 12.847656 32.972656 12.761719 32.804688 12.59375 Z M 42.824219 44.539062 L 35.117188 44.539062 L 35.117188 36.832031 L 42.824219 36.832031 Z M 42.824219 35.117188 L 35.117188 35.117188 L 35.117188 26.554688 L 42.824219 26.554688 Z M 42.824219 24.839844 L 35.117188 24.839844 L 35.117188 17.128906 L 42.824219 17.128906 Z M 42.824219 24.839844" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default CalendarIcon
|
@ -18,7 +18,7 @@ const GlobeIcon = ({
|
|||||||
aria-label={title}
|
aria-label={title}
|
||||||
>
|
>
|
||||||
<g>
|
<g>
|
||||||
<circle fill='none' stroke='#616770' stroke-width='1px' cx='14' cy='14' r='13.5' />
|
<circle fill='none' stroke='#616770' strokeWidth='1px' cx='14' cy='14' r='13.5' />
|
||||||
<path fill='#616770' d='M 16 5 L 18 4 L 20 5 L 22 5 L 23 4 C 24 5 25 6 25 7 L 25 7 L 22 8 L 20 7 L 19 6 L 16 6 L 14 7 L 15 11 L 18 12 L 20 12 L 21 13 L 21 14 L 22 16 L 23 18 L 23 20 L 26.4 21 C 20 27 12 29 6 25 C 1 21 0 14 1 8 L 2 11 L 3 12 L 5 13 L 4 14 L 4 15 L 5 17 L 7 17 L 7 22 L 8 24 L 9 25 L 9 22 L 11 21 L 11 20 L 13 18 L 14 15 L 12 15 L 10 13 L 7 13 L 6 11 L 5 13 L 5 11 L 4 10 L 4 8 L 7 8 L 9 7 L 11 4 L 12 4 L 13 2 L 10 2 L 10 1 C 12 0 16 0 18 1 L 18 2 L 16 2 L 15 4 Z M 16 5' />
|
<path fill='#616770' d='M 16 5 L 18 4 L 20 5 L 22 5 L 23 4 C 24 5 25 6 25 7 L 25 7 L 22 8 L 20 7 L 19 6 L 16 6 L 14 7 L 15 11 L 18 12 L 20 12 L 21 13 L 21 14 L 22 16 L 23 18 L 23 20 L 26.4 21 C 20 27 12 29 6 25 C 1 21 0 14 1 8 L 2 11 L 3 12 L 5 13 L 4 14 L 4 15 L 5 17 L 7 17 L 7 22 L 8 24 L 9 25 L 9 22 L 11 21 L 11 20 L 13 18 L 14 15 L 12 15 L 10 13 L 7 13 L 6 11 L 5 13 L 5 11 L 4 10 L 4 8 L 7 8 L 9 7 L 11 4 L 12 4 L 13 2 L 10 2 L 10 1 C 12 0 16 0 18 1 L 18 2 L 16 2 L 15 4 Z M 16 5' />
|
||||||
{/*<path fill='#616770' d='M 14 27 C 21 28 28 21 28 14 C 28 6 21 0 14 0 C 8 0 3 3 1 8 L 0 8 L 1 8 C -1 15 1 24 8 26 C 10 27 12 28 14 27 Z M 24 21 L 24 20 L 24 18 C 24 18 24 18 24 18 L 22 14 L 22 13 C 22 12 22 12 22 12 L 20 11 C 20 11 20 11 20 11 L 18 12 L 15 10 L 15 8 L 16 7 L 18 7 L 19 8 C 19 8 19 8 19 8 L 22 8 C 22 8 22 8 23 8 L 25 7 C 27 12 27 17 24 21 Z M 23 4 L 22 5 L 20 4 L 18 4 C 18 4 18 4 18 4 L 16 4 L 16 4 L 16 3 L 18 3 C 18 3 18 3 18 3 L 20 2 C 21 2 22 3 23 4 Z M 8 1 L 10 2 C 10 2 10 2 10 2 L 12 3 L 12 3 L 11 4 C 10 4 10 4 10 4 L 9 6 L 7 7 L 4 8 C 3 8 3 8 3 8 L 3 10 C 3 10 3 10 3 10 L 4 11 L 4 12 L 2 10 L 2 8 C 3 5 5 3 8 1 Z M 7 17 L 5 16 L 4 15 L 4 14 L 6 12 L 7 13 C 7 13 7 14 7 14 L 10 14 L 11 16 C 11 16 11 16 12 16 L 13 16 L 13 17 L 11 19 C 11 19 11 19 11 20 L 11 21 L 9 22 C 9 22 9 22 9 22 L 9 24 L 8 24 L 7 22 L 7 17 C 7 17 7 17 7 17 Z M 1 10 L 1 11 C 1 11 1 11 2 11 L 4 13 L 3 13 C 3 13 3 13 3 14 L 3 15 C 3 15 3 15 3 15 L 4 17 C 4 17 4 17 5 17 L 7 18 L 7 22 C 7 22 7 22 7 22 L 7 24 C 8 25 8 25 8 25 L 9 25 C 9 25 9 25 9 25 C 10 25 10 25 10 25 L 10 23 L 11 21 C 12 21 12 21 12 21 L 12 20 L 13 18 C 13 18 13 18 13 18 L 14 15 C 14 15 14 15 14 15 C 14 15 14 15 14 15 L 12 15 L 11 13 C 11 13 10 13 10 13 L 7 13 L 6 11 C 6 11 6 11 6 11 C 6 11 6 11 6 11 L 5 11 L 5 11 C 5 11 5 10 5 10 L 4 10 L 4 9 L 7 8 C 7 8 7 8 7 8 L 10 7 C 10 7 10 7 10 7 L 11 5 L 12 4 C 12 4 12 4 13 4 L 13 2 C 13 2 13 2 13 2 C 13 2 13 2 13 2 L 10 1 L 9 1 C 12 0 16 0 18 1 L 18 2 L 16 2 C 16 2 15 2 15 2 L 14 4 C 14 4 14 4 15 5 C 15 5 15 5 15 5 L 16 5 C 16 5 16 5 16 5 L 18 5 L 19 5 C 19 5 19 5 19 5 L 22 6 C 22 6 22 6 22 5 L 23 5 C 24 5 24 6 25 7 L 22 7 L 20 7 L 19 6 C 19 6 19 6 19 6 L 16 6 C 16 6 16 6 16 6 L 14 7 C 14 7 14 7 14 8 L 14 11 C 14 11 15 11 15 11 L 18 13 C 18 13 18 13 18 13 L 20 12 L 21 13 L 21 14 C 21 15 21 15 21 15 L 23 18 L 23 20 C 23 20 23 20 23 20 L 24 21 C 20 27 11 28 6 24 C 1 21 0 15 1 10 Z M 1 10' /> */}
|
{/*<path fill='#616770' d='M 14 27 C 21 28 28 21 28 14 C 28 6 21 0 14 0 C 8 0 3 3 1 8 L 0 8 L 1 8 C -1 15 1 24 8 26 C 10 27 12 28 14 27 Z M 24 21 L 24 20 L 24 18 C 24 18 24 18 24 18 L 22 14 L 22 13 C 22 12 22 12 22 12 L 20 11 C 20 11 20 11 20 11 L 18 12 L 15 10 L 15 8 L 16 7 L 18 7 L 19 8 C 19 8 19 8 19 8 L 22 8 C 22 8 22 8 23 8 L 25 7 C 27 12 27 17 24 21 Z M 23 4 L 22 5 L 20 4 L 18 4 C 18 4 18 4 18 4 L 16 4 L 16 4 L 16 3 L 18 3 C 18 3 18 3 18 3 L 20 2 C 21 2 22 3 23 4 Z M 8 1 L 10 2 C 10 2 10 2 10 2 L 12 3 L 12 3 L 11 4 C 10 4 10 4 10 4 L 9 6 L 7 7 L 4 8 C 3 8 3 8 3 8 L 3 10 C 3 10 3 10 3 10 L 4 11 L 4 12 L 2 10 L 2 8 C 3 5 5 3 8 1 Z M 7 17 L 5 16 L 4 15 L 4 14 L 6 12 L 7 13 C 7 13 7 14 7 14 L 10 14 L 11 16 C 11 16 11 16 12 16 L 13 16 L 13 17 L 11 19 C 11 19 11 19 11 20 L 11 21 L 9 22 C 9 22 9 22 9 22 L 9 24 L 8 24 L 7 22 L 7 17 C 7 17 7 17 7 17 Z M 1 10 L 1 11 C 1 11 1 11 2 11 L 4 13 L 3 13 C 3 13 3 13 3 14 L 3 15 C 3 15 3 15 3 15 L 4 17 C 4 17 4 17 5 17 L 7 18 L 7 22 C 7 22 7 22 7 22 L 7 24 C 8 25 8 25 8 25 L 9 25 C 9 25 9 25 9 25 C 10 25 10 25 10 25 L 10 23 L 11 21 C 12 21 12 21 12 21 L 12 20 L 13 18 C 13 18 13 18 13 18 L 14 15 C 14 15 14 15 14 15 C 14 15 14 15 14 15 L 12 15 L 11 13 C 11 13 10 13 10 13 L 7 13 L 6 11 C 6 11 6 11 6 11 C 6 11 6 11 6 11 L 5 11 L 5 11 C 5 11 5 10 5 10 L 4 10 L 4 9 L 7 8 C 7 8 7 8 7 8 L 10 7 C 10 7 10 7 10 7 L 11 5 L 12 4 C 12 4 12 4 13 4 L 13 2 C 13 2 13 2 13 2 C 13 2 13 2 13 2 L 10 1 L 9 1 C 12 0 16 0 18 1 L 18 2 L 16 2 C 16 2 15 2 15 2 L 14 4 C 14 4 14 4 15 5 C 15 5 15 5 15 5 L 16 5 C 16 5 16 5 16 5 L 18 5 L 19 5 C 19 5 19 5 19 5 L 22 6 C 22 6 22 6 22 5 L 23 5 C 24 5 24 6 25 7 L 22 7 L 20 7 L 19 6 C 19 6 19 6 19 6 L 16 6 C 16 6 16 6 16 6 L 14 7 C 14 7 14 7 14 8 L 14 11 C 14 11 15 11 15 11 L 18 13 C 18 13 18 13 18 13 L 20 12 L 21 13 L 21 14 C 21 15 21 15 21 15 L 23 18 L 23 20 C 23 20 23 20 23 20 L 24 21 C 20 27 11 28 6 24 C 1 21 0 15 1 10 Z M 1 10' /> */}
|
||||||
</g>
|
</g>
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
const LoadingIcon = ({
|
||||||
|
className = '',
|
||||||
|
width = '24px',
|
||||||
|
height = '24px',
|
||||||
|
viewBox = '0 0 100 100',
|
||||||
|
}) => (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
style={{shapeRendering: 'auto'}}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
viewBox={viewBox}
|
||||||
|
preserveAspectRatio='xMidYMid'
|
||||||
|
>
|
||||||
|
<g transform='translate(82,50)'>
|
||||||
|
<g transform='rotate(0)'>
|
||||||
|
<circle cx='0' cy='0' r='6' fill='#30ce7d' fill-opacity='1' transform='scale(1.03405 1.03405)'>
|
||||||
|
<animateTransform attributeName='transform' type='scale' begin='-1.0294117647058822s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
|
||||||
|
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-1.0294117647058822s'></animate>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform='translate(72.62741699796952,72.62741699796952)'>
|
||||||
|
<g transform='rotate(45)'>
|
||||||
|
<circle cx='0' cy='0' r='6' fill='#30ce7d' fill-opacity='0.875' transform='scale(1.09655 1.09655)'>
|
||||||
|
<animateTransform attributeName='transform' type='scale' begin='-0.8823529411764705s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
|
||||||
|
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.8823529411764705s'></animate>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform='translate(50,82)'>
|
||||||
|
<g transform='rotate(90)'>
|
||||||
|
<circle cx='0' cy='0' r='6' fill='#30ce7d' fill-opacity='0.75' transform='scale(1.15905 1.15905)'>
|
||||||
|
<animateTransform attributeName='transform' type='scale' begin='-0.7352941176470588s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
|
||||||
|
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.7352941176470588s'></animate>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform='translate(27.37258300203048,72.62741699796952)'>
|
||||||
|
<g transform='rotate(135)'>
|
||||||
|
<circle cx='0' cy='0' r='6' fill='#30ce7d' fill-opacity='0.625' transform='scale(1.22155 1.22155)'>
|
||||||
|
<animateTransform attributeName='transform' type='scale' begin='-0.588235294117647s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
|
||||||
|
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.588235294117647s'></animate>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform='translate(18,50)'>
|
||||||
|
<g transform='rotate(180)'>
|
||||||
|
<circle cx='0' cy='0' r='6' fill='#30ce7d' fill-opacity='0.5' transform='scale(1.28405 1.28405)'>
|
||||||
|
<animateTransform attributeName='transform' type='scale' begin='-0.4411764705882352s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
|
||||||
|
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.4411764705882352s'></animate>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform='translate(27.372583002030474,27.37258300203048)'>
|
||||||
|
<g transform='rotate(225)'>
|
||||||
|
<circle cx='0' cy='0' r='6' fill='#30ce7d' fill-opacity='0.375' transform='scale(1.34655 1.34655)'>
|
||||||
|
<animateTransform attributeName='transform' type='scale' begin='-0.2941176470588235s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
|
||||||
|
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.2941176470588235s'></animate>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform='translate(50,18)'>
|
||||||
|
<g transform='rotate(270)'>
|
||||||
|
<circle cx='0' cy='0' r='6' fill='#30ce7d' fill-opacity='0.25' transform='scale(1.40905 1.40905)'>
|
||||||
|
<animateTransform attributeName='transform' type='scale' begin='-0.14705882352941174s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
|
||||||
|
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='-0.14705882352941174s'></animate>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform='translate(72.62741699796952,27.372583002030474)'>
|
||||||
|
<g transform='rotate(315)'>
|
||||||
|
<circle cx='0' cy='0' r='6' fill='#30ce7d' fill-opacity='0.125' transform='scale(1.47155 1.47155)'>
|
||||||
|
<animateTransform attributeName='transform' type='scale' begin='0s' values='1.5 1.5;1 1' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite'></animateTransform>
|
||||||
|
<animate attributeName='fill-opacity' keyTimes='0;1' dur='1.176470588235294s' repeatCount='indefinite' values='1;0' begin='0s'></animate>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default LoadingIcon
|
29
app/javascript/gabsocial/components/icon/svgs/media_icon.js
Normal file
29
app/javascript/gabsocial/components/icon/svgs/media_icon.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
const MediaIcon = ({
|
||||||
|
className = '',
|
||||||
|
width = '16px',
|
||||||
|
height = '16px',
|
||||||
|
viewBox = '0 0 48 48',
|
||||||
|
title = 'Media',
|
||||||
|
}) => (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
version='1.1'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
x='0px'
|
||||||
|
y='0px'
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
viewBox={viewBox}
|
||||||
|
xmlSpace='preserve'
|
||||||
|
aria-label={title}
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path d="M 24.867188 37.953125 C 23.472656 37.933594 22.125 37.429688 21.058594 36.535156 L 14.019531 30.332031 C 12.910156 29.296875 11.214844 29.214844 10.015625 30.140625 L 0.00390625 37.503906 L 0.00390625 42.28125 C -0.0664062 43.5625 0.914062 44.660156 2.195312 44.734375 C 2.261719 44.738281 2.328125 44.738281 2.394531 44.734375 L 37.847656 44.734375 C 39.269531 44.734375 40.691406 43.703125 40.691406 42.28125 L 40.691406 29.753906 L 27.96875 37.113281 C 27.03125 37.675781 25.957031 37.96875 24.867188 37.953125 Z M 24.867188 37.953125" />
|
||||||
|
<path d="M 27.191406 22.582031 C 27.191406 24.152344 25.921875 25.425781 24.351562 25.425781 C 22.78125 25.425781 21.507812 24.152344 21.507812 22.582031 C 21.507812 21.015625 22.78125 19.742188 24.351562 19.742188 C 25.921875 19.742188 27.191406 21.015625 27.191406 22.582031 Z M 27.191406 22.582031" />
|
||||||
|
<path d="M 47.40625 8.3125 C 46.996094 7.75 46.359375 7.394531 45.664062 7.34375 L 10.464844 3.273438 C 9.78125 3.214844 9.09375 3.398438 8.527344 3.789062 C 8.027344 4.226562 7.6875 4.816406 7.558594 5.46875 L 6.980469 10.507812 L 37.847656 10.507812 C 40.792969 10.574219 43.171875 12.925781 43.273438 15.867188 L 43.273438 38.664062 C 43.273438 38.535156 43.855469 38.40625 44.113281 38.148438 C 44.648438 37.726562 44.957031 37.085938 44.953125 36.40625 L 47.988281 10.183594 C 48.054688 9.507812 47.84375 8.832031 47.40625 8.3125 Z M 47.40625 8.3125" />
|
||||||
|
<path d="M 37.847656 13.089844 L 2.394531 13.089844 C 0.972656 13.089844 0.00390625 14.445312 0.00390625 15.867188 L 0.00390625 34.273438 L 8.527344 28.074219 C 10.691406 26.46875 13.6875 26.601562 15.695312 28.394531 L 22.800781 34.597656 C 23.871094 35.503906 25.402344 35.636719 26.609375 34.917969 L 40.691406 26.71875 L 40.691406 15.867188 C 40.59375 14.351562 39.367188 13.152344 37.847656 13.089844 Z M 24.351562 28.007812 C 21.355469 28.007812 18.925781 25.578125 18.925781 22.582031 C 18.925781 19.585938 21.355469 17.160156 24.351562 17.160156 C 27.347656 17.160156 29.777344 19.585938 29.777344 22.582031 C 29.777344 25.578125 27.347656 28.007812 24.351562 28.007812 Z M 24.351562 28.007812" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default MediaIcon
|
26
app/javascript/gabsocial/components/icon/svgs/poll_icon.js
Normal file
26
app/javascript/gabsocial/components/icon/svgs/poll_icon.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const PollIcon = ({
|
||||||
|
className = '',
|
||||||
|
width = '16px',
|
||||||
|
height = '16px',
|
||||||
|
viewBox = '0 0 48 48',
|
||||||
|
title = 'Poll',
|
||||||
|
}) => (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
version='1.1'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
x='0px'
|
||||||
|
y='0px'
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
viewBox={viewBox}
|
||||||
|
xmlSpace='preserve'
|
||||||
|
aria-label={title}
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path d="M 42.667969 0 L 5.332031 0 C 2.386719 0 0 2.386719 0 5.332031 L 0 42.667969 C 0 45.613281 2.386719 48 5.332031 48 L 42.667969 48 C 45.613281 48 48 45.613281 48 42.667969 L 48 5.332031 C 48 2.386719 45.613281 0 42.667969 0 Z M 16 37.332031 L 10.667969 37.332031 L 10.667969 18.667969 L 16 18.667969 Z M 26.667969 37.332031 L 21.332031 37.332031 L 21.332031 10.667969 L 26.667969 10.667969 Z M 37.332031 37.332031 L 32 37.332031 L 32 26.667969 L 37.332031 26.667969 Z M 37.332031 37.332031" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default PollIcon
|
@ -21,8 +21,8 @@ const ShareIcon = ({
|
|||||||
<circle cx="18" cy="5" r="3"/>
|
<circle cx="18" cy="5" r="3"/>
|
||||||
<circle cx="6" cy="12" r="3"/>
|
<circle cx="6" cy="12" r="3"/>
|
||||||
<circle cx="18" cy="19" r="3"/>
|
<circle cx="18" cy="19" r="3"/>
|
||||||
<line stroke='#666' stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="8.59" x2="15.42" y1="13.51" y2="17.49" />
|
<line stroke='#666' strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" x1="8.59" x2="15.42" y1="13.51" y2="17.49" />
|
||||||
<line stroke='#666' stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="15.41" x2="8.59" y1="6.51" y2="10.49" />
|
<line stroke='#666' strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" x1="15.41" x2="8.59" y1="6.51" y2="10.49" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
const WarningIcon = ({
|
||||||
|
className = '',
|
||||||
|
width = '16px',
|
||||||
|
height = '16px',
|
||||||
|
viewBox = '0 0 48 48',
|
||||||
|
title = 'Warning',
|
||||||
|
}) => (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
version='1.1'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
x='0px'
|
||||||
|
y='0px'
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
viewBox={viewBox}
|
||||||
|
xmlSpace='preserve'
|
||||||
|
aria-label={title}
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path d="M 47.003906 35.996094 L 30.046875 4.824219 C 27.324219 0.238281 20.679688 0.234375 17.953125 4.824219 L 1 35.996094 C -1.785156 40.683594 1.585938 46.617188 7.042969 46.617188 L 40.957031 46.617188 C 46.410156 46.617188 49.789062 40.6875 47.003906 35.996094 Z M 24 40.992188 C 22.449219 40.992188 21.1875 39.730469 21.1875 38.179688 C 21.1875 36.628906 22.449219 35.367188 24 35.367188 C 25.550781 35.367188 26.8125 36.628906 26.8125 38.179688 C 26.8125 39.730469 25.550781 40.992188 24 40.992188 Z M 26.8125 29.742188 C 26.8125 31.292969 25.550781 32.554688 24 32.554688 C 22.449219 32.554688 21.1875 31.292969 21.1875 29.742188 L 21.1875 15.679688 C 21.1875 14.128906 22.449219 12.867188 24 12.867188 C 25.550781 12.867188 26.8125 14.128906 26.8125 15.679688 Z M 26.8125 29.742188" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default WarningIcon
|
@ -164,7 +164,7 @@ class Item extends ImmutablePureComponent {
|
|||||||
|
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<a
|
<a
|
||||||
className='media-item__thumbnail'
|
className={[styles.default, styles.overflowHidden].join(' ')}
|
||||||
href={attachment.get('remote_url') || originalUrl}
|
href={attachment.get('remote_url') || originalUrl}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
@ -184,9 +184,9 @@ class Item extends ImmutablePureComponent {
|
|||||||
const autoPlay = !isIOS() && autoPlayGif !== false;
|
const autoPlay = !isIOS() && autoPlayGif !== false;
|
||||||
|
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}>
|
<div className={[styles.default, styles.overflowHidden, styles.heigh100PC, styles.width100PC].join(' ')}>
|
||||||
<video
|
<video
|
||||||
className='media-item__gifv'
|
className={[styles.default, styles.cursorPointer, styles.objectFitCover, styles.width100PC, styles.height100PC, styles.z1].join(' ')}
|
||||||
aria-label={attachment.get('description')}
|
aria-label={attachment.get('description')}
|
||||||
title={attachment.get('description')}
|
title={attachment.get('description')}
|
||||||
role='application'
|
role='application'
|
||||||
@ -208,8 +208,8 @@ class Item extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames('media-gallery__item', { standalone })} key={attachment.get('id')} style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}>
|
<div className={[styles.defeault, styles.positionAbsolute].join(' ')} key={attachment.get('id')} style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}>
|
||||||
<canvas width={32} height={32} ref={this.setCanvasRef} className={classNames('media-gallery__preview', { 'media-gallery__preview--hidden': visible && this.state.loaded })} />
|
<canvas width={0} height={0} ref={this.setCanvasRef} className={styles.displayNone} />
|
||||||
{visible && thumbnail}
|
{visible && thumbnail}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -512,10 +512,15 @@ class MediaGallery extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='media-gallery' style={style} ref={this.handleRef}>
|
<div
|
||||||
|
className={[styles.default, styles.overflowHidden, styles.borderColorSubtle, styles.borderTop1PX, styles.borderBottom1PX].join(' ')}
|
||||||
|
style={style}
|
||||||
|
ref={this.handleRef}
|
||||||
|
>
|
||||||
|
{ /*
|
||||||
<div className={classNames('spoiler-button', { 'spoiler-button--minified': visible })}>
|
<div className={classNames('spoiler-button', { 'spoiler-button--minified': visible })}>
|
||||||
{spoilerButton}
|
{spoilerButton}
|
||||||
</div>
|
</div> */ }
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,43 +1,55 @@
|
|||||||
|
import ColumnHeader from './column_header'
|
||||||
import Header from './header'
|
import Header from './header'
|
||||||
|
|
||||||
export default class PageLayout extends PureComponent {
|
export default class PageLayout extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
layout: PropTypes.object,
|
layout: PropTypes.object,
|
||||||
|
title: PropTypes.string,
|
||||||
|
showBackBtn: PropTypes.boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children, layout } = this.props
|
const { children, title, showBackBtn, layout } = this.props
|
||||||
|
|
||||||
const right = layout.RIGHT || null
|
const right = layout.RIGHT || null
|
||||||
const headerRight = layout.HEADER_RIGHT || null
|
const headerRight = layout.HEADER_RIGHT || null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[styles.default, styles.flexRow, styles.width100PC, styles.backgroundColorSubtle3].join(' ')}>
|
<div className={[styles.default, styles.flexRow, styles.width100PC, styles.backgroundColorSubtle3].join(' ')}>
|
||||||
|
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<main role='main' className={[styles.default, styles.flexShrink1, styles.flexGrow1, styles.borderColorSubtle2, styles.borderLeft1PX].join(' ')}>
|
<main role='main' className={[styles.default, styles.flexShrink1, styles.flexGrow1, styles.borderColorSubtle2, styles.borderLeft1PX].join(' ')}>
|
||||||
<div className={[styles.default, styles.height53PX, styles.borderBottom1PX, styles.borderColorSubtle2, styles.backgroundColorSubtle3].join(' ')}>
|
|
||||||
|
<div className={[styles.default, styles.height53PX, styles.borderBottom1PX, styles.borderColorSubtle2, styles.backgroundColorSubtle3, styles.z3, styles.top0, styles.positionFixed].join(' ')}>
|
||||||
<div className={[styles.default, styles.height53PX, styles.paddingLeft15PX, styles.width1015PX, styles.flexRow, styles.justifyContentSpaceBetween].join(' ')}>
|
<div className={[styles.default, styles.height53PX, styles.paddingLeft15PX, styles.width1015PX, styles.flexRow, styles.justifyContentSpaceBetween].join(' ')}>
|
||||||
<div className={[styles.default, styles.width660PX].join(' ')}>
|
<div className={[styles.default, styles.width660PX].join(' ')}>
|
||||||
test
|
<ColumnHeader title={title} />
|
||||||
</div>
|
</div>
|
||||||
<div className={[styles.default, styles.width325PX].join(' ')}>
|
<div className={[styles.default, styles.width325PX].join(' ')}>
|
||||||
{ headerRight }
|
{ headerRight }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={[styles.default, styles.height53PX].join(' ')}></div>
|
||||||
|
|
||||||
<div className={[styles.default, styles.width1015PX, styles.flexRow, styles.justifyContentSpaceBetween, styles.paddingLeft15PX, styles.paddingVertical15PX].join(' ')}>
|
<div className={[styles.default, styles.width1015PX, styles.flexRow, styles.justifyContentSpaceBetween, styles.paddingLeft15PX, styles.paddingVertical15PX].join(' ')}>
|
||||||
<div className={[styles.default, styles.width660PX, styles.z1].join(' ')}>
|
<div className={[styles.default, styles.width660PX, styles.z1].join(' ')}>
|
||||||
<div className={styles.default}>
|
<div className={styles.default}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={[styles.default, styles.width325PX].join(' ')}>
|
<div className={[styles.default, styles.width325PX].join(' ')}>
|
||||||
<div className={styles.default}>
|
<div className={styles.default}>
|
||||||
{right}
|
{right}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames/bind';
|
||||||
import Overlay from 'react-overlays/lib/Overlay';
|
import Overlay from 'react-overlays/lib/Overlay';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
import SearchPopout from '../search_popout';
|
import SearchPopout from '../search_popout';
|
||||||
@ -41,7 +41,19 @@ export default class Search extends PureComponent {
|
|||||||
const { expanded } = this.state;
|
const { expanded } = this.state;
|
||||||
|
|
||||||
const hasValue = value ? value.length > 0 || submitted : 0;
|
const hasValue = value ? value.length > 0 || submitted : 0;
|
||||||
const iconClass = hasValue ? 'active' : '';
|
|
||||||
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
|
const btnClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
cursorPointer: 1,
|
||||||
|
marginRight5PX: 1,
|
||||||
|
paddingHorizontal10PX: 1,
|
||||||
|
paddingVertical10PX: 1,
|
||||||
|
circle: 1,
|
||||||
|
backgroundColorBrandLight: 1,
|
||||||
|
displayNone: !hasValue,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[styles.default, styles.justifyContentCenter, styles.height53PX].join(' ')}>
|
<div className={[styles.default, styles.justifyContentCenter, styles.height53PX].join(' ')}>
|
||||||
@ -57,7 +69,7 @@ export default class Search extends PureComponent {
|
|||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
/>
|
/>
|
||||||
<div role='button' tabIndex='0' className={[styles.default, styles.cursorPointer, styles.marginRight5PX, styles.paddingHorizontal10PX, styles.paddingVertical10PX, styles.circle, styles.backgroundColorBrandLight].join(' ')} onClick={handleClear}>
|
<div role='button' tabIndex='0' className={btnClasses} onClick={handleClear}>
|
||||||
<Icon id='close' width='10px' height='10px' className={styles.fillColorWhite} aria-label={placeholder} />
|
<Icon id='close' width='10px' height='10px' className={styles.fillColorWhite} aria-label={placeholder} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -265,6 +265,8 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
const { intl, hidden, featured, otherAccounts, unread, showThread, group, promoted } = this.props;
|
const { intl, hidden, featured, otherAccounts, unread, showThread, group, promoted } = this.props;
|
||||||
|
|
||||||
|
// console.log("replies:", this.props.replies)
|
||||||
|
|
||||||
let { status, account, ...other } = this.props;
|
let { status, account, ...other } = this.props;
|
||||||
|
|
||||||
if (status === null) return null;
|
if (status === null) return null;
|
||||||
@ -391,6 +393,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (status.get('spoiler_text').length === 0 && status.get('card')) {
|
} else if (status.get('spoiler_text').length === 0 && status.get('card')) {
|
||||||
|
console.log("card:", status.get('card'))
|
||||||
media = (
|
media = (
|
||||||
<Card
|
<Card
|
||||||
onOpenMedia={this.props.onOpenMedia}
|
onOpenMedia={this.props.onOpenMedia}
|
||||||
@ -424,8 +427,6 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
const statusUrl = `/${status.getIn(['account', 'acct'])}/posts/${status.get('id')}`;
|
const statusUrl = `/${status.getIn(['account', 'acct'])}/posts/${status.get('id')}`;
|
||||||
|
|
||||||
console.log("const replies = state.getIn(['contexts', 'replies', id]);", state.getIn(['contexts', 'replies', id]))
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HotKeys handlers={handlers}>
|
<HotKeys handlers={handlers}>
|
||||||
<div
|
<div
|
||||||
@ -472,7 +473,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
<Icon id='globe' width='12px' height='12px' className={[styles.default, styles.displayInline, styles.marginLeft5PX, styles.fillColorSubtle].join(' ')}/>
|
<Icon id='globe' width='12px' height='12px' className={[styles.default, styles.displayInline, styles.marginLeft5PX, styles.fillColorSubtle].join(' ')}/>
|
||||||
|
|
||||||
{
|
{
|
||||||
status.get('group') &&
|
!!status.get('group') &&
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<span className={[styles.default, styles.text, styles.fontSize12PX, styles.marginLeft5PX, styles.colorSubtle].join(' ')}>•</span>
|
<span className={[styles.default, styles.text, styles.fontSize12PX, styles.marginLeft5PX, styles.colorSubtle].join(' ')}>•</span>
|
||||||
<NavLink
|
<NavLink
|
||||||
@ -502,7 +503,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={[styles.default, styles.paddingHorizontal15PX, styles.marginBottom15PX].join(' ')}>
|
<div className={styles.default}>
|
||||||
<StatusContent
|
<StatusContent
|
||||||
status={status}
|
status={status}
|
||||||
reblogContent={reblogContent}
|
reblogContent={reblogContent}
|
||||||
@ -513,7 +514,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ /* media */ }
|
{ media }
|
||||||
|
|
||||||
{ /* status.get('quote') && <StatusQuote
|
{ /* status.get('quote') && <StatusQuote
|
||||||
id={status.get('quote')}
|
id={status.get('quote')}
|
||||||
|
@ -57,21 +57,8 @@ class StatusActionBarItem extends PureComponent {
|
|||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
|
||||||
hovering: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOnMouseEnter = () => {
|
|
||||||
this.setState({ hovering: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOnMouseLeave = () => {
|
|
||||||
this.setState({ hovering: false })
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { title, onClick, icon, active, disabled } = this.props
|
const { title, onClick, icon, active, disabled } = this.props
|
||||||
const { hovering } = this.state
|
|
||||||
|
|
||||||
const cx = classNames.bind(styles)
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
@ -90,11 +77,9 @@ class StatusActionBarItem extends PureComponent {
|
|||||||
width100PC: 1,
|
width100PC: 1,
|
||||||
radiusSmall: 1,
|
radiusSmall: 1,
|
||||||
outlineFocusBrand: 1,
|
outlineFocusBrand: 1,
|
||||||
backgroundTransparent: !hovering,
|
backgroundTransparent: 1,
|
||||||
backgroundSubtle: hovering,
|
backgroundSubtle_onHover: 1,
|
||||||
colorSubtle: 1,
|
colorSubtle: 1,
|
||||||
// colorSubtle: !hovering,
|
|
||||||
// colorBrand: hovering,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -104,9 +89,7 @@ class StatusActionBarItem extends PureComponent {
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
active={active}
|
active={active}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
>
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
|
||||||
>
|
|
||||||
<Icon width='16px' height='16px' id={icon} className={[styles.default, styles.marginRight10PX, styles.fillColorSubtle].join(' ')} />
|
<Icon width='16px' height='16px' id={icon} className={[styles.default, styles.marginRight10PX, styles.fillColorSubtle].join(' ')} />
|
||||||
{title}
|
{title}
|
||||||
</button>
|
</button>
|
||||||
@ -358,25 +341,83 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
const hasInteractions = favoriteCount > 0 || replyCount > 0 || reblogCount > 0
|
||||||
<div className={[styles.default, styles.marginTop10PX, styles.paddingHorizontal10PX].join(' ')}>
|
const shouldCondense = (!!status.get('card') || status.get('media_attachments').size > 0) && !hasInteractions
|
||||||
<div className={[styles.default, styles.paddingVertical2PX, styles.flexRow, styles.borderTop1PX, styles.borderColorSubtle].join(' ')}>
|
|
||||||
{
|
|
||||||
items.map((item, i) => (
|
|
||||||
<StatusActionBarItem key={`status-action-bar-item-${i}`} {...item} />
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
{/*<div className='status-action-bar__dropdown'>
|
const cx = classNames.bind(styles)
|
||||||
<DropdownMenuContainer
|
|
||||||
status={status}
|
const containerClasses = cx({
|
||||||
items={menu}
|
default: 1,
|
||||||
icon='ellipsis-h'
|
paddingHorizontal10PX: 1,
|
||||||
size={18}
|
marginTop10PX: !shouldCondense,
|
||||||
direction='right'
|
marginTop5PX: shouldCondense,
|
||||||
title={formatMessage(messages.more)}
|
})
|
||||||
/>
|
|
||||||
</div>*/}
|
const innerContainerClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
paddingVertical2PX: 1,
|
||||||
|
flexRow: 1,
|
||||||
|
width100PC: 1,
|
||||||
|
borderTop1PX: !shouldCondense,
|
||||||
|
borderColorSubtle: !shouldCondense,
|
||||||
|
marginTop5PX: hasInteractions,
|
||||||
|
})
|
||||||
|
|
||||||
|
const interactionBtnClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
text: 1,
|
||||||
|
colorSubtle: 1,
|
||||||
|
cursorPointer: 1,
|
||||||
|
fontSize15PX: 1,
|
||||||
|
fontWeightNormal: 1,
|
||||||
|
marginRight10PX: 1,
|
||||||
|
paddingVertical5PX: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={containerClasses}>
|
||||||
|
{
|
||||||
|
hasInteractions &&
|
||||||
|
<div className={[styles.default, styles.flexRow, styles.paddingHorizontal5PX].join(' ')}>
|
||||||
|
{ favoriteCount > 0 &&
|
||||||
|
<button className={interactionBtnClasses}>
|
||||||
|
{favoriteCount}
|
||||||
|
Likes
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
{ replyCount > 0 &&
|
||||||
|
<button className={interactionBtnClasses}>
|
||||||
|
{replyCount}
|
||||||
|
Comments
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
{ reblogCount > 0 &&
|
||||||
|
<button className={interactionBtnClasses}>
|
||||||
|
{reblogCount}
|
||||||
|
Reposts
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div className={innerContainerClasses}>
|
||||||
|
<div className={[styles.default, styles.flexRow, styles.paddingVertical2PX, styles.width100PC].join(' ')}>
|
||||||
|
{
|
||||||
|
items.map((item, i) => (
|
||||||
|
<StatusActionBarItem key={`status-action-bar-item-${i}`} {...item} />
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
{/*<div className='status-action-bar__dropdown'>
|
||||||
|
<DropdownMenuContainer
|
||||||
|
status={status}
|
||||||
|
items={menu}
|
||||||
|
icon='ellipsis-h'
|
||||||
|
size={18}
|
||||||
|
direction='right'
|
||||||
|
title={formatMessage(messages.more)}
|
||||||
|
/>
|
||||||
|
</div>*/}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='status-action-bar__comment'>
|
<div className='status-action-bar__comment'>
|
||||||
{/*<ComposeFormContainer shouldCondense statusId={status.get('id')} />*/}
|
{/*<ComposeFormContainer shouldCondense statusId={status.get('id')} />*/}
|
||||||
|
@ -2,7 +2,7 @@ import { Fragment } from 'react';
|
|||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
||||||
import classnames from 'classnames';
|
import classNames from 'classnames/bind'
|
||||||
import { isRtl } from '../../utils/rtl';
|
import { isRtl } from '../../utils/rtl';
|
||||||
import Permalink from '../permalink/permalink';
|
import Permalink from '../permalink/permalink';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
@ -12,6 +12,7 @@ const MAX_HEIGHT = 200;
|
|||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
showMore: { id: 'status.show_more', defaultMessage: 'Show more' },
|
showMore: { id: 'status.show_more', defaultMessage: 'Show more' },
|
||||||
showLess: { id: 'status.show_less', defaultMessage: 'Show less' },
|
showLess: { id: 'status.show_less', defaultMessage: 'Show less' },
|
||||||
|
readMore: { id: 'status.read_more', defaultMessage: 'Read more' },
|
||||||
})
|
})
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@ -161,16 +162,20 @@ class StatusContent extends ImmutablePureComponent {
|
|||||||
const content = { __html: this.getHtmlContent() };
|
const content = { __html: this.getHtmlContent() };
|
||||||
const spoilerContent = { __html: status.get('spoilerHtml') };
|
const spoilerContent = { __html: status.get('spoilerHtml') };
|
||||||
const directionStyle = { direction: 'ltr' };
|
const directionStyle = { direction: 'ltr' };
|
||||||
const classNames = classnames('status__content', {
|
// const classNames = '';
|
||||||
'status__content--with-action': this.props.onClick && this.context.router,
|
// classnames('status__content', {
|
||||||
'status__content--with-spoiler': status.get('spoiler_text').length > 0,
|
// 'status__content--with-action': this.props.onClick && this.context.router,
|
||||||
'status__content--collapsed': this.state.collapsed === true,
|
// 'status__content--with-spoiler': status.get('spoiler_text').length > 0,
|
||||||
});
|
// 'status__content--collapsed': this.state.collapsed === true,
|
||||||
|
// // styles.paddingHorizontal15PX, styles.marginBottom15PX
|
||||||
|
// });
|
||||||
|
|
||||||
if (isRtl(status.get('search_index'))) {
|
if (isRtl(status.get('search_index'))) {
|
||||||
directionStyle.direction = 'rtl';
|
directionStyle.direction = 'rtl';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
if (status.get('spoiler_text').length > 0) {
|
if (status.get('spoiler_text').length > 0) {
|
||||||
let mentionsPlaceholder = '';
|
let mentionsPlaceholder = '';
|
||||||
|
|
||||||
@ -187,7 +192,7 @@ class StatusContent extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames} ref={this.setRef} tabIndex='0' style={directionStyle} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}>
|
<div className={[].join(' ')} ref={this.setRef} tabIndex='0' style={directionStyle} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}>
|
||||||
<p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }}>
|
<p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }}>
|
||||||
<span dangerouslySetInnerHTML={spoilerContent} lang={status.get('language')} />
|
<span dangerouslySetInnerHTML={spoilerContent} lang={status.get('language')} />
|
||||||
{' '}
|
{' '}
|
||||||
@ -200,8 +205,15 @@ class StatusContent extends ImmutablePureComponent {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (this.props.onClick) {
|
} else if (this.props.onClick) {
|
||||||
|
const hasMarginBottom = !!status.get('card') || !!status.get('poll') || status.get('media_attachments').size > 0
|
||||||
|
|
||||||
|
const containerClasses = cx({
|
||||||
|
paddingHorizontal15PX: 1,
|
||||||
|
marginBottom15PX: hasMarginBottom,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<div className={containerClasses}>
|
||||||
<div
|
<div
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
@ -212,17 +224,16 @@ class StatusContent extends ImmutablePureComponent {
|
|||||||
onMouseDown={this.handleMouseDown}
|
onMouseDown={this.handleMouseDown}
|
||||||
onMouseUp={this.handleMouseUp}
|
onMouseUp={this.handleMouseUp}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{
|
{
|
||||||
this.state.collapsed &&
|
this.state.collapsed &&
|
||||||
<button
|
<button
|
||||||
className={[styles.default].join(' ')}
|
className={[styles.default, styles.displayFlex, styles.cursorPointer, styles.paddingVertical2PX, styles.text, styles.colorBlack, styles.fontWeightBold, styles.fontSize15PX].join(' ')}
|
||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}
|
||||||
>
|
>
|
||||||
<FormattedMessage id='status.read_more' defaultMessage='Read more' />
|
{intl.formatMessage(messages.readMore)}
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
</Fragment>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +241,7 @@ class StatusContent extends ImmutablePureComponent {
|
|||||||
<div
|
<div
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
className={[styles.statusContent].join(' ')}
|
className={[styles.paddingHorizontal15PX, styles.marginBottom15PX, styles.statusContent].join(' ')}
|
||||||
style={directionStyle}
|
style={directionStyle}
|
||||||
dangerouslySetInnerHTML={content}
|
dangerouslySetInnerHTML={content}
|
||||||
lang={status.get('language')}
|
lang={status.get('language')}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { me } from '../../initial_state';
|
import { me } from '../initial_state';
|
||||||
import ComposeFormContainer from '../../features/compose/containers/compose_form_container';
|
import ComposeFormContainer from '../features/compose/containers/compose_form_container';
|
||||||
import Avatar from '../avatar';
|
import Avatar from './avatar';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
@ -26,7 +26,7 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
|||||||
const { account, size, ...rest } = this.props;
|
const { account, size, ...rest } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={[styles.default, styles.radiusSmall, styles.border1PX, styles.borderColorSubtle, styles.backgroundWhite, styles.marginBottom15PX].join(' ')}>
|
<section className={[styles.default, styles.overflowHidden, styles.radiusSmall, styles.border1PX, styles.borderColorSubtle, styles.backgroundWhite, styles.marginBottom15PX].join(' ')}>
|
||||||
<div className={[styles.default, styles.backgroundSubtle, styles.borderBottom1PX, styles.borderColorSubtle, styles.paddingHorizontal15PX, styles.paddingVertical2PX].join(' ')}>
|
<div className={[styles.default, styles.backgroundSubtle, styles.borderBottom1PX, styles.borderColorSubtle, styles.paddingHorizontal15PX, styles.paddingVertical2PX].join(' ')}>
|
||||||
<h1 className={[styles.default, styles.text, styles.colorSubtle, styles.fontSize12PX, styles.fontWeight500, styles.lineHeight2, styles.paddingVertical2PX].join(' ')}>
|
<h1 className={[styles.default, styles.text, styles.colorSubtle, styles.fontSize12PX, styles.fontWeight500, styles.lineHeight2, styles.paddingVertical2PX].join(' ')}>
|
||||||
Create Post
|
Create Post
|
@ -1 +0,0 @@
|
|||||||
export { default } from './timeline_compose_block';
|
|
@ -1,19 +0,0 @@
|
|||||||
.timeline-compose-block {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
padding: 20px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
@include gab-container-standards();
|
|
||||||
|
|
||||||
.emoji-picker-wrapper {
|
|
||||||
.emoji-picker-dropdown {
|
|
||||||
top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.compose-form {
|
|
||||||
flex: 1 1;
|
|
||||||
padding: 0 0 0 20px !important;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
}
|
|
@ -50,6 +50,7 @@ const makeMapStateToProps = () => {
|
|||||||
|
|
||||||
const mapStateToProps = (state, props) => ({
|
const mapStateToProps = (state, props) => ({
|
||||||
status: getStatus(state, props),
|
status: getStatus(state, props),
|
||||||
|
replies: state.getIn(['contexts', 'replies', props.id]),
|
||||||
});
|
});
|
||||||
|
|
||||||
return mapStateToProps;
|
return mapStateToProps;
|
||||||
|
@ -7,7 +7,7 @@ import { expandAccountFeaturedTimeline, expandAccountTimeline } from '../../acti
|
|||||||
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
||||||
import { me } from '../../initial_state';
|
import { me } from '../../initial_state';
|
||||||
import StatusList from '../../components/status_list/status_list';
|
import StatusList from '../../components/status_list/status_list';
|
||||||
import ColumnIndicator from '../../components/column_indicator/column_indicator';
|
import ColumnIndicator from '../../components/column_indicator';
|
||||||
import Column from '../../components/column';
|
import Column from '../../components/column';
|
||||||
import SectionHeadlineBar from '../../components/section_headline_bar' ;
|
import SectionHeadlineBar from '../../components/section_headline_bar' ;
|
||||||
|
|
||||||
|
@ -1,23 +1,36 @@
|
|||||||
import { length } from 'stringz';
|
import { length } from 'stringz'
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
export default class CharacterCounter extends PureComponent {
|
export default class CharacterCounter extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
text: PropTypes.string.isRequired,
|
text: PropTypes.string.isRequired,
|
||||||
max: PropTypes.number.isRequired,
|
max: PropTypes.number.isRequired,
|
||||||
};
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const diff = this.props.max - length(this.props.text);
|
const radius = 12
|
||||||
|
const circumference = 2 * Math.PI * radius
|
||||||
const classes = classNames('character-counter', {
|
const diff = length(this.props.text) / this.props.max
|
||||||
'character-counter--over': (diff < 0),
|
const dashoffset = circumference * (1 - diff)
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='character-counter__wrapper'>
|
<div className={[styles.default, styles.marginRight10PX, styles.justifyContentCenter, styles.alignItemsCenter].join(' ')}>
|
||||||
<span className={classes}>{diff}</span>
|
<svg width="32" height="32" viewBox="0 0 32 32">
|
||||||
|
<circle fill='none' cx="16" cy="16" r="12" fill="none" stroke="#e6e6e6" stroke-width="2" />
|
||||||
|
<circle style={{
|
||||||
|
// transform: 'rotate(-90deg)',
|
||||||
|
strokeDashoffset: dashoffset,
|
||||||
|
strokeDasharray: circumference,
|
||||||
|
}}
|
||||||
|
fill='none'
|
||||||
|
cx="16"
|
||||||
|
cy="16"
|
||||||
|
r="12"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap='round'
|
||||||
|
stroke='#21cf7a'
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ export default class ComposeExtraButton extends PureComponent {
|
|||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
>
|
>
|
||||||
<Icon icon={icon} width='18px' height='18px' />
|
<Icon id={icon} width='18px' height='18px' className={styles.fillColorSubtle} />
|
||||||
<span className={titleClasses}>
|
<span className={titleClasses}>
|
||||||
{title}
|
{title}
|
||||||
</span>
|
</span>
|
||||||
|
@ -299,6 +299,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
</div>
|
</div>
|
||||||
<CharacterCounter max={maxPostCharacterCount} text={text} />
|
<CharacterCounter max={maxPostCharacterCount} text={text} />
|
||||||
<Button
|
<Button
|
||||||
|
className={[styles.fontSize15PX, styles.paddingHorizontal15PX].join(' ')}
|
||||||
text={intl.formatMessage(scheduledAt ? messages.schedulePost : messages.publish)}
|
text={intl.formatMessage(scheduledAt ? messages.schedulePost : messages.publish)}
|
||||||
onClick={this.handleSubmit}
|
onClick={this.handleSubmit}
|
||||||
disabled={disabledButton}
|
disabled={disabledButton}
|
||||||
|
@ -54,7 +54,7 @@ class PollButton extends PureComponent {
|
|||||||
title={intl.formatMessage(active ? messages.remove_poll : messages.title)}
|
title={intl.formatMessage(active ? messages.remove_poll : messages.title)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
icon='tasks'
|
icon='poll'
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ class UploadButton extends ImmutablePureComponent {
|
|||||||
title={intl.formatMessage(messages.title)}
|
title={intl.formatMessage(messages.title)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
icon='upload'
|
icon='media'
|
||||||
>
|
>
|
||||||
<label>
|
<label>
|
||||||
<span className={styles.displayNone}>{intl.formatMessage(messages.upload)}</span>
|
<span className={styles.displayNone}>{intl.formatMessage(messages.upload)}</span>
|
||||||
|
@ -5,7 +5,7 @@ import { fetchPinnedStatuses } from '../../actions/pin_statuses';
|
|||||||
import { meUsername } from '../../initial_state';
|
import { meUsername } from '../../initial_state';
|
||||||
import Column from '../../components/column';
|
import Column from '../../components/column';
|
||||||
import StatusList from '../../components/status_list/status_list';
|
import StatusList from '../../components/status_list/status_list';
|
||||||
import ColumnIndicator from '../../components/column_indicator/column_indicator';
|
import ColumnIndicator from '../../components/column_indicator';
|
||||||
|
|
||||||
const mapStateToProps = (state, { params: { username } }) => {
|
const mapStateToProps = (state, { params: { username } }) => {
|
||||||
return {
|
return {
|
||||||
|
@ -115,113 +115,131 @@ export default class Card extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderVideo () {
|
renderVideo () {
|
||||||
const { card } = this.props;
|
const { card } = this.props
|
||||||
const content = { __html: addAutoPlay(card.get('html')) };
|
const content = { __html: addAutoPlay(card.get('html')) }
|
||||||
const { width } = this.state;
|
const { width } = this.state
|
||||||
const ratio = card.get('width') / card.get('height');
|
const ratio = card.get('width') / card.get('height')
|
||||||
const height = width / ratio;
|
const height = width / ratio
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
className='status-card__image status-card-video'
|
className={[styles.default, styles.backgroundColorSubtle3, styles.positionAbsolute, styles.top0, styles.right0, styles.bottom0, styles.left0, styles.statusCardVideo].join(' ')}
|
||||||
dangerouslySetInnerHTML={content}
|
dangerouslySetInnerHTML={content}
|
||||||
style={{
|
|
||||||
height,
|
|
||||||
paddingBottom: 0,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { card } = this.props;
|
const { card } = this.props
|
||||||
const { width, embedded } = this.state;
|
const { width, embedded } = this.state
|
||||||
|
|
||||||
if (card === null) {
|
if (card === null) return null
|
||||||
return null;
|
|
||||||
}
|
const maxDescription = 160
|
||||||
|
const cardImg = card.get('image')
|
||||||
|
const provider = card.get('provider_name').length === 0 ? decodeIDNA(getHostname(card.get('url'))) : card.get('provider_name')
|
||||||
|
const horizontal = (card.get('width') > card.get('height') && (card.get('width') + 100 >= width)) || card.get('type') !== 'link' || embedded
|
||||||
|
const interactive = card.get('type') !== 'link'
|
||||||
|
|
||||||
const maxDescription = 150;
|
|
||||||
const cardImg = card.get('image');
|
|
||||||
const provider = card.get('provider_name').length === 0 ? decodeIDNA(getHostname(card.get('url'))) : card.get('provider_name');
|
|
||||||
const horizontal = (card.get('width') > card.get('height') && (card.get('width') + 100 >= width)) || card.get('type') !== 'link' || embedded;
|
|
||||||
const interactive = card.get('type') !== 'link';
|
|
||||||
const className = classnames('status-card', {
|
|
||||||
horizontal,
|
|
||||||
interactive,
|
|
||||||
compact: !cardImg && !interactive,
|
|
||||||
});
|
|
||||||
const title = interactive ?
|
const title = interactive ?
|
||||||
<a className='status-card__title' href={card.get('url')} title={card.get('title')} rel='noopener' target='_blank'>
|
(
|
||||||
<strong>{card.get('title')}</strong>
|
<a
|
||||||
</a>
|
className={[styles.default, styles.displayFlex, styles.text, styles.noUnderline, styles.overflowWrapBreakWord, styles.colorBlack, styles.fontSize15PX, styles.fontWeight500].join(' ')}
|
||||||
: <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>;
|
href={card.get('url')}
|
||||||
|
title={card.get('title')}
|
||||||
|
rel='noopener'
|
||||||
|
target='_blank'
|
||||||
|
>
|
||||||
|
{card.get('title')}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<span className={[styles.default, styles.displayFlex, styles.text, styles.overflowWrapBreakWord, styles.colorBlack, styles.fontSize15PX, styles.fontWeight500].join(' ')}>
|
||||||
|
{card.get('title')}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
|
||||||
const description = (
|
const description = (
|
||||||
<div className='status-card__content'>
|
<div className={[styles.default, styles.flexNormal, styles.paddingHorizontal10PX, styles.paddingVertical10PX, styles.borderColorSubtle, styles.borderLeft1PX].join(' ')}>
|
||||||
{title}
|
{title}
|
||||||
{!horizontal && <p className='status-card__description'>{trim(card.get('description') || '', maxDescription)}</p>}
|
<p className={[styles.default, styles.displayFlex, styles.text, styles.marginVertical5PX, styles.overflowWrapBreakWord, styles.colorSubtle, styles.fontSize13PX, styles.fontWeightNormal].join(' ')}>
|
||||||
<span className='status-card__host'>
|
{trim(card.get('description') || '', maxDescription)}
|
||||||
<Icon id='link' fixedWidth />
|
</p>
|
||||||
{' '}
|
<span className={[styles.default, styles.marginTopAuto, styles.flexRow, styles.alignItemsCenter, styles.colorSubtle, styles.text, styles.displayFlex, styles.textOverflowEllipsis, styles.fontSize13PX].join(' ')}>
|
||||||
|
<Icon id='link' width='12px' height='12px' className={[styles.fillColorSubtle, styles.marginRight5PX].join(' ')} fixedWidth />
|
||||||
{provider}
|
{provider}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
let embed = '';
|
let embed = ''
|
||||||
let thumbnail = card ? <div style={{ backgroundImage: `url(${cardImg})` }} className='status-card__image-image' /> : thumbnail = <div className='status-card__image-image' />;
|
let thumbnail = interactive ?
|
||||||
|
<img src={cardImg} className={[styles.default, styles.objectFitCover, styles.positionAbsolute, styles.width100PC, styles.height100PC, styles.top0, styles.right0, styles.bottom0, styles.left0].join(' ')} />
|
||||||
|
:
|
||||||
|
<img src={cardImg} className={[styles.default, styles.objectFitCover, styles.width400PX, styles.height260PX].join(' ')} />
|
||||||
|
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
if (embedded) {
|
if (embedded) {
|
||||||
embed = this.renderVideo();
|
embed = this.renderVideo()
|
||||||
} else {
|
}
|
||||||
let iconVariant = 'play';
|
|
||||||
|
|
||||||
if (card.get('type') === 'photo') {
|
let iconVariant = 'play'
|
||||||
iconVariant = 'search-plus';
|
|
||||||
}
|
|
||||||
|
|
||||||
embed = (
|
if (card.get('type') === 'photo') {
|
||||||
<div className='status-card__image'>
|
iconVariant = 'search-plus'
|
||||||
{thumbnail}
|
|
||||||
<div className='status-card__actions'>
|
|
||||||
<div>
|
|
||||||
<button onClick={this.handleEmbedClick}><Icon id={iconVariant} /></button>
|
|
||||||
{horizontal && <a href={card.get('url')} target='_blank' rel='noopener'><Icon id='external-link' /></a>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className} ref={this.setRef}>
|
<div className={[styles.default, styles.width100PC, styles.paddingHorizontal10PX].join(' ')}>
|
||||||
{embed}
|
<div className={[styles.default, styles.overflowHidden, styles.width100PC, styles.borderColorSubtle2, styles.border1PX, styles.radiusSmall].join(' ')}>
|
||||||
{description}
|
<div className={[styles.default, styles.width100PC].join(' ')}>
|
||||||
|
<div className={[styles.default, styles.width100PC, styles.paddingTop5625PC].join(' ')}>
|
||||||
|
{ !!embed && embed}
|
||||||
|
{ !embed && thumbnail}
|
||||||
|
{ !embed &&
|
||||||
|
<div className={[styles.default, styles.positionAbsolute, styles.top0, styles.right0, styles.left0, styles.bottom0, styles.alignItemsCenter, styles.justifyContentCenter].join(' ')}>
|
||||||
|
<button
|
||||||
|
className={[styles.default, styles.cursorPointer, styles.backgroundColorOpaque, styles.radiusSmall, styles.paddingVertical15PX, styles.paddingHorizontal15PX].join(' ')}
|
||||||
|
onClick={this.handleEmbedClick}
|
||||||
|
>
|
||||||
|
<Icon id={iconVariant} className={[styles.fillColorWhite].join(' ')}/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{description}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
} else if (cardImg) {
|
} else if (cardImg) {
|
||||||
embed = (
|
embed = (
|
||||||
<div className='status-card__image'>
|
<div className={[styles.default].join(' ')}>
|
||||||
{thumbnail}
|
{thumbnail}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
} else {
|
} else {
|
||||||
embed = (
|
embed = (
|
||||||
<div className='status-card__image'>
|
<div className={[styles.default, styles.paddingVertical15PX, styles.paddingHorizontal15PX, styles.width72PX, styles.alignItemsCenter, styles.justifyContentCenter].join(' ')}>
|
||||||
<Icon id='file-text' />
|
<Icon id='file-text' width='22px' height='22px' className={styles.fillColorSubtle} />
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a href={card.get('url')} className={className} target='_blank' rel='noopener' ref={this.setRef}>
|
<div className={[styles.default, styles.width100PC, styles.paddingHorizontal10PX].join(' ')}>
|
||||||
{embed}
|
<a
|
||||||
{description}
|
href={card.get('url')}
|
||||||
</a>
|
className={[styles.default, styles.cursorPointer, styles.flexRow, styles.overflowHidden, styles.noUnderline, styles.width100PC, styles.borderColorSubtle2, styles.border1PX, styles.radiusSmall].join(' ')}
|
||||||
);
|
rel='noopener'
|
||||||
|
ref={this.setRef}
|
||||||
|
>
|
||||||
|
{embed}
|
||||||
|
{description}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import HomePage from '../../pages/home_page';
|
|||||||
// import GroupSidebarPanel from '../groups/sidebar_panel';
|
// import GroupSidebarPanel from '../groups/sidebar_panel';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
// Status,
|
Status,
|
||||||
// GettingStarted,
|
// GettingStarted,
|
||||||
// CommunityTimeline,
|
// CommunityTimeline,
|
||||||
// AccountTimeline,
|
// AccountTimeline,
|
||||||
@ -230,10 +230,10 @@ class SwitchingColumnsArea extends PureComponent {
|
|||||||
|
|
||||||
<Redirect from='/@:username/pins' to='/:username/pins' />
|
<Redirect from='/@:username/pins' to='/:username/pins' />
|
||||||
<WrappedRoute path='/:username/pins' component={PinnedStatuses} page={ProfilePage} content={children} />
|
<WrappedRoute path='/:username/pins' component={PinnedStatuses} page={ProfilePage} content={children} />
|
||||||
|
*/ }
|
||||||
<Redirect from='/@:username/posts/:statusId' to='/:username/posts/:statusId' exact />
|
<Redirect from='/@:username/posts/:statusId' to='/:username/posts/:statusId' exact />
|
||||||
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact layout={LAYOUT.STATUS} component={Status} content={children} />
|
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact layout={LAYOUT.STATUS} component={Status} content={children} />
|
||||||
|
{ /*
|
||||||
<Redirect from='/@:username/posts/:statusId/reblogs' to='/:username/posts/:statusId/reblogs' />
|
<Redirect from='/@:username/posts/:statusId/reblogs' to='/:username/posts/:statusId/reblogs' />
|
||||||
<WrappedRoute path='/:username/posts/:statusId/reblogs' layout={LAYOUT.STATUS} component={Reblogs} content={children} />
|
<WrappedRoute path='/:username/posts/:statusId/reblogs' layout={LAYOUT.STATUS} component={Reblogs} content={children} />
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ export default class WrappedRoute extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderLoading = () => {
|
renderLoading = () => {
|
||||||
return <ColumnIndicator type='loading' />;
|
return <div />
|
||||||
}
|
}
|
||||||
|
|
||||||
renderError = (props) => {
|
renderError = (props) => {
|
||||||
|
@ -16,8 +16,8 @@ export default class HomePage extends PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PageLayout
|
<PageLayout
|
||||||
|
title='Home'
|
||||||
layout={{
|
layout={{
|
||||||
HEADER: <span>hello</span>,
|
|
||||||
HEADER_RIGHT: <Search />,
|
HEADER_RIGHT: <Search />,
|
||||||
RIGHT: (
|
RIGHT: (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
@ -16,6 +16,11 @@ body {
|
|||||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.statusCardVideo iframe {
|
||||||
|
height: 100% !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
.default {
|
.default {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-basis: auto;
|
flex-basis: auto;
|
||||||
@ -93,7 +98,7 @@ body {
|
|||||||
.resizeNone { resize: none; }
|
.resizeNone { resize: none; }
|
||||||
|
|
||||||
.circle { border-radius: 9999px; }
|
.circle { border-radius: 9999px; }
|
||||||
.radiusSmall { border-radius: 4px; }
|
.radiusSmall { border-radius: 8px; }
|
||||||
|
|
||||||
.borderColorSubtle2 { border-color: #e5e9ed; }
|
.borderColorSubtle2 { border-color: #e5e9ed; }
|
||||||
.borderColorSubtle { border-color: #ECECED; }
|
.borderColorSubtle { border-color: #ECECED; }
|
||||||
@ -122,13 +127,16 @@ body {
|
|||||||
.backgroundTransparent { background-color: transparent; }
|
.backgroundTransparent { background-color: transparent; }
|
||||||
.backgroundPanel { background-color: #aaa; }
|
.backgroundPanel { background-color: #aaa; }
|
||||||
.backgroundSubtle { background-color: #F5F8FA; }
|
.backgroundSubtle { background-color: #F5F8FA; }
|
||||||
|
.backgroundSubtle_onHover:hover { background-color: #F5F8FA; }
|
||||||
.backgroundSubtle2 { background-color: #e8ecef; }
|
.backgroundSubtle2 { background-color: #e8ecef; }
|
||||||
.backgroundColorSubtle3 { background-color: #F6F6F9; }
|
.backgroundColorSubtle3 { background-color: #F6F6F9; }
|
||||||
.backgroundWhite { background-color: #fff; }
|
.backgroundWhite { background-color: #fff; }
|
||||||
.backgroundColorBrandLightOpaque { background-color: rgba(54, 233, 145, 0.1); }
|
.backgroundColorBrandLightOpaque { background-color: rgba(54, 233, 145, 0.1); }
|
||||||
|
.backgroundColorOpaque { background-color: rgba(0,0,0, 0.4); }
|
||||||
.backgroundColorBrandLight { background-color: #36e991; }
|
.backgroundColorBrandLight { background-color: #36e991; }
|
||||||
.backgroundColorBrand { background-color: #21cf7a; }
|
.backgroundColorBrand { background-color: #21cf7a; }
|
||||||
.backgroundColorBrandDark { background-color: #38A16B; }
|
.backgroundColorBrandDark { background-color: #38A16B; }
|
||||||
|
.backgroundColorBrandDark_onHover:hover { background-color: #38A16B; }
|
||||||
.colorBlack { color: #000; }
|
.colorBlack { color: #000; }
|
||||||
.colorWhite { color: #fff; }
|
.colorWhite { color: #fff; }
|
||||||
.colorSubtle { color: #666; }
|
.colorSubtle { color: #666; }
|
||||||
@ -161,9 +169,11 @@ body {
|
|||||||
.height53PX { height: 53px; }
|
.height53PX { height: 53px; }
|
||||||
.height72PX { height: 72px; }
|
.height72PX { height: 72px; }
|
||||||
.height122PX { height: 122px; }
|
.height122PX { height: 122px; }
|
||||||
|
.height260PX { height: 260px; }
|
||||||
|
|
||||||
.width1015PX { width: 1015px; }
|
.width1015PX { width: 1015px; }
|
||||||
.width660PX { width: 660px; }
|
.width660PX { width: 660px; }
|
||||||
|
.width400PX { width: 400px; }
|
||||||
.width325PX { width: 325px; }
|
.width325PX { width: 325px; }
|
||||||
.width250PX { width: 250px; }
|
.width250PX { width: 250px; }
|
||||||
.width100PC { width: 100%; }
|
.width100PC { width: 100%; }
|
||||||
@ -175,6 +185,7 @@ body {
|
|||||||
|
|
||||||
.textAlignCenter { text-align: center; }
|
.textAlignCenter { text-align: center; }
|
||||||
|
|
||||||
|
.fontSize24PX { font-size: 24px; }
|
||||||
.fontSize19PX { font-size: 19px; }
|
.fontSize19PX { font-size: 19px; }
|
||||||
.fontSize16PX { font-size: 16px; }
|
.fontSize16PX { font-size: 16px; }
|
||||||
.fontSize15PX { font-size: 15px; }
|
.fontSize15PX { font-size: 15px; }
|
||||||
@ -189,6 +200,7 @@ body {
|
|||||||
|
|
||||||
.noUnderline { text-decoration: none; }
|
.noUnderline { text-decoration: none; }
|
||||||
.underline { text-decoration: underline; }
|
.underline { text-decoration: underline; }
|
||||||
|
.underline_onHover:hover { text-decoration: underline; }
|
||||||
|
|
||||||
.objectFitCover { object-fit: cover; }
|
.objectFitCover { object-fit: cover; }
|
||||||
|
|
||||||
@ -218,8 +230,11 @@ body {
|
|||||||
.marginBottom10PX { margin-bottom: 10px; }
|
.marginBottom10PX { margin-bottom: 10px; }
|
||||||
.marginTop10PX { margin-top: 10px; }
|
.marginTop10PX { margin-top: 10px; }
|
||||||
.marginTop5PX { margin-top: 5px; }
|
.marginTop5PX { margin-top: 5px; }
|
||||||
|
.marginTopAuto { margin-top: auto; }
|
||||||
.marginTopNeg30PX { margin-top: -30px; }
|
.marginTopNeg30PX { margin-top: -30px; }
|
||||||
|
|
||||||
|
.paddingTop5625PC { padding-top: 56.25%; }
|
||||||
|
|
||||||
.paddingHorizontal15PX {
|
.paddingHorizontal15PX {
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user