diff options
Diffstat (limited to 'app/javascript/flavours/glitch/features')
6 files changed, 146 insertions, 8 deletions
diff --git a/app/javascript/flavours/glitch/features/compose/components/action_bar.js b/app/javascript/flavours/glitch/features/compose/components/action_bar.js new file mode 100644 index 000000000..267c0ba69 --- /dev/null +++ b/app/javascript/flavours/glitch/features/compose/components/action_bar.js @@ -0,0 +1,66 @@ +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import PropTypes from 'prop-types'; +import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; +import { defineMessages, injectIntl } from 'react-intl'; +import { preferencesLink, profileLink } from 'flavours/glitch/utils/backend_links'; + +const messages = defineMessages({ + edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, + pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned posts' }, + preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, + follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, + favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' }, + lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' }, + blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, + domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' }, + mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, + filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' }, + logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' }, + bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' }, +}); + +export default @injectIntl +class ActionBar extends React.PureComponent { + + static propTypes = { + account: ImmutablePropTypes.map.isRequired, + onLogout: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + handleLogout = () => { + this.props.onLogout(); + } + + render () { + const { intl } = this.props; + + let menu = []; + + menu.push({ text: intl.formatMessage(messages.edit_profile), href: profileLink }); + menu.push({ text: intl.formatMessage(messages.preferences), href: preferencesLink }); + menu.push({ text: intl.formatMessage(messages.pins), to: '/pinned' }); + menu.push(null); + menu.push({ text: intl.formatMessage(messages.follow_requests), to: '/follow_requests' }); + menu.push({ text: intl.formatMessage(messages.favourites), to: '/favourites' }); + menu.push({ text: intl.formatMessage(messages.bookmarks), to: '/bookmarks' }); + menu.push({ text: intl.formatMessage(messages.lists), to: '/lists' }); + menu.push(null); + menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' }); + menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' }); + menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' }); + menu.push({ text: intl.formatMessage(messages.filters), href: '/filters' }); + menu.push(null); + menu.push({ text: intl.formatMessage(messages.logout), action: this.handleLogout }); + + return ( + <div className='compose__action-bar'> + <div className='compose__action-bar-dropdown'> + <DropdownMenuContainer items={menu} icon='ellipsis-v' size={18} direction='right' /> + </div> + </div> + ); + } + +} diff --git a/app/javascript/flavours/glitch/features/compose/components/navigation_bar.js b/app/javascript/flavours/glitch/features/compose/components/navigation_bar.js index ba73ed553..1a68f1e12 100644 --- a/app/javascript/flavours/glitch/features/compose/components/navigation_bar.js +++ b/app/javascript/flavours/glitch/features/compose/components/navigation_bar.js @@ -1,5 +1,7 @@ import React from 'react'; +import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import ActionBar from './action_bar'; import Avatar from 'flavours/glitch/components/avatar'; import Permalink from 'flavours/glitch/components/permalink'; import { FormattedMessage } from 'react-intl'; @@ -10,11 +12,12 @@ export default class NavigationBar extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map.isRequired, + onLogout: PropTypes.func.isRequired, }; render () { return ( - <div className='drawer--account'> + <div className='navigation-bar'> <Permalink className='avatar' href={this.props.account.get('url')} to={`/@${this.props.account.get('acct')}`}> <span style={{ display: 'none' }}>{this.props.account.get('acct')}</span> <Avatar account={this.props.account} size={48} /> @@ -28,11 +31,16 @@ export default class NavigationBar extends ImmutablePureComponent { { profileLink !== undefined && ( <a className='edit' - href={ profileLink } + href={profileLink} ><FormattedMessage id='navigation_bar.edit_profile' defaultMessage='Edit profile' /></a> )} </div> + + <div className='navigation-bar__actions'> + <ActionBar account={this.props.account} onLogout={this.props.onLogout} /> + </div> </div> ); - }; + } + } diff --git a/app/javascript/flavours/glitch/features/compose/containers/navigation_container.js b/app/javascript/flavours/glitch/features/compose/containers/navigation_container.js index 0e1400261..89036adcd 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/navigation_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/navigation_container.js @@ -1,11 +1,30 @@ import { connect } from 'react-redux'; +import { defineMessages, injectIntl } from 'react-intl'; import NavigationBar from '../components/navigation_bar'; +import { logOut } from 'flavours/glitch/utils/log_out'; +import { openModal } from 'flavours/glitch/actions/modal'; import { me } from 'flavours/glitch/initial_state'; +const messages = defineMessages({ + logoutMessage: { id: 'confirmations.logout.message', defaultMessage: 'Are you sure you want to log out?' }, + logoutConfirm: { id: 'confirmations.logout.confirm', defaultMessage: 'Log out' }, +}); + const mapStateToProps = state => { return { account: state.getIn(['accounts', me]), }; }; -export default connect(mapStateToProps)(NavigationBar); +const mapDispatchToProps = (dispatch, { intl }) => ({ + onLogout () { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.logoutMessage), + confirm: intl.formatMessage(messages.logoutConfirm), + closeWhenConfirm: false, + onConfirm: () => logOut(), + })); + }, +}); + +export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(NavigationBar)); diff --git a/app/javascript/flavours/glitch/features/status/components/detailed_status.js b/app/javascript/flavours/glitch/features/status/components/detailed_status.js index 46770930f..7d2c2aace 100644 --- a/app/javascript/flavours/glitch/features/status/components/detailed_status.js +++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.js @@ -34,6 +34,7 @@ class DetailedStatus extends ImmutablePureComponent { onOpenMedia: PropTypes.func.isRequired, onOpenVideo: PropTypes.func.isRequired, onToggleHidden: PropTypes.func, + onTranslate: PropTypes.func.isRequired, expanded: PropTypes.bool, measureHeight: PropTypes.bool, onHeightChange: PropTypes.func, @@ -112,6 +113,11 @@ class DetailedStatus extends ImmutablePureComponent { window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); } + handleTranslate = () => { + const { onTranslate, status } = this.props; + onTranslate(status); + } + render () { const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status; const { expanded, onToggleHidden, settings, usingPiP, intl } = this.props; @@ -305,6 +311,7 @@ class DetailedStatus extends ImmutablePureComponent { expanded={expanded} collapsed={false} onExpandedToggle={onToggleHidden} + onTranslate={this.handleTranslate} parseClick={this.parseClick} onUpdate={this.handleChildUpdate} tagLinks={settings.get('tag_misleading_links')} diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index aaa9c7928..e190652b0 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -33,7 +33,9 @@ import { deleteStatus, editStatus, hideStatus, - revealStatus + revealStatus, + translateStatus, + undoStatusTranslation, } from 'flavours/glitch/actions/statuses'; import { initMuteModal } from 'flavours/glitch/actions/mutes'; import { initBlockModal } from 'flavours/glitch/actions/blocks'; @@ -437,6 +439,16 @@ class Status extends ImmutablePureComponent { this.setState({ isExpanded: !isExpanded, threadExpanded: !isExpanded }); } + handleTranslate = status => { + const { dispatch } = this.props; + + if (status.get('translation')) { + dispatch(undoStatusTranslation(status.get('id'))); + } else { + dispatch(translateStatus(status.get('id'))); + } + } + handleBlockClick = (status) => { const { dispatch } = this.props; const account = status.get('account'); @@ -666,6 +678,7 @@ class Status extends ImmutablePureComponent { onOpenMedia={this.handleOpenMedia} expanded={isExpanded} onToggleHidden={this.handleToggleHidden} + onTranslate={this.handleTranslate} domain={domain} showMedia={this.state.showMedia} onToggleMediaVisibility={this.handleToggleMediaVisibility} diff --git a/app/javascript/flavours/glitch/features/ui/components/header.js b/app/javascript/flavours/glitch/features/ui/components/header.js index 891f7fc07..d9ad94961 100644 --- a/app/javascript/flavours/glitch/features/ui/components/header.js +++ b/app/javascript/flavours/glitch/features/ui/components/header.js @@ -7,6 +7,7 @@ import Avatar from 'flavours/glitch/components/avatar'; import Permalink from 'flavours/glitch/components/permalink'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; +import { openModal } from 'flavours/glitch/actions/modal'; const Account = connect(state => ({ account: state.getIn(['accounts', me]), @@ -16,7 +17,14 @@ const Account = connect(state => ({ </Permalink> )); -export default @withRouter +const mapDispatchToProps = (dispatch) => ({ + openClosedRegistrationsModal() { + dispatch(openModal('CLOSED_REGISTRATIONS')); + }, +}); + +export default @connect(null, mapDispatchToProps) +@withRouter class Header extends React.PureComponent { static contextTypes = { @@ -24,12 +32,13 @@ class Header extends React.PureComponent { }; static propTypes = { + openClosedRegistrationsModal: PropTypes.func, location: PropTypes.object, }; render () { const { signedIn } = this.context.identity; - const { location } = this.props; + const { location, openClosedRegistrationsModal } = this.props; let content; @@ -41,10 +50,26 @@ class Header extends React.PureComponent { </> ); } else { + let signupButton; + + if (registrationsOpen) { + signupButton = ( + <a href='/auth/sign_up' className='button button-tertiary'> + <FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' /> + </a> + ); + } else { + signupButton = ( + <button className='button button-tertiary' onClick={openClosedRegistrationsModal}> + <FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' /> + </button> + ); + } + content = ( <> <a href='/auth/sign_in' className='button'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a> - <a href={registrationsOpen ? '/auth/sign_up' : 'https://joinmastodon.org/servers'} className='button button-tertiary'><FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' /></a> + {signupButton} </> ); } |