* Add: `conversations`テーブルに`ancestor_status`プロパティ * Fix test * Fix test more * Add: `limited_visibility`に`Reply`を追加、`context`のURI * Add: 外部からの`context`受信処理 * Fix test * Add: 公開範囲「返信」 * Fix test * Fix: 返信に返信以外の公開範囲を設定できない問題 * Add: ローカル投稿時にメンション追加・他サーバーへの転送 * Fix test * Fix test * Test: ローカルスレッドへの返信投稿の転送 * Test: 未知のアカウントからのメンション * Add: 編集・削除の連合に対応 * Remove: 重複テスト * Fix: 改善 * Add: 編集削除の転送処理・返信なのにsilentなメンションでの通知 * Fix: リプライが第三者に届かない問題 * Add: `always_sign_unsafe` * Add: Subject * Remove space * Fix: 他人のスレッドの送信先一覧を非表示 * Fix: おかしいコード
This commit is contained in:
parent
a52a8ce214
commit
a88349af55
42 changed files with 1115 additions and 77 deletions
|
@ -61,16 +61,6 @@ export const defaultMediaVisibility = (status) => {
|
|||
};
|
||||
|
||||
const messages = defineMessages({
|
||||
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
|
||||
unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
|
||||
public_unlisted_short: { id: 'privacy.public_unlisted.short', defaultMessage: 'Public unlisted' },
|
||||
login_short: { id: 'privacy.login.short', defaultMessage: 'Login only' },
|
||||
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers only' },
|
||||
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Limited menbers only' },
|
||||
mutual_short: { id: 'privacy.mutual.short', defaultMessage: 'Mutual followers only' },
|
||||
circle_short: { id: 'privacy.circle.short', defaultMessage: 'Circle members only' },
|
||||
personal_short: { id: 'privacy.personal.short', defaultMessage: 'Yourself only' },
|
||||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Mentioned people only' },
|
||||
edited: { id: 'status.edited', defaultMessage: 'Edited {date}' },
|
||||
});
|
||||
|
||||
|
|
|
@ -76,16 +76,6 @@ export const defaultMediaVisibility = (status) => {
|
|||
};
|
||||
|
||||
const messages = defineMessages({
|
||||
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
|
||||
unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
|
||||
public_unlisted_short: { id: 'privacy.public_unlisted.short', defaultMessage: 'Public unlisted' },
|
||||
login_short: { id: 'privacy.login.short', defaultMessage: 'Login only' },
|
||||
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers only' },
|
||||
limited_short: { id: 'privacy.limited.short', defaultMessage: 'Limited menbers only' },
|
||||
mutual_short: { id: 'privacy.mutual.short', defaultMessage: 'Mutual followers only' },
|
||||
circle_short: { id: 'privacy.circle.short', defaultMessage: 'Circle members only' },
|
||||
personal_short: { id: 'privacy.personal.short', defaultMessage: 'Yourself only' },
|
||||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Mentioned people only' },
|
||||
edited: { id: 'status.edited', defaultMessage: 'Edited {date}' },
|
||||
});
|
||||
|
||||
|
|
|
@ -336,7 +336,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
if (signedIn) {
|
||||
if (writtenByMe) {
|
||||
if (writtenByMe && status.get('limited_scope') !== 'reply') {
|
||||
menu.push({ text: intl.formatMessage(messages.mentions), action: this.handleOpenMentions });
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import { ReactComponent as LoginIcon } from '@material-symbols/svg-600/outlined/
|
|||
import { ReactComponent as LockIcon } from '@material-symbols/svg-600/outlined/lock.svg';
|
||||
import { ReactComponent as LockOpenIcon } from '@material-symbols/svg-600/outlined/no_encryption.svg';
|
||||
import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
|
||||
import { ReactComponent as ReplyIcon } from '@material-symbols/svg-600/outlined/reply.svg';
|
||||
import { ReactComponent as LimitedIcon } from '@material-symbols/svg-600/outlined/shield.svg';
|
||||
import { ReactComponent as PersonalIcon } from '@material-symbols/svg-600/outlined/sticky_note.svg';
|
||||
|
||||
|
@ -23,6 +24,7 @@ type Visibility =
|
|||
| 'mutual'
|
||||
| 'circle'
|
||||
| 'personal'
|
||||
| 'reply'
|
||||
| 'limited';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -49,6 +51,10 @@ const messages = defineMessages({
|
|||
id: 'privacy.circle.short',
|
||||
defaultMessage: 'Circle members only',
|
||||
},
|
||||
reply_short: {
|
||||
id: 'privacy.reply.short',
|
||||
defaultMessage: 'Reply',
|
||||
},
|
||||
personal_short: {
|
||||
id: 'privacy.personal.short',
|
||||
defaultMessage: 'Yourself only',
|
||||
|
@ -105,6 +111,11 @@ export const VisibilityIcon: React.FC<{ visibility: Visibility }> = ({
|
|||
iconComponent: CircleIcon,
|
||||
text: intl.formatMessage(messages.circle_short),
|
||||
},
|
||||
reply: {
|
||||
icon: 'reply',
|
||||
iconComponent: ReplyIcon,
|
||||
text: intl.formatMessage(messages.reply_short),
|
||||
},
|
||||
personal: {
|
||||
icon: 'sticky-note-o',
|
||||
iconComponent: PersonalIcon,
|
||||
|
|
|
@ -14,6 +14,7 @@ import { ReactComponent as LoginIcon } from '@material-symbols/svg-600/outlined/
|
|||
import { ReactComponent as LockIcon } from '@material-symbols/svg-600/outlined/lock.svg';
|
||||
import { ReactComponent as LockOpenIcon } from '@material-symbols/svg-600/outlined/no_encryption.svg';
|
||||
import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
|
||||
import { ReactComponent as ReplyIcon } from '@material-symbols/svg-600/outlined/reply.svg';
|
||||
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
import Overlay from 'react-overlays/Overlay';
|
||||
|
||||
|
@ -38,6 +39,8 @@ const messages = defineMessages({
|
|||
mutual_long: { id: 'privacy.mutual.long', defaultMessage: 'Mutual follows only' },
|
||||
circle_short: { id: 'privacy.circle.short', defaultMessage: 'Circle' },
|
||||
circle_long: { id: 'privacy.circle.long', defaultMessage: 'Circle members only' },
|
||||
reply_short: { id: 'privacy.reply.short', defaultMessage: 'Reply' },
|
||||
reply_long: { id: 'privacy.reply.long', defaultMessage: 'Reply to limited post' },
|
||||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Mentioned people only' },
|
||||
direct_long: { id: 'privacy.direct.long', defaultMessage: 'Visible for mentioned users only' },
|
||||
change_privacy: { id: 'privacy.change', defaultMessage: 'Adjust status privacy' },
|
||||
|
@ -166,6 +169,7 @@ class PrivacyDropdown extends PureComponent {
|
|||
value: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
noDirect: PropTypes.bool,
|
||||
replyToLimited: PropTypes.bool,
|
||||
container: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
@ -280,10 +284,22 @@ class PrivacyDropdown extends PureComponent {
|
|||
};
|
||||
|
||||
render () {
|
||||
const { value, container, disabled, intl } = this.props;
|
||||
const { value, container, disabled, intl, replyToLimited } = this.props;
|
||||
const { open, placement } = this.state;
|
||||
|
||||
const valueOption = this.options.find(item => item.value === value) || this.options[0];
|
||||
if (replyToLimited) {
|
||||
if (!this.selectableOptions.some((op) => op.value === 'reply')) {
|
||||
this.selectableOptions.unshift(
|
||||
{ icon: 'reply', iconComponent: ReplyIcon, value: 'reply', text: intl.formatMessage(messages.reply_short), meta: intl.formatMessage(messages.reply_long) },
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (this.selectableOptions.some((op) => op.value === 'reply')) {
|
||||
this.selectableOptions = this.selectableOptions.filter((op) => op.value !== 'reply');
|
||||
}
|
||||
}
|
||||
|
||||
const valueOption = this.selectableOptions.find(item => item.value === value) || this.selectableOptions[0];
|
||||
|
||||
return (
|
||||
<div ref={this.setTargetRef} onKeyDown={this.handleKeyDown}>
|
||||
|
|
|
@ -7,6 +7,7 @@ import PrivacyDropdown from '../components/privacy_dropdown';
|
|||
|
||||
const mapStateToProps = state => ({
|
||||
value: state.getIn(['compose', 'privacy']),
|
||||
replyToLimited: state.getIn(['compose', 'reply_to_limited']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
|
|
@ -287,7 +287,10 @@ class ActionBar extends PureComponent {
|
|||
menu.push(null);
|
||||
}
|
||||
|
||||
menu.push({ text: intl.formatMessage(messages.mentions), action: this.handleOpenMentions });
|
||||
if (status.get('limited_scope') !== 'reply') {
|
||||
menu.push({ text: intl.formatMessage(messages.mentions), action: this.handleOpenMentions });
|
||||
}
|
||||
|
||||
menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
|
||||
menu.push(null);
|
||||
menu.push({ text: intl.formatMessage(messages.edit), action: this.handleEditClick });
|
||||
|
|
|
@ -77,6 +77,7 @@ const initialState = ImmutableMap({
|
|||
caretPosition: null,
|
||||
preselectDate: null,
|
||||
in_reply_to: null,
|
||||
reply_to_limited: false,
|
||||
is_composing: false,
|
||||
is_submitting: false,
|
||||
is_changing_upload: false,
|
||||
|
@ -114,6 +115,10 @@ const initialPoll = ImmutableMap({
|
|||
});
|
||||
|
||||
function statusToTextMentions(state, status) {
|
||||
if (status.get('visibility_ex') === 'limited') {
|
||||
return '';
|
||||
}
|
||||
|
||||
let set = ImmutableOrderedSet([]);
|
||||
|
||||
if (status.getIn(['account', 'id']) !== me) {
|
||||
|
@ -144,6 +149,7 @@ function clearAll(state) {
|
|||
if (!state.get('in_reply_to')) {
|
||||
map.set('posted_on_this_session', true);
|
||||
}
|
||||
map.set('reply_to_limited', false);
|
||||
map.set('limited_scope', null);
|
||||
map.set('id', null);
|
||||
map.set('in_reply_to', null);
|
||||
|
@ -411,7 +417,12 @@ export default function compose(state = initialState, action) {
|
|||
map.set('id', null);
|
||||
map.set('in_reply_to', action.status.get('id'));
|
||||
map.set('text', statusToTextMentions(state, action.status));
|
||||
map.set('privacy', privacyPreference(action.status.get('visibility_ex'), state.get('default_privacy')));
|
||||
map.set('reply_to_limited', action.status.get('visibility_ex') === 'limited');
|
||||
if (action.status.get('visibility_ex') === 'limited') {
|
||||
map.set('privacy', 'reply');
|
||||
} else {
|
||||
map.set('privacy', privacyPreference(action.status.get('visibility_ex'), state.get('default_privacy')));
|
||||
}
|
||||
map.set('limited_scope', null);
|
||||
map.set('searchability', privacyPreference(action.status.get('searchability'), state.get('default_searchability')));
|
||||
map.set('focusDate', new Date());
|
||||
|
@ -521,7 +532,11 @@ export default function compose(state = initialState, action) {
|
|||
return state.set('tagHistory', fromJS(action.tags));
|
||||
case TIMELINE_DELETE:
|
||||
if (action.id === state.get('in_reply_to')) {
|
||||
return state.set('in_reply_to', null);
|
||||
if (state.get('privacy') === 'reply') {
|
||||
return state.set('in_reply_to', null).set('privacy', 'circle');
|
||||
} else {
|
||||
return state.set('in_reply_to', null);
|
||||
}
|
||||
} else if (action.id === state.get('id')) {
|
||||
return state.set('id', null);
|
||||
} else {
|
||||
|
@ -549,6 +564,7 @@ export default function compose(state = initialState, action) {
|
|||
map.set('text', action.raw_text || unescapeHTML(expandMentions(action.status)));
|
||||
map.set('in_reply_to', action.status.get('in_reply_to_id'));
|
||||
map.set('privacy', action.status.get('visibility_ex'));
|
||||
map.set('reply_to_limited', action.status.get('limited_scope') === 'reply');
|
||||
map.set('limited_scope', null);
|
||||
map.set('media_attachments', action.status.get('media_attachments').map((media) => media.set('unattached', true)));
|
||||
map.set('focusDate', new Date());
|
||||
|
@ -583,8 +599,9 @@ export default function compose(state = initialState, action) {
|
|||
if (action.status.get('visibility_ex') !== 'limited') {
|
||||
map.set('privacy', action.status.get('visibility_ex'));
|
||||
} else {
|
||||
map.set('privacy', action.status.get('limited_scope') === 'mutual' ? 'mutual' : 'circle');
|
||||
map.set('privacy', action.status.get('limited_scope') || 'circle');
|
||||
}
|
||||
map.set('reply_to_limited', action.status.get('limited_scope') === 'reply');
|
||||
map.set('limited_scope', action.status.get('limited_scope'));
|
||||
map.set('media_attachments', action.status.get('media_attachments'));
|
||||
map.set('focusDate', new Date());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue