about summary refs log tree commit diff
path: root/app/javascript/flavours
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/flavours')
-rw-r--r--app/javascript/flavours/glitch/components/status.js7
-rw-r--r--app/javascript/flavours/glitch/components/status_action_bar.js40
-rw-r--r--app/javascript/flavours/glitch/components/status_content.js6
-rw-r--r--app/javascript/flavours/glitch/components/status_header.js65
-rw-r--r--app/javascript/flavours/glitch/components/status_icons.js35
-rw-r--r--app/javascript/flavours/glitch/features/compose/components/publisher.js2
-rw-r--r--app/javascript/flavours/glitch/features/local_settings/page/index.js44
-rw-r--r--app/javascript/flavours/glitch/locales/ko.js9
-rw-r--r--app/javascript/flavours/glitch/reducers/compose.js4
-rw-r--r--app/javascript/flavours/glitch/reducers/local_settings.js7
-rw-r--r--app/javascript/flavours/glitch/styles/components/index.scss11
-rw-r--r--app/javascript/flavours/glitch/styles/components/status.scss3
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;
   }