diff options
Diffstat (limited to 'app/javascript/flavours/glitch')
12 files changed, 150 insertions, 83 deletions
diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 21f0e3a6f..8a5fda676 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -67,7 +67,6 @@ class Status extends ImmutablePureComponent { containerId: PropTypes.string, id: PropTypes.string, status: ImmutablePropTypes.map, - otherAccounts: ImmutablePropTypes.list, account: ImmutablePropTypes.map, onReply: PropTypes.func, onFavourite: PropTypes.func, @@ -100,6 +99,7 @@ class Status extends ImmutablePureComponent { scrollKey: PropTypes.string, deployPictureInPicture: PropTypes.func, usingPiP: PropTypes.bool, + settings: ImmutablePropTypes.map.isRequired, }; state = { @@ -491,7 +491,6 @@ class Status extends ImmutablePureComponent { intl, status, account, - otherAccounts, settings, collapsed, muted, @@ -744,7 +743,6 @@ class Status extends ImmutablePureComponent { friend={account} collapsed={isCollapsed} parseClick={parseClick} - otherAccounts={otherAccounts} /> ) : null} </span> @@ -754,7 +752,7 @@ class Status extends ImmutablePureComponent { collapsible={settings.getIn(['collapsed', 'enabled'])} collapsed={isCollapsed} setCollapsed={setCollapsed} - directMessage={!!otherAccounts} + settings={settings.get('status_icons')} /> </header> <StatusContent @@ -774,7 +772,6 @@ class Status extends ImmutablePureComponent { status={status} account={status.get('account')} showReplyCount={settings.get('show_reply_count')} - directMessage={!!otherAccounts} onFilter={this.handleFilterClick} /> ) : null} diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js index 68d93cd67..0a5c5b69d 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.js @@ -67,7 +67,6 @@ class StatusActionBar extends ImmutablePureComponent { onFilter: PropTypes.func, withDismiss: PropTypes.bool, showReplyCount: PropTypes.bool, - directMessage: PropTypes.bool, scrollKey: PropTypes.string, intl: PropTypes.object.isRequired, }; @@ -197,7 +196,7 @@ class StatusActionBar extends ImmutablePureComponent { } render () { - const { status, intl, withDismiss, showReplyCount, directMessage, scrollKey } = this.props; + const { status, intl, withDismiss, showReplyCount, scrollKey } = this.props; const anonymousAccess = !me; const mutingConversation = status.get('muted'); @@ -311,25 +310,24 @@ class StatusActionBar extends ImmutablePureComponent { return ( <div className='status__action-bar'> {replyButton} - {!directMessage && [ - <IconButton key='reblog-button' className={classNames('status__action-bar-button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} pressed={status.get('reblogged')} title={reblogTitle} icon={reblogIcon} onClick={this.handleReblogClick} />, - <IconButton key='favourite-button' className='status__action-bar-button star-icon' animate active={status.get('favourited')} pressed={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} />, - shareButton, - <IconButton key='bookmark-button' className='status__action-bar-button bookmark-icon' disabled={anonymousAccess} active={status.get('bookmarked')} pressed={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} />, - filterButton, - <div key='dropdown-button' className='status__action-bar-dropdown'> - <DropdownMenuContainer - scrollKey={scrollKey} - disabled={anonymousAccess} - status={status} - items={menu} - icon='ellipsis-h' - size={18} - direction='right' - ariaLabel={intl.formatMessage(messages.more)} - /> - </div>, - ]} + <IconButton className={classNames('status__action-bar-button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} pressed={status.get('reblogged')} title={reblogTitle} icon={reblogIcon} onClick={this.handleReblogClick} /> + <IconButton className='status__action-bar-button star-icon' animate active={status.get('favourited')} pressed={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} /> + {shareButton} + <IconButton className='status__action-bar-button bookmark-icon' disabled={anonymousAccess} active={status.get('bookmarked')} pressed={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} /> + {filterButton} + + <div className='status__action-bar-dropdown'> + <DropdownMenuContainer + scrollKey={scrollKey} + disabled={anonymousAccess} + status={status} + items={menu} + icon='ellipsis-h' + size={18} + direction='right' + ariaLabel={intl.formatMessage(messages.more)} + /> + </div> <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener'> <RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { hour12: false, year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>} diff --git a/app/javascript/flavours/glitch/components/status_content.js b/app/javascript/flavours/glitch/components/status_content.js index 1d32b35e5..6a027f8d2 100644 --- a/app/javascript/flavours/glitch/components/status_content.js +++ b/app/javascript/flavours/glitch/components/status_content.js @@ -267,6 +267,7 @@ export default class StatusContent extends React.PureComponent { const content = { __html: status.get('contentHtml') }; const spoilerContent = { __html: status.get('spoilerHtml') }; + const lang = status.get('language'); const classNames = classnames('status__content', { 'status__content--with-action': parseClick && !disabled, 'status__content--with-spoiler': status.get('spoiler_text').length > 0, @@ -327,7 +328,7 @@ export default class StatusContent extends React.PureComponent { <p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }} > - <span dangerouslySetInnerHTML={spoilerContent} className='translate' /> + <span dangerouslySetInnerHTML={spoilerContent} className='translate' lang={lang} /> {' '} <button tabIndex='0' className='status__content__spoiler-link' onClick={this.handleSpoilerClick}> {toggleText} @@ -345,6 +346,7 @@ export default class StatusContent extends React.PureComponent { className='status__content__text translate' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} + lang={lang} /> {media} </div> @@ -367,6 +369,7 @@ export default class StatusContent extends React.PureComponent { tabIndex='0' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} + lang={lang} /> {media} </div> @@ -385,6 +388,7 @@ export default class StatusContent extends React.PureComponent { tabIndex='0' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} + lang={lang} /> {media} </div> diff --git a/app/javascript/flavours/glitch/components/status_header.js b/app/javascript/flavours/glitch/components/status_header.js index cc476139b..990dea536 100644 --- a/app/javascript/flavours/glitch/components/status_header.js +++ b/app/javascript/flavours/glitch/components/status_header.js @@ -15,7 +15,6 @@ export default class StatusHeader extends React.PureComponent { status: ImmutablePropTypes.map.isRequired, friend: ImmutablePropTypes.map, parseClick: PropTypes.func.isRequired, - otherAccounts: ImmutablePropTypes.list, }; // Handles clicks on account name/image @@ -34,57 +33,39 @@ export default class StatusHeader extends React.PureComponent { const { status, friend, - otherAccounts, } = this.props; const account = status.get('account'); let statusAvatar; - if (otherAccounts && otherAccounts.size > 0) { - statusAvatar = <AvatarComposite accounts={otherAccounts} size={48} onAccountClick={this.handleClick} />; - } else if (friend === undefined || friend === null) { + if (friend === undefined || friend === null) { statusAvatar = <Avatar account={account} size={48} />; } else { statusAvatar = <AvatarOverlay account={account} friend={friend} />; } - if (!otherAccounts) { - return ( - <div className='status__info__account'> - <a - href={account.get('url')} - target='_blank' - className='status__avatar' - onClick={this.handleAccountClick} - rel='noopener noreferrer' - > - {statusAvatar} - </a> - <a - href={account.get('url')} - target='_blank' - className='status__display-name' - onClick={this.handleAccountClick} - rel='noopener noreferrer' - > - <DisplayName account={account} others={otherAccounts} /> - </a> - </div> - ); - } else { - // This is a DM conversation - return ( - <div className='status__info__account'> - <span className='status__avatar'> - {statusAvatar} - </span> - - <span className='status__display-name'> - <DisplayName account={account} others={otherAccounts} onAccountClick={this.handleClick} /> - </span> - </div> - ); - } + return ( + <div className='status__info__account'> + <a + href={account.get('url')} + target='_blank' + className='status__avatar' + onClick={this.handleAccountClick} + rel='noopener noreferrer' + > + {statusAvatar} + </a> + <a + href={account.get('url')} + target='_blank' + className='status__display-name' + onClick={this.handleAccountClick} + rel='noopener noreferrer' + > + <DisplayName account={account} /> + </a> + </div> + ); } } diff --git a/app/javascript/flavours/glitch/components/status_icons.js b/app/javascript/flavours/glitch/components/status_icons.js index e66947f4a..2226aaef2 100644 --- a/app/javascript/flavours/glitch/components/status_icons.js +++ b/app/javascript/flavours/glitch/components/status_icons.js @@ -8,6 +8,7 @@ import { defineMessages, injectIntl } from 'react-intl'; import IconButton from './icon_button'; import VisibilityIcon from './status_visibility_icon'; import Icon from 'flavours/glitch/components/icon'; +import { languages } from 'flavours/glitch/util/initial_state'; // Messages for use with internationalization stuff. const messages = defineMessages({ @@ -22,6 +23,23 @@ const messages = defineMessages({ localOnly: { id: 'status.local_only', defaultMessage: 'Only visible from your instance' }, }); +const LanguageIcon = ({ language }) => { + if (!languages) return null; + + const lang = languages.find((lang) => lang[0] === language); + if (!lang) return null; + + return ( + <span className='text-icon' title={`${lang[2]} (${lang[1]})`} aria-hidden='true'> + {lang[0].toUpperCase()} + </span> + ); +}; + +LanguageIcon.propTypes = { + language: PropTypes.string.isRequired, +}; + export default @injectIntl class StatusIcons extends React.PureComponent { @@ -30,9 +48,9 @@ class StatusIcons extends React.PureComponent { mediaIcons: PropTypes.arrayOf(PropTypes.string), collapsible: PropTypes.bool, collapsed: PropTypes.bool, - directMessage: PropTypes.bool, setCollapsed: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, + settings: ImmutablePropTypes.map.isRequired, }; // Handles clicks on collapsed button @@ -81,13 +99,14 @@ class StatusIcons extends React.PureComponent { mediaIcons, collapsible, collapsed, - directMessage, + settings, intl, } = this.props; return ( <div className='status__info__icons'> - {status.get('in_reply_to_id', null) !== null ? ( + {settings.get('language') && status.get('language') && <LanguageIcon language={status.get('language')} />} + {settings.get('reply') && status.get('in_reply_to_id', null) !== null ? ( <Icon className='status__reply-icon' fixedWidth @@ -96,16 +115,16 @@ class StatusIcons extends React.PureComponent { title={intl.formatMessage(messages.inReplyTo)} /> ) : null} - {status.get('local_only') && + {settings.get('local_only') && status.get('local_only') && <Icon fixedWidth id='home' aria-hidden='true' title={intl.formatMessage(messages.localOnly)} />} - { !!mediaIcons && mediaIcons.map(icon => this.renderIcon(icon)) } - {!directMessage && <VisibilityIcon visibility={status.get('visibility')} />} - {collapsible ? ( + {settings.get('media') && !!mediaIcons && mediaIcons.map(icon => this.renderIcon(icon))} + {settings.get('visibility') && <VisibilityIcon visibility={status.get('visibility')} />} + {collapsible && ( <IconButton className='status__collapse-button' animate @@ -118,7 +137,7 @@ class StatusIcons extends React.PureComponent { icon='angle-double-up' onClick={this.handleCollapsedClick} /> - ) : null} + )} </div> ); } diff --git a/app/javascript/flavours/glitch/features/compose/components/publisher.js b/app/javascript/flavours/glitch/features/compose/components/publisher.js index 9a8c0f510..e2498bcad 100644 --- a/app/javascript/flavours/glitch/features/compose/components/publisher.js +++ b/app/javascript/flavours/glitch/features/compose/components/publisher.js @@ -16,7 +16,7 @@ import { maxChars } from 'flavours/glitch/util/initial_state'; // Messages. const messages = defineMessages({ publish: { - defaultMessage: 'Toot', + defaultMessage: 'Publish', id: 'compose_form.publish', }, publishLoud: { diff --git a/app/javascript/flavours/glitch/features/local_settings/page/index.js b/app/javascript/flavours/glitch/features/local_settings/page/index.js index 4b86a8f6f..2490b6e2d 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js @@ -117,6 +117,50 @@ class LocalSettingsPage extends React.PureComponent { <span className='hint'><FormattedMessage id='settings.notifications.favicon_badge.hint' defaultMessage="Add a badge for unread notifications to the favicon" /></span> </LocalSettingsPageItem> </section> + + <section> + <h2><FormattedMessage id='settings.status_icons' defaultMessage='Toot icons' /></h2> + <LocalSettingsPageItem + settings={settings} + item={['status_icons', 'language']} + id='mastodon-settings--status-icons-language' + onChange={onChange} + > + <FormattedMessage id='settings.status_icons_language' defaultMessage='Language indicator' /> + </LocalSettingsPageItem> + <LocalSettingsPageItem + settings={settings} + item={['status_icons', 'reply']} + id='mastodon-settings--status-icons-reply' + onChange={onChange} + > + <FormattedMessage id='settings.status_icons_reply' defaultMessage='Reply indicator' /> + </LocalSettingsPageItem> + <LocalSettingsPageItem + settings={settings} + item={['status_icons', 'local_only']} + id='mastodon-settings--status-icons-local_only' + onChange={onChange} + > + <FormattedMessage id='settings.status_icons_local_only' defaultMessage='Local-only indicator' /> + </LocalSettingsPageItem> + <LocalSettingsPageItem + settings={settings} + item={['status_icons', 'media']} + id='mastodon-settings--status-icons-media' + onChange={onChange} + > + <FormattedMessage id='settings.status_icons_media' defaultMessage='Media and poll indicators' /> + </LocalSettingsPageItem> + <LocalSettingsPageItem + settings={settings} + item={['status_icons', 'visibility']} + id='mastodon-settings--status-icons-visibility' + onChange={onChange} + > + <FormattedMessage id='settings.status_icons_visibility' defaultMessage='Toot privacy indicator' /> + </LocalSettingsPageItem> + </section> <section> <h2><FormattedMessage id='settings.layout_opts' defaultMessage='Layout options' /></h2> <LocalSettingsPageItem diff --git a/app/javascript/flavours/glitch/locales/ko.js b/app/javascript/flavours/glitch/locales/ko.js index b67fec187..a817044c1 100644 --- a/app/javascript/flavours/glitch/locales/ko.js +++ b/app/javascript/flavours/glitch/locales/ko.js @@ -37,7 +37,6 @@ const messages = { 'compose_form.poll.single_choice': '하나만 선택 가능', 'compose_form.spoiler': '경고 메시지로 숨기기', 'confirmation_modal.do_not_ask_again': '다음부터 확인창을 띄우지 않기', - 'confirmations.discard_edit_media.confirm': '취소', 'confirmations.discard_edit_media.message': '저장하지 않은 미디어 설명이나 미리보기가 있습니다, 그냥 닫을까요?', 'confirmations.missing_media_description.confirm': '그냥 보내기', 'confirmations.missing_media_description.edit': '미디어 편집', @@ -119,6 +118,7 @@ const messages = { 'settings.content_warnings': '열람주의', 'settings.content_warnings.regexp': '정규표현식', 'settings.content_warnings_filter': '자동으로 펼치지 않을 열람주의 문구:', + 'settings.deprecated_setting': '이 설정은 마스토돈의 {settings_page_link}에서 관리됩니다', 'settings.enable_collapsed': '접힌 글 활성화', 'settings.enable_content_warnings_auto_unfold': '자동으로 열람주의 펼치기', 'settings.filtering_behavior': '필터링 동작', @@ -159,6 +159,7 @@ const messages = { 'settings.rewrite_mentions_acct': '사용자명과 도메인으로 바꾸기(계정이 원격일 때)', 'settings.rewrite_mentions_no': '멘션을 그대로 두기', 'settings.rewrite_mentions_username': '사용자명으로 바꾸기', + 'settings.shared_settings_link': '사용자 설정', 'settings.show_action_bar': '접힌 글에 액션 버튼들 보이기', 'settings.show_content_type_choice': '글을 작성할 때 콘텐트 타입을 고를 수 있도록 합니다', 'settings.show_reply_counter': '대략적인 답글 개수를 표시합니다', @@ -168,6 +169,12 @@ const messages = { 'settings.side_arm_reply_mode.copy': '답글을 달려는 글의 공개설정을 복사합니다', 'settings.side_arm_reply_mode.keep': '보조 작성 버튼의 공개설정을 유지합니다', 'settings.side_arm_reply_mode.restrict': '답글을 달려는 글의 공개설정에 맞게 제한합니다', + 'settings.status_icons': '게시물 아이콘', + 'settings.status_icons_language': '언어 표시', + 'settings.status_icons_local_only': '로컬 전용 표시', + 'settings.status_icons_media': '미디어와 투표 표시', + 'settings.status_icons_reply': '답글 표시', + 'settings.status_icons_visibility': '툿 공개설정 표시', 'settings.swipe_to_change_columns': '스와이프하여 컬럼간 전환을 허용합니다 (모바일 전용)', 'settings.tag_misleading_links': '오해의 소지가 있는 링크를 표시합니다', 'settings.tag_misleading_links.hint': '링크에 명시적으로 주소가 없는 경우엔 대상 호스트를 보이도록 표시합니다', diff --git a/app/javascript/flavours/glitch/reducers/compose.js b/app/javascript/flavours/glitch/reducers/compose.js index d0aeaa1f0..2ef08b2a6 100644 --- a/app/javascript/flavours/glitch/reducers/compose.js +++ b/app/javascript/flavours/glitch/reducers/compose.js @@ -419,6 +419,10 @@ export default function compose(state = initialState, action) { map.set('preselectDate', new Date()); map.set('idempotencyKey', uuid()); + if (action.status.get('language')) { + map.set('language', action.status.get('language')); + } + if (action.status.get('spoiler_text').length > 0) { let spoiler_text = action.status.get('spoiler_text'); if (action.prependCWRe && !spoiler_text.match(/^re[: ]/i)) { diff --git a/app/javascript/flavours/glitch/reducers/local_settings.js b/app/javascript/flavours/glitch/reducers/local_settings.js index a16c337fc..d4cdc124f 100644 --- a/app/javascript/flavours/glitch/reducers/local_settings.js +++ b/app/javascript/flavours/glitch/reducers/local_settings.js @@ -54,6 +54,13 @@ const initialState = ImmutableMap({ favicon_badge : false, tab_badge : true, }), + status_icons : ImmutableMap({ + language: true, + reply: true, + local_only: true, + media: true, + visibility: true, + }), }); const hydrate = (state, localSettings) => state.mergeDeep(localSettings); diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index 373280fc4..da9fb6ad2 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -239,16 +239,21 @@ } } +.text-icon, +.text-icon-button { + font-weight: 600; + font-size: 11px; + line-height: 27px; + cursor: default; +} + .text-icon-button { color: $lighter-text-color; border: 0; border-radius: 4px; background: transparent; cursor: pointer; - font-weight: 600; - font-size: 11px; padding: 0 3px; - line-height: 27px; outline: 0; transition: all 100ms ease-in; transition-property: background-color, color; diff --git a/app/javascript/flavours/glitch/styles/components/status.scss b/app/javascript/flavours/glitch/styles/components/status.scss index d7c8f2716..fe3829fdd 100644 --- a/app/javascript/flavours/glitch/styles/components/status.scss +++ b/app/javascript/flavours/glitch/styles/components/status.scss @@ -492,7 +492,8 @@ .status__media-icon, .status__visibility-icon, - .status__reply-icon { + .status__reply-icon, + .text-icon { padding-left: 2px; padding-right: 2px; } |