From 92b09d90c8f48e30e83d98cab4f3bc1724e32dae Mon Sep 17 00:00:00 2001 From: bsky Date: Tue, 22 May 2018 20:24:54 +0900 Subject: Remove outline (#7582) --- app/javascript/styles/mastodon/components.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'app/javascript') diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 0765b3ffc..412f8d770 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1984,6 +1984,7 @@ a.account__display-name { padding: 15px; margin: 0; z-index: 3; + outline: 0; &:hover { text-decoration: underline; -- cgit From 06252ec71ed67cb84e6730fe7148552dc6481c7a Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Tue, 22 May 2018 20:26:06 +0900 Subject: Change column params on pinned timeline (#7581) --- app/javascript/mastodon/actions/columns.js | 19 ++++++++++--- .../mastodon/features/community_timeline/index.js | 31 +++++++++++++++++++--- .../mastodon/features/public_timeline/index.js | 31 +++++++++++++++++++--- app/javascript/mastodon/reducers/settings.js | 15 ++++++++++- 4 files changed, 84 insertions(+), 12 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/actions/columns.js b/app/javascript/mastodon/actions/columns.js index bcb0cdf98..f550e6c48 100644 --- a/app/javascript/mastodon/actions/columns.js +++ b/app/javascript/mastodon/actions/columns.js @@ -1,8 +1,9 @@ import { saveSettings } from './settings'; -export const COLUMN_ADD = 'COLUMN_ADD'; -export const COLUMN_REMOVE = 'COLUMN_REMOVE'; -export const COLUMN_MOVE = 'COLUMN_MOVE'; +export const COLUMN_ADD = 'COLUMN_ADD'; +export const COLUMN_REMOVE = 'COLUMN_REMOVE'; +export const COLUMN_MOVE = 'COLUMN_MOVE'; +export const COLUMN_PARAMS_CHANGE = 'COLUMN_PARAMS_CHANGE'; export function addColumn(id, params) { return dispatch => { @@ -38,3 +39,15 @@ export function moveColumn(uuid, direction) { dispatch(saveSettings()); }; }; + +export function changeColumnParams(uuid, params) { + return dispatch => { + dispatch({ + type: COLUMN_PARAMS_CHANGE, + uuid, + params, + }); + + dispatch(saveSettings()); + }; +} diff --git a/app/javascript/mastodon/features/community_timeline/index.js b/app/javascript/mastodon/features/community_timeline/index.js index b6489432f..bae856c4b 100644 --- a/app/javascript/mastodon/features/community_timeline/index.js +++ b/app/javascript/mastodon/features/community_timeline/index.js @@ -1,13 +1,13 @@ import React from 'react'; import { connect } from 'react-redux'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { NavLink, Link } from 'react-router-dom'; +import { NavLink } from 'react-router-dom'; import PropTypes from 'prop-types'; import StatusListContainer from '../ui/containers/status_list_container'; import Column from '../../components/column'; import ColumnHeader from '../../components/column_header'; import { expandCommunityTimeline } from '../../actions/timelines'; -import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; +import { addColumn, removeColumn, moveColumn, changeColumnParams } from '../../actions/columns'; import ColumnSettingsContainer from './containers/column_settings_container'; import { connectCommunityStream } from '../../actions/streaming'; @@ -62,6 +62,16 @@ export default class CommunityTimeline extends React.PureComponent { this.disconnect = dispatch(connectCommunityStream({ onlyMedia })); } + componentDidUpdate (prevProps) { + if (prevProps.onlyMedia !== this.props.onlyMedia) { + const { dispatch, onlyMedia } = this.props; + + this.disconnect(); + dispatch(expandCommunityTimeline({ onlyMedia })); + this.disconnect = dispatch(connectCommunityStream({ onlyMedia })); + } + } + componentWillUnmount () { if (this.disconnect) { this.disconnect(); @@ -79,14 +89,27 @@ export default class CommunityTimeline extends React.PureComponent { dispatch(expandCommunityTimeline({ maxId, onlyMedia })); } + handleHeadlineLinkClick = e => { + e.preventDefault(); + + const { columnId, dispatch } = this.props; + const onlyMedia = /\/media$/.test(e.currentTarget.href); + + dispatch(changeColumnParams(columnId, { other: { onlyMedia } })); + } + render () { const { intl, hasUnread, columnId, multiColumn, onlyMedia } = this.props; const pinned = !!columnId; const headline = pinned ? (
- - + + + + + +
) : (
diff --git a/app/javascript/mastodon/features/public_timeline/index.js b/app/javascript/mastodon/features/public_timeline/index.js index da59b7167..84d61e81b 100644 --- a/app/javascript/mastodon/features/public_timeline/index.js +++ b/app/javascript/mastodon/features/public_timeline/index.js @@ -1,13 +1,13 @@ import React from 'react'; import { connect } from 'react-redux'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { NavLink, Link } from 'react-router-dom'; +import { NavLink } from 'react-router-dom'; import PropTypes from 'prop-types'; import StatusListContainer from '../ui/containers/status_list_container'; import Column from '../../components/column'; import ColumnHeader from '../../components/column_header'; import { expandPublicTimeline } from '../../actions/timelines'; -import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; +import { addColumn, removeColumn, moveColumn, changeColumnParams } from '../../actions/columns'; import ColumnSettingsContainer from './containers/column_settings_container'; import { connectPublicStream } from '../../actions/streaming'; @@ -62,6 +62,16 @@ export default class PublicTimeline extends React.PureComponent { this.disconnect = dispatch(connectPublicStream({ onlyMedia })); } + componentDidUpdate (prevProps) { + if (prevProps.onlyMedia !== this.props.onlyMedia) { + const { dispatch, onlyMedia } = this.props; + + this.disconnect(); + dispatch(expandPublicTimeline({ onlyMedia })); + this.disconnect = dispatch(connectPublicStream({ onlyMedia })); + } + } + componentWillUnmount () { if (this.disconnect) { this.disconnect(); @@ -79,14 +89,27 @@ export default class PublicTimeline extends React.PureComponent { dispatch(expandPublicTimeline({ maxId, onlyMedia })); } + handleHeadlineLinkClick = e => { + e.preventDefault(); + + const { columnId, dispatch } = this.props; + const onlyMedia = /\/media$/.test(e.currentTarget.href); + + dispatch(changeColumnParams(columnId, { other: { onlyMedia } })); + } + render () { const { intl, columnId, hasUnread, multiColumn, onlyMedia } = this.props; const pinned = !!columnId; const headline = pinned ? (
- - + + + + + +
) : (
diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js index 9ec52a7fa..de8865e43 100644 --- a/app/javascript/mastodon/reducers/settings.js +++ b/app/javascript/mastodon/reducers/settings.js @@ -1,5 +1,5 @@ import { SETTING_CHANGE, SETTING_SAVE } from '../actions/settings'; -import { COLUMN_ADD, COLUMN_REMOVE, COLUMN_MOVE } from '../actions/columns'; +import { COLUMN_ADD, COLUMN_REMOVE, COLUMN_MOVE, COLUMN_PARAMS_CHANGE } from '../actions/columns'; import { STORE_HYDRATE } from '../actions/store'; import { EMOJI_USE } from '../actions/emojis'; import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists'; @@ -89,6 +89,17 @@ const moveColumn = (state, uuid, direction) => { .set('saved', false); }; +const changeColumnParams = (state, uuid, params) => { + const columns = state.get('columns'); + const index = columns.findIndex(item => item.get('uuid') === uuid); + + const newColumns = columns.update(index, column => column.update('params', () => fromJS(params))); + + return state + .set('columns', newColumns) + .set('saved', false); +}; + const updateFrequentEmojis = (state, emoji) => state.update('frequentlyUsedEmojis', ImmutableMap(), map => map.update(emoji.id, 0, count => count + 1)).set('saved', false); const filterDeadListColumns = (state, listId) => state.update('columns', columns => columns.filterNot(column => column.get('id') === 'LIST' && column.get('params').get('id') === listId)); @@ -111,6 +122,8 @@ export default function settings(state = initialState, action) { .set('saved', false); case COLUMN_MOVE: return moveColumn(state, action.uuid, action.direction); + case COLUMN_PARAMS_CHANGE: + return changeColumnParams(state, action.uuid, action.params); case EMOJI_USE: return updateFrequentEmojis(state, action.emoji); case SETTING_SAVE: -- cgit From 4eeda6772796bcd08b8c63ec2e1f3e68a95cbca4 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Tue, 22 May 2018 21:44:32 +0900 Subject: Hide section headline for timelines in production (#7590) * Hide section headline for timelines in production * comment out --- .../components/section_headline.js | 59 ++++++++++++++++++++++ .../mastodon/features/community_timeline/index.js | 32 +++++------- .../mastodon/features/public_timeline/index.js | 32 +++++------- 3 files changed, 85 insertions(+), 38 deletions(-) create mode 100644 app/javascript/mastodon/features/community_timeline/components/section_headline.js (limited to 'app/javascript') diff --git a/app/javascript/mastodon/features/community_timeline/components/section_headline.js b/app/javascript/mastodon/features/community_timeline/components/section_headline.js new file mode 100644 index 000000000..c7176d04b --- /dev/null +++ b/app/javascript/mastodon/features/community_timeline/components/section_headline.js @@ -0,0 +1,59 @@ +import PropTypes from 'prop-types'; +import React, { Component, Fragment } from 'react'; +import { FormattedMessage } from 'react-intl'; +import { NavLink } from 'react-router-dom'; + +export default class SectionHeadline extends Component { + + static propTypes = { + timelineId: PropTypes.string.isRequired, + to: PropTypes.string.isRequired, + pinned: PropTypes.bool.isRequired, + onlyMedia: PropTypes.bool.isRequired, + onClick: PropTypes.func, + }; + + shouldComponentUpdate (nextProps) { + return ( + this.props.onlyMedia !== nextProps.onlyMedia || + this.props.pinned !== nextProps.pinned || + this.props.to !== nextProps.to || + this.props.timelineId !== nextProps.timelineId + ); + } + + handleClick = e => { + const { onClick } = this.props; + + if (typeof onClick === 'function') { + e.preventDefault(); + + onClick.call(this, e); + } + } + + render () { + const { timelineId, to, pinned, onlyMedia } = this.props; + + return ( +
+ {pinned ? ( + + + + + + + + + ) : ( + + + + + )} +
+ ); + } + +} diff --git a/app/javascript/mastodon/features/community_timeline/index.js b/app/javascript/mastodon/features/community_timeline/index.js index bae856c4b..58b8a8b73 100644 --- a/app/javascript/mastodon/features/community_timeline/index.js +++ b/app/javascript/mastodon/features/community_timeline/index.js @@ -1,7 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { NavLink } from 'react-router-dom'; import PropTypes from 'prop-types'; import StatusListContainer from '../ui/containers/status_list_container'; import Column from '../../components/column'; @@ -9,6 +8,7 @@ import ColumnHeader from '../../components/column_header'; import { expandCommunityTimeline } from '../../actions/timelines'; import { addColumn, removeColumn, moveColumn, changeColumnParams } from '../../actions/columns'; import ColumnSettingsContainer from './containers/column_settings_container'; +// import SectionHeadline from './components/section_headline'; import { connectCommunityStream } from '../../actions/streaming'; const messages = defineMessages({ @@ -90,8 +90,6 @@ export default class CommunityTimeline extends React.PureComponent { } handleHeadlineLinkClick = e => { - e.preventDefault(); - const { columnId, dispatch } = this.props; const onlyMedia = /\/media$/.test(e.currentTarget.href); @@ -102,21 +100,17 @@ export default class CommunityTimeline extends React.PureComponent { const { intl, hasUnread, columnId, multiColumn, onlyMedia } = this.props; const pinned = !!columnId; - const headline = pinned ? ( - - ) : ( -
- - -
- ); + // pending + // + // const headline = ( + // + // ); return ( @@ -134,7 +128,7 @@ export default class CommunityTimeline extends React.PureComponent { { - e.preventDefault(); - const { columnId, dispatch } = this.props; const onlyMedia = /\/media$/.test(e.currentTarget.href); @@ -102,21 +100,17 @@ export default class PublicTimeline extends React.PureComponent { const { intl, columnId, hasUnread, multiColumn, onlyMedia } = this.props; const pinned = !!columnId; - const headline = pinned ? ( - - ) : ( -
- - -
- ); + // pending + // + // const headline = ( + // + // ); return ( @@ -134,7 +128,7 @@ export default class PublicTimeline extends React.PureComponent { Date: Tue, 22 May 2018 21:26:42 +0800 Subject: [WIP] i18n: Update Simplified Chinese translations (#7576) * i18n: (zh-CN) #7027 * Rewording This placeholder is also seen on single user page at Moderation > Accounts, where "this report" doesn't make sense. * i18n: (zh-CN) #6425 * i18n: (zh-CN) #6497 * i18n: (zh-CN) #6246 * i18n: (zh-CN) Improvements --- app/javascript/mastodon/locales/zh-CN.json | 8 ++++---- config/locales/en.yml | 4 ++-- config/locales/simple_form.zh-CN.yml | 2 +- config/locales/zh-CN.yml | 18 +++++++++++++----- 4 files changed, 20 insertions(+), 12 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index b920bc19e..b67afd29f 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -39,7 +39,7 @@ "bundle_modal_error.close": "关闭", "bundle_modal_error.message": "载入这个组件时发生了错误。", "bundle_modal_error.retry": "重试", - "column.blocks": "屏蔽用户", + "column.blocks": "已屏蔽的用户", "column.community": "本站时间轴", "column.direct": "私信", "column.domain_blocks": "已屏蔽的网站", @@ -47,7 +47,7 @@ "column.follow_requests": "关注请求", "column.home": "主页", "column.lists": "列表", - "column.mutes": "被隐藏的用户", + "column.mutes": "已隐藏的用户", "column.notifications": "通知", "column.pins": "置顶嘟文", "column.public": "跨站公共时间轴", @@ -157,7 +157,7 @@ "missing_indicator.label": "找不到内容", "missing_indicator.sublabel": "无法找到此资源", "mute_modal.hide_notifications": "同时隐藏来自这个用户的通知", - "navigation_bar.blocks": "被屏蔽的用户", + "navigation_bar.blocks": "已屏蔽的用户", "navigation_bar.community_timeline": "本站时间轴", "navigation_bar.direct": "私信", "navigation_bar.domain_blocks": "已屏蔽的网站", @@ -168,7 +168,7 @@ "navigation_bar.keyboard_shortcuts": "快捷键列表", "navigation_bar.lists": "列表", "navigation_bar.logout": "注销", - "navigation_bar.mutes": "被隐藏的用户", + "navigation_bar.mutes": "已隐藏的用户", "navigation_bar.pins": "置顶嘟文", "navigation_bar.preferences": "首选项", "navigation_bar.public_timeline": "跨站公共时间轴", diff --git a/config/locales/en.yml b/config/locales/en.yml index 65b5b1e0b..262883e2c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -283,7 +283,7 @@ en: create_and_resolve: Resolve with note create_and_unresolve: Reopen with note delete: Delete - placeholder: Describe what actions have been taken, or any other updates to this report… + placeholder: Describe what actions have been taken, or any other related updates... reopen: Reopen report report: 'Report #%{id}' report_contents: Contents @@ -550,7 +550,7 @@ en: subject: one: "1 new notification since your last visit \U0001F418" other: "%{count} new notifications since your last visit \U0001F418" - title: In your absence… + title: In your absence... favourite: body: 'Your status was favourited by %{name}:' subject: "%{name} favourited your status" diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index b12538b35..5b3b25ab1 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -13,7 +13,7 @@ zh-CN: note: 还能输入 %{count} 个字符 setting_hide_network: 你关注的人和关注你的人将不会在你的个人资料页上展示 setting_noindex: 此设置会影响到你的公开个人资料以及嘟文页面 - setting_theme: 此设置会影响到你从任意设备登录时 Mastodon 的显示样式 + setting_theme: 此设置会影响到所有已登录设备上 Mastodon 的显示样式 imports: data: 请上传从其他 Mastodon 实例导出的 CSV 文件 sessions: diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index f7fc1a7a9..357575a3b 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -26,9 +26,9 @@ zh-CN: within_reach_title: 始终触手可及 generic_description: "%{domain} 是这个庞大网络中的一台服务器" hosted_on: 一个在 %{domain} 上运行的 Mastodon 实例 - learn_more: 详细了解 + learn_more: 了解详情 other_instances: 其他实例 - source_code: 源码 + source_code: 源代码 status_count_after: 条嘟文 status_count_before: 他们共嘟出了 user_count_after: 位用户 @@ -281,7 +281,7 @@ zh-CN: create_and_resolve: 添加记录并标记为“已处理” create_and_unresolve: 添加记录并重开 delete: 删除 - placeholder: 描述已经执行的操作,或其他任何与此条举报相关的跟进情况 + placeholder: 描述已经执行的操作,或其他任何相关的跟进情况 reopen: 重开举报 report: '举报 #%{id}' report_contents: 内容 @@ -405,6 +405,9 @@ zh-CN: migrate_account_html: 如果你希望引导他人关注另一个帐户,请点击这里进行设置。 or: 或者 or_log_in_with: 或通过其他方式登录 + providers: + cas: CAS + saml: SAML register: 注册 register_elsewhere: 前往其他实例注册 resend_confirmation: 重新发送确认邮件 @@ -460,7 +463,7 @@ zh-CN: archive_takeout: date: 日期 download: 下载你的存档 - hint_html: 你可以请求一份包含你的嘟文和已上传的媒体文件的存档。导出的数据为 ActivityPub 格式,因而可以通过相应的软件读取。每次可以请求存档的间隔至少为 7 天。 + hint_html: 你可以请求一份帐户数据存档,其中包含你的嘟文和已上传的媒体文件。导出的数据为 ActivityPub 格式,因而可以被兼容的软件读取。每次允许请求存档的间隔至少为 7 天。 in_progress: 正在准备你的存档…… request: 请求你的存档 size: 大小 @@ -574,7 +577,9 @@ zh-CN: trillion: T unit: '' pagination: + newer: 更新 next: 下一页 + older: 更早 prev: 上一页 truncate: "…" preferences: @@ -599,12 +604,14 @@ zh-CN: blackberry: Blackberry chrome: Chrome edge: Microsoft Edge + electron: Electron firefox: Firefox generic: 未知浏览器 ie: Internet Explorer micro_messenger: 微信 nokia: Nokia S40 Ovi 浏览器 opera: Opera + otter: Otter phantom_js: PhantomJS qq: QQ浏览器 safari: Safari @@ -632,7 +639,7 @@ zh-CN: title: 会话 settings: authorized_apps: 已授权的应用 - back: 回到 Mastodon + back: 返回 Mastodon delete: 删除帐户 development: 开发 edit_profile: 更改个人资料 @@ -681,6 +688,7 @@ zh-CN: themes: contrast: 高对比度 default: Mastodon + mastodon-light: Mastodon(亮色主题) time: formats: default: "%Y年%-m月%d日 %H:%M" -- cgit From 39d70f375f2f9cd7e12cbf4486059dfc4a945755 Mon Sep 17 00:00:00 2001 From: ThibG Date: Tue, 22 May 2018 19:32:02 +0200 Subject: Remove unneeded code now that attachment URL isn't appended to toots (#7593) --- .../mastodon/features/compose/components/compose_form.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index 39eb02362..9cd39be8b 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -104,23 +104,13 @@ export default class ComposeForm extends ImmutablePureComponent { this.props.onChangeSpoilerText(e.target.value); } - componentWillReceiveProps (nextProps) { - // If this is the update where we've finished uploading, - // save the last caret position so we can restore it below! - if (!nextProps.is_uploading && this.props.is_uploading) { - this._restoreCaret = this.autosuggestTextarea.textarea.selectionStart; - } - } - componentDidUpdate (prevProps) { // This statement does several things: // - If we're beginning a reply, and, // - Replying to zero or one users, places the cursor at the end of the textbox. // - Replying to more than one user, selects any usernames past the first; // this provides a convenient shortcut to drop everyone else from the conversation. - // - If we've just finished uploading an image, and have a saved caret position, - // restores the cursor to that position after the text changes! - if (this.props.focusDate !== prevProps.focusDate || (prevProps.is_uploading && !this.props.is_uploading && typeof this._restoreCaret === 'number')) { + if (this.props.focusDate !== prevProps.focusDate) { let selectionEnd, selectionStart; if (this.props.preselectDate !== prevProps.preselectDate) { -- cgit From d8864b9e9d4fd56606a3b809bedeb1216b6620ae Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 23 May 2018 15:20:15 +0200 Subject: Fix caret position after selected suggestion and media upload (#7595) * Fix media upload reseting caret position to last inserted emoji * Fix caret position after inserting suggestions (fixes #6089) --- .../mastodon/features/compose/components/compose_form.js | 10 ++++------ .../features/compose/containers/compose_form_container.js | 1 + app/javascript/mastodon/reducers/compose.js | 7 ++++++- 3 files changed, 11 insertions(+), 7 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index 9cd39be8b..6cc594c88 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -40,6 +40,7 @@ export default class ComposeForm extends ImmutablePureComponent { privacy: PropTypes.string, spoiler_text: PropTypes.string, focusDate: PropTypes.instanceOf(Date), + caretPosition: PropTypes.number, preselectDate: PropTypes.instanceOf(Date), is_submitting: PropTypes.bool, is_uploading: PropTypes.bool, @@ -96,7 +97,6 @@ export default class ComposeForm extends ImmutablePureComponent { } onSuggestionSelected = (tokenStart, token, value) => { - this._restoreCaret = null; this.props.onSuggestionSelected(tokenStart, token, value); } @@ -116,9 +116,9 @@ export default class ComposeForm extends ImmutablePureComponent { if (this.props.preselectDate !== prevProps.preselectDate) { selectionEnd = this.props.text.length; selectionStart = this.props.text.search(/\s/) + 1; - } else if (typeof this._restoreCaret === 'number') { - selectionStart = this._restoreCaret; - selectionEnd = this._restoreCaret; + } else if (typeof this.props.caretPosition === 'number') { + selectionStart = this.props.caretPosition; + selectionEnd = this.props.caretPosition; } else { selectionEnd = this.props.text.length; selectionStart = selectionEnd; @@ -138,10 +138,8 @@ export default class ComposeForm extends ImmutablePureComponent { handleEmojiPick = (data) => { const { text } = this.props; const position = this.autosuggestTextarea.textarea.selectionStart; - const emojiChar = data.native; const needsSpace = data.custom && position > 0 && !allowedAroundShortCode.includes(text[position - 1]); - this._restoreCaret = position + emojiChar.length + 1 + (needsSpace ? 1 : 0); this.props.onPickEmoji(position, data, needsSpace); } diff --git a/app/javascript/mastodon/features/compose/containers/compose_form_container.js b/app/javascript/mastodon/features/compose/containers/compose_form_container.js index c3aa580ee..3822dd711 100644 --- a/app/javascript/mastodon/features/compose/containers/compose_form_container.js +++ b/app/javascript/mastodon/features/compose/containers/compose_form_container.js @@ -19,6 +19,7 @@ const mapStateToProps = state => ({ spoiler_text: state.getIn(['compose', 'spoiler_text']), privacy: state.getIn(['compose', 'privacy']), focusDate: state.getIn(['compose', 'focusDate']), + caretPosition: state.getIn(['compose', 'caretPosition']), preselectDate: state.getIn(['compose', 'preselectDate']), is_submitting: state.getIn(['compose', 'is_submitting']), is_uploading: state.getIn(['compose', 'is_uploading']), diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js index 46d9d6c8e..62461d1a7 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -44,6 +44,7 @@ const initialState = ImmutableMap({ privacy: null, text: '', focusDate: null, + caretPosition: null, preselectDate: null, in_reply_to: null, is_composing: false, @@ -91,7 +92,6 @@ function appendMedia(state, media) { map.update('media_attachments', list => list.push(media)); map.set('is_uploading', false); map.set('resetFileKey', Math.floor((Math.random() * 0x10000))); - map.set('focusDate', new Date()); map.set('idempotencyKey', uuid()); if (prevSize === 0 && (state.get('default_sensitive') || state.get('spoiler'))) { @@ -119,6 +119,7 @@ const insertSuggestion = (state, position, token, completion) => { map.set('suggestion_token', null); map.update('suggestions', ImmutableList(), list => list.clear()); map.set('focusDate', new Date()); + map.set('caretPosition', position + completion.length + 1); map.set('idempotencyKey', uuid()); }); }; @@ -142,6 +143,7 @@ const insertEmoji = (state, position, emojiData, needsSpace) => { return state.merge({ text: `${oldText.slice(0, position)}${emoji} ${oldText.slice(position)}`, focusDate: new Date(), + caretPosition: position + emoji.length + 1, idempotencyKey: uuid(), }); }; @@ -216,6 +218,7 @@ export default function compose(state = initialState, action) { map.set('text', statusToTextMentions(state, action.status)); map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy'))); map.set('focusDate', new Date()); + map.set('caretPosition', null); map.set('preselectDate', new Date()); map.set('idempotencyKey', uuid()); @@ -259,6 +262,7 @@ export default function compose(state = initialState, action) { 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('caretPosition', null); map.set('idempotencyKey', uuid()); }); case COMPOSE_DIRECT: @@ -266,6 +270,7 @@ export default function compose(state = initialState, action) { 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('caretPosition', null); map.set('idempotencyKey', uuid()); }); case COMPOSE_SUGGESTIONS_CLEAR: -- cgit