diff options
Diffstat (limited to 'app/javascript')
-rw-r--r-- | app/javascript/mastodon/components/load_gap.js | 33 | ||||
-rw-r--r-- | app/javascript/mastodon/components/status.js | 2 | ||||
-rw-r--r-- | app/javascript/mastodon/components/status_action_bar.js | 7 | ||||
-rw-r--r-- | app/javascript/mastodon/components/status_list.js | 20 | ||||
-rw-r--r-- | app/javascript/mastodon/containers/status_container.js | 5 | ||||
-rw-r--r-- | app/javascript/mastodon/features/notifications/index.js | 20 | ||||
-rw-r--r-- | app/javascript/mastodon/features/status/components/action_bar.js | 8 | ||||
-rw-r--r-- | app/javascript/mastodon/features/status/index.js | 6 | ||||
-rw-r--r-- | app/javascript/mastodon/locales/defaultMessages.json | 8 | ||||
-rw-r--r-- | app/javascript/mastodon/locales/en.json | 1 | ||||
-rw-r--r-- | app/javascript/mastodon/locales/pl.json | 1 | ||||
-rw-r--r-- | app/javascript/mastodon/reducers/compose.js | 20 | ||||
-rw-r--r-- | app/javascript/styles/mastodon/admin.scss | 35 | ||||
-rw-r--r-- | app/javascript/styles/mastodon/components.scss | 4 |
14 files changed, 123 insertions, 47 deletions
diff --git a/app/javascript/mastodon/components/load_gap.js b/app/javascript/mastodon/components/load_gap.js new file mode 100644 index 000000000..012303ae1 --- /dev/null +++ b/app/javascript/mastodon/components/load_gap.js @@ -0,0 +1,33 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { injectIntl, defineMessages } from 'react-intl'; + +const messages = defineMessages({ + load_more: { id: 'status.load_more', defaultMessage: 'Load more' }, +}); + +@injectIntl +export default class LoadGap extends React.PureComponent { + + static propTypes = { + disabled: PropTypes.bool, + maxId: PropTypes.string, + onClick: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + handleClick = () => { + this.props.onClick(this.props.maxId); + } + + render () { + const { disabled, intl } = this.props; + + return ( + <button className='load-more load-gap' disabled={disabled} onClick={this.handleClick} aria-label={intl.formatMessage(messages.load_more)}> + <i className='fa fa-ellipsis-h' /> + </button> + ); + } + +} diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index a918a94f8..6129b3f1e 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -31,6 +31,8 @@ export default class Status extends ImmutablePureComponent { onFavourite: PropTypes.func, onReblog: PropTypes.func, onDelete: PropTypes.func, + onDirect: PropTypes.func, + onMention: PropTypes.func, onPin: PropTypes.func, onOpenMedia: PropTypes.func, onOpenVideo: PropTypes.func, diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js index e036dc1da..10f34b0c7 100644 --- a/app/javascript/mastodon/components/status_action_bar.js +++ b/app/javascript/mastodon/components/status_action_bar.js @@ -9,6 +9,7 @@ import { me } from '../initial_state'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, + direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' }, mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, block: { id: 'account.block', defaultMessage: 'Block @{name}' }, @@ -41,6 +42,7 @@ export default class StatusActionBar extends ImmutablePureComponent { onFavourite: PropTypes.func, onReblog: PropTypes.func, onDelete: PropTypes.func, + onDirect: PropTypes.func, onMention: PropTypes.func, onMute: PropTypes.func, onBlock: PropTypes.func, @@ -92,6 +94,10 @@ export default class StatusActionBar extends ImmutablePureComponent { this.props.onMention(this.props.status.get('account'), this.context.router.history); } + handleDirectClick = () => { + this.props.onDirect(this.props.status.get('account'), this.context.router.history); + } + handleMuteClick = () => { this.props.onMute(this.props.status.get('account')); } @@ -149,6 +155,7 @@ export default class StatusActionBar extends ImmutablePureComponent { menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); } else { menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); + menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick }); menu.push(null); menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick }); menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); diff --git a/app/javascript/mastodon/components/status_list.js b/app/javascript/mastodon/components/status_list.js index 8c2673f30..c98d4564e 100644 --- a/app/javascript/mastodon/components/status_list.js +++ b/app/javascript/mastodon/components/status_list.js @@ -4,28 +4,10 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import StatusContainer from '../containers/status_container'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import LoadMore from './load_more'; +import LoadGap from './load_gap'; import ScrollableList from './scrollable_list'; import { FormattedMessage } from 'react-intl'; -class LoadGap extends ImmutablePureComponent { - - static propTypes = { - disabled: PropTypes.bool, - maxId: PropTypes.string, - onClick: PropTypes.func.isRequired, - }; - - handleClick = () => { - this.props.onClick(this.props.maxId); - } - - render () { - return <LoadMore onClick={this.handleClick} disabled={this.props.disabled} />; - } - -} - export default class StatusList extends ImmutablePureComponent { static propTypes = { diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js index 4579bd132..f22509edf 100644 --- a/app/javascript/mastodon/containers/status_container.js +++ b/app/javascript/mastodon/containers/status_container.js @@ -5,6 +5,7 @@ import { makeGetStatus } from '../selectors'; import { replyCompose, mentionCompose, + directCompose, } from '../actions/compose'; import { reblog, @@ -102,6 +103,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, + onDirect (account, router) { + dispatch(directCompose(account, router)); + }, + onMention (account, router) { dispatch(mentionCompose(account, router)); }, diff --git a/app/javascript/mastodon/features/notifications/index.js b/app/javascript/mastodon/features/notifications/index.js index 9a6fb45c8..94a46b833 100644 --- a/app/javascript/mastodon/features/notifications/index.js +++ b/app/javascript/mastodon/features/notifications/index.js @@ -13,7 +13,7 @@ import { createSelector } from 'reselect'; import { List as ImmutableList } from 'immutable'; import { debounce } from 'lodash'; import ScrollableList from '../../components/scrollable_list'; -import LoadMore from '../../components/load_more'; +import LoadGap from '../../components/load_gap'; const messages = defineMessages({ title: { id: 'column.notifications', defaultMessage: 'Notifications' }, @@ -24,24 +24,6 @@ const getNotifications = createSelector([ state => state.getIn(['notifications', 'items']), ], (excludedTypes, notifications) => notifications.filterNot(item => item !== null && excludedTypes.includes(item.get('type')))); -class LoadGap extends React.PureComponent { - - static propTypes = { - disabled: PropTypes.bool, - maxId: PropTypes.string, - onClick: PropTypes.func.isRequired, - }; - - handleClick = () => { - this.props.onClick(this.props.maxId); - } - - render () { - return <LoadMore onClick={this.handleClick} disabled={this.props.disabled} />; - } - -} - const mapStateToProps = state => ({ notifications: getNotifications(state), isLoading: state.getIn(['notifications', 'isLoading'], true), diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js index 13cc10c9c..4aa6b08f2 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.js +++ b/app/javascript/mastodon/features/status/components/action_bar.js @@ -8,6 +8,7 @@ import { me } from '../../../initial_state'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, + direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' }, mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, reply: { id: 'status.reply', defaultMessage: 'Reply' }, reblog: { id: 'status.reblog', defaultMessage: 'Boost' }, @@ -37,6 +38,7 @@ export default class ActionBar extends React.PureComponent { onReblog: PropTypes.func.isRequired, onFavourite: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired, + onDirect: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, onMute: PropTypes.func, onMuteConversation: PropTypes.func, @@ -63,6 +65,10 @@ export default class ActionBar extends React.PureComponent { this.props.onDelete(this.props.status); } + handleDirectClick = () => { + this.props.onDirect(this.props.status.get('account'), this.context.router.history); + } + handleMentionClick = () => { this.props.onMention(this.props.status.get('account'), this.context.router.history); } @@ -108,6 +114,7 @@ export default class ActionBar extends React.PureComponent { if (publicStatus) { menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed }); + menu.push(null); } if (me === status.getIn(['account', 'id'])) { @@ -121,6 +128,7 @@ export default class ActionBar extends React.PureComponent { menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); } else { menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); + menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick }); menu.push(null); menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick }); menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js index 2f482b292..55eff0823 100644 --- a/app/javascript/mastodon/features/status/index.js +++ b/app/javascript/mastodon/features/status/index.js @@ -19,6 +19,7 @@ import { import { replyCompose, mentionCompose, + directCompose, } from '../../actions/compose'; import { blockAccount } from '../../actions/accounts'; import { @@ -148,6 +149,10 @@ export default class Status extends ImmutablePureComponent { } } + handleDirectClick = (account, router) => { + this.props.dispatch(directCompose(account, router)); + } + handleMentionClick = (account, router) => { this.props.dispatch(mentionCompose(account, router)); } @@ -379,6 +384,7 @@ export default class Status extends ImmutablePureComponent { onFavourite={this.handleFavouriteClick} onReblog={this.handleReblogClick} onDelete={this.handleDeleteClick} + onDirect={this.handleDirectClick} onMention={this.handleMentionClick} onMute={this.handleMuteClick} onMuteConversation={this.handleConversationMuteClick} diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index 6b50e6f4b..6f81db13e 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -198,6 +198,10 @@ "id": "status.delete" }, { + "defaultMessage": "Direct message @{name}", + "id": "status.direct" + }, + { "defaultMessage": "Mention @{name}", "id": "status.mention" }, @@ -1371,6 +1375,10 @@ "id": "status.delete" }, { + "defaultMessage": "Direct message @{name}", + "id": "status.direct" + }, + { "defaultMessage": "Mention @{name}", "id": "status.mention" }, diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 330db2568..4802ddfd1 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -247,6 +247,7 @@ "status.block": "Block @{name}", "status.cannot_reblog": "This post cannot be boosted", "status.delete": "Delete", + "status.direct": "Direct message @{name}", "status.embed": "Embed", "status.favourite": "Favourite", "status.load_more": "Load more", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index c0877262f..82b7070b8 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -276,6 +276,7 @@ "tabs_bar.home": "Strona główna", "tabs_bar.local_timeline": "Lokalne", "tabs_bar.notifications": "Powiadomienia", + "tabs_bar.search": "Szukaj", "ui.beforeunload": "Utracisz tworzony wpis, jeżeli opuścisz Mastodona.", "upload_area.title": "Przeciągnij i upuść aby wysłać", "upload_button.label": "Dodaj zawartość multimedialną", diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js index 1f4177585..87049ea79 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -259,16 +259,18 @@ export default function compose(state = initialState, action) { case COMPOSE_UPLOAD_PROGRESS: return state.set('progress', Math.round((action.loaded / action.total) * 100)); case COMPOSE_MENTION: - return state - .update('text', text => `${text}@${action.account.get('acct')} `) - .set('focusDate', new Date()) - .set('idempotencyKey', uuid()); + return state.withMutations(map => { + map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' ')); + map.set('focusDate', new Date()); + map.set('idempotencyKey', uuid()); + }); case COMPOSE_DIRECT: - return state - .update('text', text => `@${action.account.get('acct')} `) - .set('privacy', 'direct') - .set('focusDate', new Date()) - .set('idempotencyKey', uuid()); + return state.withMutations(map => { + map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' ')); + map.set('privacy', 'direct'); + map.set('focusDate', new Date()); + map.set('idempotencyKey', uuid()); + }); case COMPOSE_SUGGESTIONS_CLEAR: return state.update('suggestions', ImmutableList(), list => list.clear()).set('suggestion_token', null); case COMPOSE_SUGGESTIONS_READY: diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index e6bd0c717..6bd659030 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -145,6 +145,11 @@ border: 0; background: transparent; border-bottom: 1px solid $ui-base-color; + + &.section-break { + margin: 30px 0; + border-bottom: 2px solid $ui-base-lighter-color; + } } .muted-hint { @@ -330,6 +335,36 @@ } } +.report-note__comment { + margin-bottom: 20px; +} + +.report-note__form { + margin-bottom: 20px; + + .report-note__textarea { + box-sizing: border-box; + border: 0; + padding: 7px 4px; + margin-bottom: 10px; + font-size: 16px; + color: $ui-base-color; + display: block; + width: 100%; + outline: 0; + font-family: inherit; + resize: vertical; + } + + .report-note__buttons { + text-align: right; + } + + .report-note__button { + margin: 0 0 5px 5px; + } +} + .batch-form-box { display: flex; flex-wrap: wrap; diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index c82a760c4..94e3089f8 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2455,6 +2455,10 @@ a.status-card { } } +.load-gap { + border-bottom: 1px solid lighten($ui-base-color, 8%); +} + .regeneration-indicator { text-align: center; font-size: 16px; |