This commit is contained in:
mgabdev
2020-02-24 18:25:55 -05:00
parent 7679012e2f
commit 32cd8e622a
62 changed files with 404 additions and 771 deletions

View File

@@ -1,5 +1,4 @@
import { defineMessages, injectIntl } from 'react-intl';
import Column from '../column';
import IconButton from '../icon_button';
const messages = defineMessages({
@@ -25,12 +24,10 @@ class BundleColumnError extends PureComponent {
const { intl: { formatMessage } } = this.props;
return (
<Column>
<div className='error-column'>
<IconButton title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
{formatMessage(messages.body)}
</div>
</Column>
<div className='error-column'>
<IconButton title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
{formatMessage(messages.body)}
</div>
);
}

View File

@@ -1,30 +0,0 @@
import { isMobile } from '../../utils/is_mobile';
export default class Column extends PureComponent {
static propTypes = {
heading: PropTypes.string,
icon: PropTypes.string,
children: PropTypes.node,
active: PropTypes.bool,
hideHeadingOnMobile: PropTypes.bool,
backBtn: PropTypes.oneOf([
'normal',
'slim',
]),
};
render () {
const { heading, icon, children, active, hideHeadingOnMobile, backBtn } = this.props;
const showHeading = heading && (!hideHeadingOnMobile || (hideHeadingOnMobile && !isMobile(window.innerWidth)));
const columnHeaderId = showHeading && heading.replace(/ /g, '-');
return (
<div role='region' aria-labelledby={columnHeaderId} className={[_s.default].join(' ')}>
{children}
</div>
);
}
}

View File

@@ -1,22 +0,0 @@
.column {
display: flex;
position: relative;
box-sizing: border-box;
flex-direction: column;
// width: 350px;
flex: 1 1 100%;
overflow: hidden;
@media screen and (min-width: 631px) {
flex: 0 0 auto;
padding: 10px 5px;
&:first-child {
padding-left: 10px;
}
&:last-child {
padding-right: 10px;
}
}
}

View File

@@ -1 +0,0 @@
export { default } from './column';

View File

@@ -1,14 +0,0 @@
export default class ColumnSettingsHeading extends PureComponent {
static propTypes = {
heading: PropTypes.object.isRequired,
id: PropTypes.string,
};
render() {
const { heading, id } = this.props;
return (
<span id={id} className='column-settings-heading'>{heading}</span>
)
}
}

View File

@@ -1,7 +0,0 @@
.column-settings-heading {
display: block;
color: $darker-text-color;
cursor: default;
font-weight: 500;
margin-bottom: 10px;
}

View File

@@ -1 +0,0 @@
export { default } from './column_settings_heading';

View File

@@ -1,19 +0,0 @@
.error-boundary {
&__container {
@include margin-center(auto);
}
span {
display: block;
text-align: center;
color: $secondary-text-color;
}
&__link {
display: block;
text-align: center;
color: $gab-brand-default;
@include margin-center(15px);
}
}

View File

@@ -1 +0,0 @@
export { default } from './error_boundary';

View File

@@ -1,6 +1,6 @@
import { is } from 'immutable';
import scheduleIdleTask from '../../utils/schedule_idle_task';
import getRectFromEntry from '../../utils/get_rect_from_entry';
import scheduleIdleTask from '../utils/schedule_idle_task';
import getRectFromEntry from '../utils/get_rect_from_entry';
// Diff these props in the "rendered" state
const updateOnPropsForRendered = ['id', 'index', 'listLength'];

View File

@@ -1 +0,0 @@
export { default } from './intersection_observer_article';

View File

@@ -1,4 +0,0 @@
article {
// TEMPORARY - content of columns may be significantly altered
// background: $gab-background-container;
}

View File

@@ -1,11 +1,11 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import classNames from 'classnames';
import StatusContent from '../../status_content';
import Avatar from '../../avatar';
import RelativeTimestamp from '../../relative_timestamp';
import DisplayName from '../../display_name';
import IconButton from '../../icon_button';
import StatusContent from '../status_content';
import Avatar from '../avatar';
import RelativeTimestamp from '../relative_timestamp';
import DisplayName from '../display_name';
import IconButton from '../icon_button';
export default class ActionsModal extends ImmutablePureComponent {

View File

@@ -1,12 +1,12 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { defineMessages, injectIntl } from 'react-intl';
import Button from '../../button';
import StatusContent from '../../status_content';
import Avatar from '../../avatar';
import RelativeTimestamp from '../../relative_timestamp';
import DisplayName from '../../display_name';
import Icon from '../../icon';
import Button from '../button';
import StatusContent from '../status_content';
import Avatar from '../avatar';
import RelativeTimestamp from '../relative_timestamp';
import DisplayName from '../display_name';
import Icon from '../icon';
const messages = defineMessages({
cancel_reblog: { id: 'status.cancel_reblog_private', defaultMessage: 'Un-repost' },

View File

@@ -1,9 +1,9 @@
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { openModal } from '../../../actions/modal';
import { cancelReplyCompose } from '../../../actions/compose';
import ModalLayout from '../modal_layout';
import TimelineComposeBlock from '../../timeline_compose_block';
import { openModal } from '../../actions/modal';
import { cancelReplyCompose } from '../../actions/compose';
import ModalLayout from './modal_layout';
import TimelineComposeBlock from '../timeline_compose_block';
const messages = defineMessages({
confirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },

View File

@@ -1,7 +1,9 @@
import { injectIntl, FormattedMessage } from 'react-intl';
import Button from '../../button';
import { injectIntl, FormattedMessage } from 'react-intl'
import ModalLayout from './modal_layout'
import Button from '../button'
export default @injectIntl
export default
@injectIntl
class ConfirmationModal extends PureComponent {
static propTypes = {
@@ -13,34 +15,34 @@ class ConfirmationModal extends PureComponent {
onSecondary: PropTypes.func,
intl: PropTypes.object.isRequired,
onCancel: PropTypes.func,
};
}
componentDidMount() {
this.button.focus();
this.button.focus()
}
handleClick = () => {
this.props.onClose();
this.props.onConfirm();
this.props.onClose()
this.props.onConfirm()
}
handleSecondary = () => {
this.props.onClose();
this.props.onSecondary();
this.props.onClose()
this.props.onSecondary()
}
handleCancel = () => {
const {onClose, onCancel} = this.props;
onClose();
if (onCancel) onCancel();
const {onClose, onCancel} = this.props
onClose()
if (onCancel) onCancel()
}
setRef = (c) => {
this.button = c;
this.button = c
}
render () {
const { message, confirm, secondary } = this.props;
const { message, confirm, secondary } = this.props
return (
<div className='modal-root__modal confirmation-modal'>
@@ -58,7 +60,7 @@ class ConfirmationModal extends PureComponent {
<Button text={confirm} onClick={this.handleClick} ref={this.setRef} />
</div>
</div>
);
)
}
}

View File

@@ -1,6 +1,6 @@
import ImmutablePureComponent from 'react-immutable-pure-component';
import { defineMessages, injectIntl } from 'react-intl';
import api from '../../../api'
import api from '../../api'
const messages = defineMessages({
embed: { id: 'status.embed', defaultMessage: 'Embed' },

View File

@@ -1,9 +1,9 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import classNames from 'classnames';
import { changeUploadCompose } from '../../../actions/compose';
import { getPointerPosition } from '../../../utils/element_position';
import ImageLoader from '../../image_loader';
import { changeUploadCompose } from '../../actions/compose';
import { getPointerPosition } from '../../utils/element_position';
import ImageLoader from '../image_loader';
const mapStateToProps = (state, { id }) => ({
media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id),

View File

@@ -1,27 +0,0 @@
import ActionsModal from './actions_modal/actions_modal';
import BoostModal from './boost_modal/boost_modal';
import ComposeModal from './compose_modal/compose_modal';
import ConfirmationModal from './confirmation_modal/confirmation_modal';
import EmbedModal from './embed_modal/embed_modal';
import FocalPointModal from './focal_point_modal/focal_point_modal';
import HotkeysModal from './hotkeys_modal';
import MediaModal from './media_modal/media_modal';
import MuteModal from './mute_modal/mute_modal';
import ReportModal from './report_modal/report_modal';
import UnauthorizedModal from './unauthorized_modal';
import VideoModal from './video_modal/video_modal';
export {
ActionsModal,
BoostModal,
ComposeModal,
ConfirmationModal,
EmbedModal,
FocalPointModal,
HotkeysModal,
MediaModal,
MuteModal,
ReportModal,
UnauthorizedModal,
VideoModal,
};

View File

@@ -3,11 +3,11 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ReactSwipeableViews from 'react-swipeable-views';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Video from '../../../features/video';
import ExtendedVideoPlayer from '../../extended_video_player';
import IconButton from '../../icon_button';
import ImageLoader from '../../image_loader';
import Icon from '../../icon';
import Video from '../../features/video';
import ExtendedVideoPlayer from '../extended_video_player';
import IconButton from '../icon_button';
import ImageLoader from '../image_loader';
import Icon from '../icon';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },

View File

@@ -1,18 +1,17 @@
import ModalBase from './modal_base'
import Bundle from '../../features/ui/util/bundle'
import BundleModalError from '../bundle_modal_error'
import {
ActionsModal,
MediaModal,
VideoModal,
BoostModal,
ConfirmationModal,
FocalPointModal,
HotkeysModal,
ComposeModal,
UnauthorizedModal,
ProUpgradeModal,
} from '.'
import ActionsModal from './actions_modal'
import MediaModal from './media_modal'
// import VideoModal from './video_modal'
import BoostModal from './boost_modal'
import ConfirmationModal from './confirmation_modal'
import FocalPointModal from './focal_point_modal'
import HotkeysModal from './hotkeys_modal'
import ComposeModal from './compose_modal'
import UnauthorizedModal from './unauthorized_modal'
import ProUpgradeModal from './pro_upgrade_modal'
import ModalLoading from './modal_loading'
import {
MuteModal,
ReportModal,
@@ -21,11 +20,10 @@ import {
ListAdder,
StatusRevisionModal,
} from '../../features/ui/util/async-components'
import ModalLoading from '../modal_loading'
const MODAL_COMPONENTS = {
'MEDIA': () => Promise.resolve({ default: MediaModal }),
'VIDEO': () => Promise.resolve({ default: VideoModal }),
// 'VIDEO': () => Promise.resolve({ default: VideoModal }),
'BOOST': () => Promise.resolve({ default: BoostModal }),
'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }),
'MUTE': MuteModal,

View File

@@ -1,9 +1,9 @@
import { injectIntl, defineMessages } from 'react-intl';
import { closeModal } from '../../../actions/modal';
import { muteAccount } from '../../../actions/accounts';
import { toggleHideNotifications } from '../../../actions/mutes';
import ToggleSwitch from '../../toggle_switch';
import Button from '../../button';
import { closeModal } from '../../actions/modal';
import { muteAccount } from '../../actions/accounts';
import { toggleHideNotifications } from '../../actions/mutes';
import ToggleSwitch from '../toggle_switch';
import Button from '../button';
const messages = defineMessages({
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },

View File

@@ -1,63 +1,63 @@
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { me } from '../initial_state';
import IconButton from './icon_button';
import Icon from './icon';
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import Button from '../button'
import Text from '../text'
import ModalLayout from './modal_layout'
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
});
const mapStateToProps = state => {
return {
account: state.getIn(['accounts', me]),
};
};
title: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
text: { id: 'pro_upgrade_modal.text', defaultMessage: 'Gab is fully funded by people like you. Please consider supporting us on our mission to defend free expression online for all people.' },
benefits: { id: 'pro_upgrade_modal.benefits', defaultMessage: 'Here are just some of the benefits that thousands of GabPRO members receive:' },
})
export default
@injectIntl
class ProUpgradeModal extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired,
};
}
onClickClose = () => {
this.props.onClose('PRO_UPGRADE');
};
render () {
const { intl } = this.props;
render() {
const { intl } = this.props
return (
<div className='modal-root__modal compose-modal pro-upgrade-modal'>
<div className='compose-modal__header'>
<h3 className='compose-modal__header__title'><FormattedMessage id='promo.gab_pro' defaultMessage='Upgrade to GabPRO' /></h3>
<IconButton className='compose-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={this.onClickClose} size={20} />
<ModalLayout title={intl.formatMessage(messages.title)}>
<div>
<Text>
{intl.formatMessage(messages.text)}
</Text>
<Text>
{intl.formatMessage(messages.benefits)}
</Text>
</div>
<div className='compose-modal__content pro-upgrade-modal__content'>
<div>
<span className="pro-upgrade-modal__text">
<FormattedMessage id='pro_upgrade_modal.text' defaultMessage='Gab is fully funded by people like you. Please consider supporting us on our mission to defend free expression online for all people.' />
<FormattedMessage id='pro_upgrade_modal.benefits' defaultMessage='Here are just some of the benefits that thousands of GabPRO members receive:' />
</span>
<ul className="pro-upgrade-modal__list">
<li>Schedule Posts</li>
<li>Get Verified</li>
<li>Create Groups</li>
<li>Larger Video and Image Uploads</li>
<li>Receive the PRO Badge</li>
<li>Remove in-feed promotions</li>
<li>More value being added daily!</li>
</ul>
<a href='https://pro.gab.com' className='pro-upgrade-modal__button button'>
<Icon id='arrow-up' fixedWidth/>
<FormattedMessage id='promo.gab_pro' defaultMessage='Upgrade to GabPRO' />
</a>
</div>
</div>
</div>
);
<ul>
<li>
<Text>Schedule Posts</Text>
</li>
<li>
<Text>Get Verified</Text>
</li>
<li>
<Text>Create Groups</Text>
</li>
<li>
<Text>Larger Video and Image Uploads</Text>
</li>
<li>
<Text>Receive the PRO Badge</Text>
</li>
<li>
<Text>Remove in-feed promotions</Text>
</li>
</ul>
<Button icon='pro' href='https://pro.gab.com'>
{intl.formatMessage(messages.title)}
</Button>
</ModalLayout>
)
}
}
export default injectIntl(connect(mapStateToProps)(ProUpgradeModal));

View File

@@ -2,13 +2,13 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl } from 'react-intl';
import { OrderedSet } from 'immutable';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { changeReportComment, changeReportForward, submitReport } from '../../../actions/reports';
import { expandAccountTimeline } from '../../../actions/timelines';
import { makeGetAccount } from '../../../selectors';
import StatusCheckBox from '../../status_check_box';
import ToggleSwitch from '../../toggle_switch';
import Button from '../../button';
import IconButton from '../../icon_button';
import { changeReportComment, changeReportForward, submitReport } from '../../actions/reports';
import { expandAccountTimeline } from '../../actions/timelines';
import { makeGetAccount } from '../../selectors';
import StatusCheckBox from '../status_check_box';
import ToggleSwitch from '../toggle_switch';
import Button from '../button';
import IconButton from '../icon_button';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },

View File

@@ -2,8 +2,8 @@
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import StatusRevisionListContainer from '../../../containers/status_revision_list_container';
import IconButton from '../../../components/icon_button';
import StatusRevisionListContainer from '../../containers/status_revision_list_container';
import IconButton from '../icon_button';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },

View File

@@ -1,7 +1,7 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { FormattedMessage } from 'react-intl';
import Video from '../../../features/video';
import Video from '../../features/video';
export const previewState = 'previewVideoModal';

View File

@@ -1 +0,0 @@
export { default } from './modal_loading';

View File

@@ -1,9 +1,9 @@
import { throttle } from 'lodash';
import { List as ImmutableList } from 'immutable';
import IntersectionObserverArticleContainer from '../../containers/intersection_observer_article_container';
import IntersectionObserverWrapper from '../../features/ui/util/intersection_observer_wrapper';
import ColumnIndicator from '../column_indicator';
import LoadMore from '../load_more';
import IntersectionObserverArticleContainer from '../containers/intersection_observer_article_container';
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper';
import ColumnIndicator from './column_indicator';
import LoadMore from './load_more';
const MOUSE_IDLE_DELAY = 300;

View File

@@ -1 +0,0 @@
export { default } from './scrollable_list';

View File

@@ -1,6 +0,0 @@
.scrollable-list {
&--flex {
display: flex;
flex-direction: column;
}
}

View File

@@ -1 +0,0 @@
export { default } from './section_headline_bar';

View File

@@ -1,62 +0,0 @@
import { NavLink } from 'react-router-dom';
import classNames from 'classnames';
import Icon from '../icon';
class SectionHeadlineBarItem extends PureComponent {
static propTypes = {
to: PropTypes.string,
icon: PropTypes.string,
className: PropTypes.string,
onClick: PropTypes.func,
title: PropTypes.oneOfType([
PropTypes.string,
PropTypes.node,
]),
exact: PropTypes.bool,
};
render() {
const { to, title, icon, className, onClick, exact } = this.props;
const classes = classNames('section-header-bar__item', className);
if (to) {
return (
<NavLink className={classes} exact={exact} to={to}>{title}</NavLink>
)
} else if (icon) {
return (
<button className={classes} onClick={onClick} title={title}>
<Icon id={icon} fixedWidth />
</button>
)
}
return (
<button className={classes} onClick={onClick}>{title}</button>
)
}
};
export default class SectionHeadlineBar extends PureComponent {
static propTypes = {
items: PropTypes.array.isRequired,
className: PropTypes.string,
};
render() {
const { items, className } = this.props;
const classes = classNames('section-headline-bar', className);
return (
<div className={classes}>
{
items.forEach((item, i) => (
<SectionHeadlineBarItem key={`shbi-${i}`} {...item} />
))
}
</div>
)
}
}

View File

@@ -1,58 +0,0 @@
.section-headline-bar {
background: darken($ui-base-color, 4%);
border-bottom: 1px solid lighten($ui-base-color, 8%);
cursor: default;
display: flex;
flex-shrink: 0;
button {
background: darken($ui-base-color, 4%);
border: 0;
margin: 0;
}
button,
a {
display: block;
flex: 1 1 auto;
color: $secondary-text-color;
padding: 15px 0;
text-decoration: none;
position: relative;
@include text-sizing(14px, 500, 1, center);
&.active {
color: $primary-text-color;
&::before,
&::after {
bottom: 0;
left: 50%;
transform: translateX(-50%);
border-style: solid;
border-width: 0 10px 10px;
border-color: transparent transparent lighten($ui-base-color, 8%);
@include pseudo;
@include size(0);
}
&::after {
bottom: -1px;
border-color: transparent transparent $ui-base-color;
}
}
}
}
.account-section-headline {
button,
a {
flex: none;
padding: 18px 15px;
@include text-sizing(16px, 600);
}
}

View File

@@ -1,6 +1,6 @@
import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import { shortNumberFormat } from '../../utils/numbers';
import { shortNumberFormat } from '../utils/numbers';
export default class TimelineQueueButtonHeader extends PureComponent {

View File

@@ -1 +0,0 @@
export { default } from './timeline_queue_button_header';

View File

@@ -1,29 +0,0 @@
.timeline-queue-header {
display: block;
width: 100%;
max-height: 0px;
position: relative;
background-color: darken($ui-base-color, 8%);
border-bottom: 1px solid;
border-top: 1px solid;
border-color: darken($ui-base-color, 4%);
transition: max-height 2.5s ease;
overflow: hidden;
&--extended {
max-height: 46px;
}
&__btn {
display: block;
cursor: pointer;
color: $secondary-text-color;
@include size(100%);
@include text-sizing(14px, 400, 46px, center);
span {
height: 46px;
}
}
}