Merge branch 'feature/frontend_refactor' of https://code.gab.com/gab/social/gab-social into feature/frontend_refactor

This commit is contained in:
Alex Gleason 2020-03-12 12:36:07 -05:00
commit 817063fd14
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
23 changed files with 152 additions and 190 deletions

View File

@ -3,7 +3,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
import { debounce } from 'lodash' import { debounce } from 'lodash'
import classNames from 'classnames/bind' import classNames from 'classnames/bind'
import { openPopover, closePopover } from '../actions/popover' import { openPopover, closePopover } from '../actions/popover'
import Badge from './badge'
import Icon from './icon' import Icon from './icon'
const cx = classNames.bind(_s) const cx = classNames.bind(_s)

View File

@ -18,6 +18,7 @@ export default class Input extends PureComponent {
onClear: PropTypes.func, onClear: PropTypes.func,
title: PropTypes.string, title: PropTypes.string,
small: PropTypes.bool, small: PropTypes.bool,
readOnly: PropTypes.string,
} }
render() { render() {
@ -32,7 +33,8 @@ export default class Input extends PureComponent {
onBlur, onBlur,
onClear, onClear,
title, title,
small small,
readOnly
} = this.props } = this.props
const inputClasses = cx({ const inputClasses = cx({
@ -42,9 +44,12 @@ export default class Input extends PureComponent {
lineHeight125: 1, lineHeight125: 1,
displayBlock: 1, displayBlock: 1,
py10: 1, py10: 1,
backgroundTransparent: 1, backgroundTransparent: !readOnly,
backgroundSubtle2: readOnly,
colorSecondary: readOnly,
fontSize15PX: 1, fontSize15PX: 1,
flexGrow1: 1, flexGrow1: 1,
circle: 1,
px5: !!prependIcon, px5: !!prependIcon,
pl15: !prependIcon, pl15: !prependIcon,
pr15: !hasClear, pr15: !hasClear,
@ -75,6 +80,7 @@ export default class Input extends PureComponent {
onKeyUp={onKeyUp} onKeyUp={onKeyUp}
onFocus={onFocus} onFocus={onFocus}
onBlur={onBlur} onBlur={onBlur}
readOnly={readOnly}
/> />
{ {

View File

@ -51,7 +51,8 @@ class ComposeModal extends ImmutablePureComponent {
return ( return (
<ModalLayout <ModalLayout
noPadding noPadding
title={intl.formatMessage(messages.title)} onClose={this.onClickClose} title={intl.formatMessage(messages.title)}
onClose={this.onClickClose}
> >
<TimelineComposeBlock modal /> <TimelineComposeBlock modal />
</ModalLayout> </ModalLayout>

View File

@ -1,18 +0,0 @@
.compose-modal {
width: 600px;
&__content {
.timeline-compose-block {
background: transparent !important;
width: 100%;
padding: 10px 5px;
margin-bottom: 0;
.compose-form {
display: flex;
flex-direction: column;
max-height: 100%;
}
}
}
}

View File

@ -1,12 +1,17 @@
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component'
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl'
import api from '../../api' import api from '../../api'
import ModalLayout from './modal_layout'
import Divider from '../divider'
import Icon from '../icon'
import Input from '../input'
import Text from '../text'
const messages = defineMessages({ const messages = defineMessages({
embed: { id: 'status.embed', defaultMessage: 'Embed' }, embed: { id: 'status.embed', defaultMessage: 'Embed' },
instructions: { id: 'embed.instructions', defaultMessage: 'Embed this status on your website by copying the code below.' }, instructions: { id: 'embed.instructions', defaultMessage: 'Embed this status on your website by copying the code below.' },
preview: { id: 'embed.preview', defaultMessage: 'Here is what it will look like:' }, preview: { id: 'embed.preview', defaultMessage: 'Here is what it will look like:' },
}); })
export default export default
@injectIntl @injectIntl
@ -22,72 +27,82 @@ class EmbedModal extends ImmutablePureComponent {
state = { state = {
loading: false, loading: false,
oembed: null, oembed: null,
}; }
componentDidMount() { componentDidMount() {
const { url } = this.props; const { url } = this.props
this.setState({ loading: true }); this.setState({ loading: true })
api().post('/api/web/embed', { url }).then(res => { api().post('/api/web/embed', { url }).then(res => {
this.setState({ loading: false, oembed: res.data }); this.setState({ loading: false, oembed: res.data })
const iframeDocument = this.iframe.contentWindow.document; const iframeDocument = this.iframe.contentWindow.document
iframeDocument.open(); iframeDocument.open()
iframeDocument.write(res.data.html); iframeDocument.write(res.data.html)
iframeDocument.close(); iframeDocument.close()
iframeDocument.body.style.margin = 0; iframeDocument.body.style.margin = 0
this.iframe.width = iframeDocument.body.scrollWidth; this.iframe.width = iframeDocument.body.scrollWidth
this.iframe.height = iframeDocument.body.scrollHeight; this.iframe.height = iframeDocument.body.scrollHeight
}).catch(error => { }).catch(error => {
this.props.onError(error); this.props.onError(error)
}); })
} }
setIframeRef = c => { setIframeRef = c => {
this.iframe = c; this.iframe = c
} }
handleTextareaClick = (e) => { handleTextareaClick = (e) => {
e.target.select(); e.target.select()
} }
render() { render() {
const { oembed, intl } = this.state; const { intl } = this.props
const { oembed } = this.state
return ( return (
<div className='modal-root__modal embed-modal'> <ModalLayout title={intl.formatMessage(messages.embed)}>
<h4>{intl.formatMessage(messages.embed)}</h4> <div className={_s.default}>
<Text className={_s.my10}>
<div className='embed-modal__container'>
<p className='hint'>
{intl.formatMessage(messages.instructions)} {intl.formatMessage(messages.instructions)}
</p> </Text>
<input <div className={[_s.default, _s.mb10].join(' ')}>
<Input
readOnly
type='text' type='text'
className='embed-modal__html' className='embed-modal__html'
readOnly
value={oembed && oembed.html || ''} value={oembed && oembed.html || ''}
onClick={this.handleTextareaClick} onClick={this.handleTextareaClick}
/> />
</div>
<p className='hint'> <Divider />
<Text className={_s.mb10}>
{intl.formatMessage(messages.preview)} {intl.formatMessage(messages.preview)}
</p> </Text>
<div className={[_s.default, _s.width100PC, _s.backgroundSubtle, _s.height220PX, _s.alignItemsCenter, _s.justifyContentCenter].join(' ')}>
<iframe <iframe
className='embed-modal__iframe' className={[_s.default, _s.width100PC, _s.height100PC, _s.z2].join(' ')}
frameBorder='0' frameBorder='0'
ref={this.setIframeRef} ref={this.setIframeRef}
sandbox='allow-same-origin' sandbox='allow-same-origin'
title='preview' title='preview'
/> />
{
!oembed &&
<Icon id='loading' height='34px' width='34px' className={[_s.positionAbsolute, _s.z3].join(' ')} />
}
</div> </div>
</div> </div>
); </ModalLayout>
)
} }
} }

View File

@ -1,57 +0,0 @@
.embed-modal {
@include max-size(80vw, 80vh);
h4 {
padding: 30px;
@include text-sizing(16px, 500, 1, center);
}
.embed-modal__container {
padding: 10px;
.hint {
margin-bottom: 15px;
}
.embed-modal__html {
outline: 0;
box-sizing: border-box;
display: block;
width: 100%;
border: none;
padding: 10px;
font-family: $font-monospace, monospace;
background: $ui-base-color;
color: $primary-text-color;
font-size: 14px;
margin: 0;
margin-bottom: 15px;
&::-moz-focus-inner {
border: 0;
}
&::-moz-focus-inner,
&:focus,
&:active {
outline: 0 !important;
}
&:focus {
background: lighten($ui-base-color, 4%);
}
@include breakpoint(sm) {
font-size: 16px;
}
}
.embed-modal__iframe {
width: 400px;
max-width: 100%;
overflow: hidden;
border: 0;
}
}
}

View File

@ -73,7 +73,7 @@ class MuteModal extends PureComponent {
} }
render () { render () {
const { account, notifications } = this.props; const { account, notifications, intl } = this.props;
return ( return (
<div className='modal-root__modal mute-modal'> <div className='modal-root__modal mute-modal'>

View File

@ -1,22 +0,0 @@
.setting-text {
color: $darker-text-color;
background: transparent;
border: none;
border-bottom: 2px solid $ui-primary-color;
box-sizing: border-box;
display: block;
font-family: inherit;
margin-bottom: 10px;
padding: 7px 0;
width: 100%;
&:focus,
&:active {
color: $primary-text-color;
border-bottom-color: $highlight-text-color;
}
@include breakpoint(sm) {
font-size: 16px;
}
}

View File

@ -1,13 +1,12 @@
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; 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 StatusRevisionListContainer from '../../containers/status_revision_list_container'
import StatusRevisionListContainer from '../../containers/status_revision_list_container'; import IconButton from '../icon_button'
import IconButton from '../icon_button';
const messages = defineMessages({ const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' }, close: { id: 'lightbox.close', defaultMessage: 'Close' },
}); })
export default export default
@injectIntl @injectIntl
@ -17,16 +16,18 @@ class StatusRevisionModal extends ImmutablePureComponent {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
status: ImmutablePropTypes.map.isRequired status: ImmutablePropTypes.map.isRequired
}; }
render() { render() {
const { intl, onClose, status } = this.props; const { intl, onClose, status } = this.props
return ( return (
<div className='modal-root__modal status-revisions-root'> <div className='modal-root__modal status-revisions-root'>
<div className='status-revisions'> <div className='status-revisions'>
<div className='status-revisions__header'> <div className='status-revisions__header'>
<h3 className='status-revisions__header__title'><FormattedMessage id='status_revisions.heading' defaultMessage='Revision History' /></h3> <h3 className='status-revisions__header__title'>
<FormattedMessage id='status_revisions.heading' defaultMessage='Revision History' />
</h3>
<IconButton className='status-revisions__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={20} /> <IconButton className='status-revisions__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={20} />
</div> </div>
<div className='status-revisions__content'> <div className='status-revisions__content'>
@ -34,6 +35,6 @@ class StatusRevisionModal extends ImmutablePureComponent {
</div> </div>
</div> </div>
</div> </div>
); )
} }
} }

View File

@ -1,5 +0,0 @@
.video-modal {
position: relative;
@include max-size(100vw, 100vh);
}

View File

@ -45,7 +45,7 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(closeSidebar()) dispatch(closeSidebar())
}, },
onOpenComposeModal() { onOpenComposeModal() {
dispatch(openModal('PRO_UPGRADE')) dispatch(openModal('COMPOSE'))
}, },
}) })

View File

@ -25,6 +25,12 @@ class GroupPage extends ImmutablePureComponent {
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
} }
componentDidMount() {
const { group } = this.props
const groupTitle = !group ? '...' : group.get('title')
document.title = `Group / ${groupTitle} - Gab`
}
componentWillMount() { componentWillMount() {
const { params: { id }, dispatch } = this.props const { params: { id }, dispatch } = this.props

View File

@ -5,6 +5,10 @@ import DefaultLayout from '../layouts/default_layout'
export default class GroupsPage extends PureComponent { export default class GroupsPage extends PureComponent {
componentDidMount() {
document.title = 'Groups - Gab'
}
handleClickNewList () { handleClickNewList () {
console.log("handleClickNewList") console.log("handleClickNewList")
} }

View File

@ -12,6 +12,10 @@ import Divider from '../components/divider'
export default class HomePage extends PureComponent { export default class HomePage extends PureComponent {
componentDidMount() {
document.title = '(1) Home - Gab'
}
handleEditHomeTimeline () { handleEditHomeTimeline () {
console.log("handleEditHomeTimeline") console.log("handleEditHomeTimeline")
} }

View File

@ -17,6 +17,12 @@ class ListPage extends ImmutablePureComponent {
list: ImmutablePropTypes.map, list: ImmutablePropTypes.map,
}; };
componentDidMount() {
const { list } = this.props
const listTitle = !list ? '...' : list.get('title')
document.title = `List / ${listTitle} - Gab`
}
handleEditListTimeline () { handleEditListTimeline () {
console.log("handleEditListTimeline") console.log("handleEditListTimeline")
} }

View File

@ -6,6 +6,10 @@ import DefaultLayout from '../layouts/default_layout'
export default class ListsPage extends PureComponent { export default class ListsPage extends PureComponent {
componentDidMount() {
document.title = 'Lists - Gab'
}
handleClickNewList () { handleClickNewList () {
console.log("handleClickNewList") console.log("handleClickNewList")
} }

View File

@ -6,6 +6,11 @@ import TrendsPanel from '../components/panel/trends_panel'
import DefaultLayout from '../layouts/default_layout' import DefaultLayout from '../layouts/default_layout'
export default class NotificationsPage extends PureComponent { export default class NotificationsPage extends PureComponent {
componentDidMount() {
document.title = 'Notifications - Gab'
}
render() { render() {
const { children } = this.props const { children } = this.props

View File

@ -41,6 +41,15 @@ class ProfilePage extends ImmutablePureComponent {
unavailable: PropTypes.bool.isRequired, unavailable: PropTypes.bool.isRequired,
} }
componentDidMount() {
const { account, params: { username } } = this.props
if (!!account) {
document.title = `${account.get('display_name')} (@${username}) - Gab`
} else {
document.title = `@${username} - Gab`
}
}
componentWillMount() { componentWillMount() {
const { dispatch, params: { username } } = this.props const { dispatch, params: { username } } = this.props
dispatch(fetchAccountByUsername(username)) dispatch(fetchAccountByUsername(username))

View File

@ -4,6 +4,10 @@ import SearchFilterPanel from '../components/panel/search_filter_panel'
import SearchLayout from '../layouts/search_layout' import SearchLayout from '../layouts/search_layout'
export default class SearchPage extends PureComponent { export default class SearchPage extends PureComponent {
componentDidMount() {
document.title = `Search - Gab`
}
render() { render() {
const { children } = this.props const { children } = this.props