Add status reference menu
This commit is contained in:
parent
c656f41b35
commit
44a987810b
8 changed files with 84 additions and 3 deletions
|
@ -62,6 +62,7 @@ export const COMPOSE_LANGUAGE_CHANGE = 'COMPOSE_LANGUAGE_CHANGE';
|
|||
|
||||
export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT';
|
||||
export const COMPOSE_EXPIRATION_INSERT = 'COMPOSE_EXPIRATION_INSERT';
|
||||
export const COMPOSE_REFERENCE_INSERT = 'COMPOSE_REFERENCE_INSERT';
|
||||
|
||||
export const COMPOSE_UPLOAD_CHANGE_REQUEST = 'COMPOSE_UPLOAD_UPDATE_REQUEST';
|
||||
export const COMPOSE_UPLOAD_CHANGE_SUCCESS = 'COMPOSE_UPLOAD_UPDATE_SUCCESS';
|
||||
|
@ -770,6 +771,14 @@ export function insertExpirationCompose(position, data) {
|
|||
};
|
||||
}
|
||||
|
||||
export function insertReferenceCompose(position, url) {
|
||||
return {
|
||||
type: COMPOSE_REFERENCE_INSERT,
|
||||
position,
|
||||
url,
|
||||
};
|
||||
}
|
||||
|
||||
export function changeComposing(value) {
|
||||
return {
|
||||
type: COMPOSE_COMPOSING_CHANGE,
|
||||
|
|
|
@ -49,6 +49,7 @@ const messages = defineMessages({
|
|||
admin_status: { id: 'status.admin_status', defaultMessage: 'Open this post in the moderation interface' },
|
||||
admin_domain: { id: 'status.admin_domain', defaultMessage: 'Open moderation interface for {domain}' },
|
||||
copy: { id: 'status.copy', defaultMessage: 'Copy link to post' },
|
||||
reference: { id: 'status.reference', defaultMessage: 'Add reference' },
|
||||
hide: { id: 'status.hide', defaultMessage: 'Hide post' },
|
||||
blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' },
|
||||
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
|
||||
|
@ -251,6 +252,10 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
navigator.clipboard.writeText(url);
|
||||
};
|
||||
|
||||
handleReference = () => {
|
||||
this.props.onReference(this.props.status);
|
||||
};
|
||||
|
||||
handleHideClick = () => {
|
||||
this.props.onFilter();
|
||||
};
|
||||
|
@ -289,6 +294,11 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
menu.push(null);
|
||||
|
||||
menu.push({ text: intl.formatMessage(status.get('reblogged') ? messages.cancelReblog : messages.reblog), action: this.handleReblogForceModalClick });
|
||||
|
||||
if (publicStatus) {
|
||||
menu.push({ text: intl.formatMessage(messages.reference), action: this.handleReference });
|
||||
}
|
||||
|
||||
menu.push({ text: intl.formatMessage(status.get('bookmarked') ? messages.removeBookmark : messages.bookmark), action: this.handleBookmarkClick });
|
||||
|
||||
if (writtenByMe && pinnableStatus) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
replyCompose,
|
||||
mentionCompose,
|
||||
directCompose,
|
||||
insertReferenceCompose,
|
||||
} from '../actions/compose';
|
||||
import {
|
||||
blockDomain,
|
||||
|
@ -192,6 +193,10 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
|
|||
});
|
||||
},
|
||||
|
||||
onReference (status) {
|
||||
dispatch(insertReferenceCompose(0, status.get('url')));
|
||||
},
|
||||
|
||||
onTranslate (status) {
|
||||
if (status.get('translation')) {
|
||||
dispatch(undoStatusTranslation(status.get('id'), status.get('poll')));
|
||||
|
|
|
@ -42,6 +42,7 @@ const messages = defineMessages({
|
|||
admin_status: { id: 'status.admin_status', defaultMessage: 'Open this post in the moderation interface' },
|
||||
admin_domain: { id: 'status.admin_domain', defaultMessage: 'Open moderation interface for {domain}' },
|
||||
copy: { id: 'status.copy', defaultMessage: 'Copy link to post' },
|
||||
reference: { id: 'status.reference', defaultMessage: 'Add reference' },
|
||||
blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' },
|
||||
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
|
||||
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
|
||||
|
@ -69,6 +70,7 @@ class ActionBar extends PureComponent {
|
|||
onReblogForceModal: PropTypes.func.isRequired,
|
||||
onFavourite: PropTypes.func.isRequired,
|
||||
onEmojiReact: PropTypes.func.isRequired,
|
||||
onReference: PropTypes.func.isRequired,
|
||||
onBookmark: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
onEdit: PropTypes.func.isRequired,
|
||||
|
@ -190,6 +192,10 @@ class ActionBar extends PureComponent {
|
|||
navigator.clipboard.writeText(url);
|
||||
};
|
||||
|
||||
handleReference = () => {
|
||||
this.props.onReference(this.props.status);
|
||||
};
|
||||
|
||||
handleEmojiPick = (data) => {
|
||||
this.props.onEmojiReact(this.props.status, data);
|
||||
};
|
||||
|
@ -227,6 +233,11 @@ class ActionBar extends PureComponent {
|
|||
|
||||
menu.push(null);
|
||||
menu.push({ text: intl.formatMessage(messages.reblog), action: this.handleReblogForceModalClick });
|
||||
|
||||
if (publicStatus) {
|
||||
menu.push({ text: intl.formatMessage(messages.reference), action: this.handleReference });
|
||||
}
|
||||
|
||||
menu.push(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import {
|
|||
replyCompose,
|
||||
mentionCompose,
|
||||
directCompose,
|
||||
insertReferenceCompose,
|
||||
} from '../../actions/compose';
|
||||
import {
|
||||
blockDomain,
|
||||
|
@ -356,6 +357,10 @@ class Status extends ImmutablePureComponent {
|
|||
this.handleReblogClick(status, e, true);
|
||||
};
|
||||
|
||||
handleReference = (status) => {
|
||||
this.props.dispatch(insertReferenceCompose(0, status.get('url')));
|
||||
};
|
||||
|
||||
handleBookmarkClick = (status) => {
|
||||
if (status.get('bookmarked')) {
|
||||
this.props.dispatch(unbookmark(status));
|
||||
|
@ -717,6 +722,7 @@ class Status extends ImmutablePureComponent {
|
|||
onEmojiReact={this.handleEmojiReact}
|
||||
onReblog={this.handleReblogClick}
|
||||
onReblogForceModal={this.handleReblogForceModalClick}
|
||||
onReference={this.handleReference}
|
||||
onBookmark={this.handleBookmarkClick}
|
||||
onDelete={this.handleDeleteClick}
|
||||
onEdit={this.handleEditClick}
|
||||
|
|
|
@ -419,6 +419,7 @@
|
|||
"notification.poll": "A poll you have voted in has ended",
|
||||
"notification.reblog": "{name} boosted your post",
|
||||
"notification.status": "{name} just posted",
|
||||
"notification.status_reference": "{name} refered your post",
|
||||
"notification.update": "{name} edited a post",
|
||||
"notifications.clear": "Clear notifications",
|
||||
"notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
|
||||
|
|
|
@ -36,6 +36,7 @@ import {
|
|||
COMPOSE_COMPOSING_CHANGE,
|
||||
COMPOSE_EMOJI_INSERT,
|
||||
COMPOSE_EXPIRATION_INSERT,
|
||||
COMPOSE_REFERENCE_INSERT,
|
||||
COMPOSE_UPLOAD_CHANGE_REQUEST,
|
||||
COMPOSE_UPLOAD_CHANGE_SUCCESS,
|
||||
COMPOSE_UPLOAD_CHANGE_FAIL,
|
||||
|
@ -238,6 +239,41 @@ const insertExpiration = (state, position, data) => {
|
|||
});
|
||||
};
|
||||
|
||||
const insertReference = (state, url) => {
|
||||
const oldText = state.get('text');
|
||||
|
||||
if (oldText.indexOf(`BT ${url}`) >= 0) {
|
||||
return state;
|
||||
}
|
||||
|
||||
let newLine = '\n\n';
|
||||
if (oldText.length === 0) newLine = '';
|
||||
else if (oldText[oldText.length - 1] === '\n') {
|
||||
if (oldText.length === 1 || oldText[oldText.length - 2] === '\n') {
|
||||
newLine = '';
|
||||
} else {
|
||||
newLine = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (oldText.length > 0) {
|
||||
const lastLine = oldText.slice(oldText.lastIndexOf('\n') + 1, oldText.length - 1);
|
||||
if (lastLine.startsWith('BT ')) {
|
||||
newLine = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
const referenceText = `${newLine}BT ${url}`;
|
||||
const text = `${oldText}${referenceText}`;
|
||||
|
||||
return state.merge({
|
||||
text,
|
||||
focusDate: new Date(),
|
||||
caretPosition: text.length - referenceText.length,
|
||||
idempotencyKey: uuid(),
|
||||
});
|
||||
};
|
||||
|
||||
const privacyPreference = (a, b) => {
|
||||
const order = ['public', 'public_unlisted', 'unlisted', 'login', 'private', 'direct'];
|
||||
return order[Math.max(order.indexOf(a), order.indexOf(b), 0)];
|
||||
|
@ -476,6 +512,8 @@ export default function compose(state = initialState, action) {
|
|||
return insertEmoji(state, action.position, action.emoji, action.needsSpace);
|
||||
case COMPOSE_EXPIRATION_INSERT:
|
||||
return insertExpiration(state, action.position, action.data);
|
||||
case COMPOSE_REFERENCE_INSERT:
|
||||
return insertReference(state, action.url);
|
||||
case COMPOSE_UPLOAD_CHANGE_SUCCESS:
|
||||
return state
|
||||
.set('is_changing_upload', false)
|
||||
|
|
|
@ -4,7 +4,7 @@ class ProcessReferencesService < BaseService
|
|||
include Payloadable
|
||||
|
||||
DOMAIN = ENV['WEB_DOMAIN'] || ENV.fetch('LOCAL_DOMAIN', nil)
|
||||
REFURL_EXP = /(RT|QT|BT|RN)((:)? +|:)(#{URI::DEFAULT_PARSER.make_regexp(%w(http https))})/
|
||||
REFURL_EXP = /(RT|QT|BT|RN|RE)((:)? +|:)(#{URI::DEFAULT_PARSER.make_regexp(%w(http https))})/
|
||||
STATUSID_EXP = %r{(http|https)://#{DOMAIN}/@[a-zA-Z0-9]+/([0-9]{16,})}
|
||||
|
||||
def call(status, reference_parameters, save_records: true, urls: nil)
|
||||
|
@ -69,9 +69,10 @@ class ProcessReferencesService < BaseService
|
|||
end
|
||||
|
||||
def create_notifications!
|
||||
return if @added_objects.empty?
|
||||
local_reference_objects = @added_objects.filter { |ref| ref.target_status.account.local? }
|
||||
return if local_reference_objects.empty?
|
||||
|
||||
LocalNotificationWorker.push_bulk(@added_objects) do |ref|
|
||||
LocalNotificationWorker.push_bulk(local_reference_objects) do |ref|
|
||||
[ref.target_status.account_id, ref.id, 'StatusReference', 'status_reference']
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue