about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch/components
diff options
context:
space:
mode:
authorReverite <github@reverite.sh>2019-07-20 18:46:40 -0700
committerReverite <github@reverite.sh>2019-07-20 18:46:40 -0700
commit266540080ef5659060faa7da502123f45bbc04f2 (patch)
tree1c34751dd4e199737b7a2a4c511b756760941c52 /app/javascript/flavours/glitch/components
parent40fd56351f0a466e0e3785cca4ee27f2a9060e8a (diff)
parentf1597e1ab90b1fb291f16977877c6ca79bf89676 (diff)
Merge branch 'glitch' into production
Diffstat (limited to 'app/javascript/flavours/glitch/components')
-rw-r--r--app/javascript/flavours/glitch/components/load_pending.js22
-rw-r--r--app/javascript/flavours/glitch/components/scrollable_list.js13
-rw-r--r--app/javascript/flavours/glitch/components/status.js5
-rw-r--r--app/javascript/flavours/glitch/components/status_icons.js32
4 files changed, 69 insertions, 3 deletions
diff --git a/app/javascript/flavours/glitch/components/load_pending.js b/app/javascript/flavours/glitch/components/load_pending.js
new file mode 100644
index 000000000..7e2702403
--- /dev/null
+++ b/app/javascript/flavours/glitch/components/load_pending.js
@@ -0,0 +1,22 @@
+import React from 'react';
+import { FormattedMessage } from 'react-intl';
+import PropTypes from 'prop-types';
+
+export default class LoadPending extends React.PureComponent {
+
+  static propTypes = {
+    onClick: PropTypes.func,
+    count: PropTypes.number,
+  }
+
+  render() {
+    const { count } = this.props;
+
+    return (
+      <button className='load-more load-gap' onClick={this.props.onClick}>
+        <FormattedMessage id='load_pending' defaultMessage='{count, plural, one {# new item} other {# new items}}' values={{ count }} />
+      </button>
+    );
+  }
+
+}
diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js
index 462185bbc..5f42bdd8b 100644
--- a/app/javascript/flavours/glitch/components/scrollable_list.js
+++ b/app/javascript/flavours/glitch/components/scrollable_list.js
@@ -3,6 +3,7 @@ import { ScrollContainer } from 'react-router-scroll-4';
 import PropTypes from 'prop-types';
 import IntersectionObserverArticleContainer from 'flavours/glitch/containers/intersection_observer_article_container';
 import LoadMore from './load_more';
+import LoadPending from './load_pending';
 import IntersectionObserverWrapper from 'flavours/glitch/util/intersection_observer_wrapper';
 import { throttle } from 'lodash';
 import { List as ImmutableList } from 'immutable';
@@ -21,6 +22,7 @@ export default class ScrollableList extends PureComponent {
   static propTypes = {
     scrollKey: PropTypes.string.isRequired,
     onLoadMore: PropTypes.func,
+    onLoadPending: PropTypes.func,
     onScrollToTop: PropTypes.func,
     onScroll: PropTypes.func,
     trackScroll: PropTypes.bool,
@@ -28,6 +30,7 @@ export default class ScrollableList extends PureComponent {
     isLoading: PropTypes.bool,
     showLoading: PropTypes.bool,
     hasMore: PropTypes.bool,
+    numPending: PropTypes.number,
     prepend: PropTypes.node,
     alwaysPrepend: PropTypes.bool,
     emptyMessage: PropTypes.node,
@@ -222,12 +225,18 @@ export default class ScrollableList extends PureComponent {
     return !(location.state && location.state.mastodonModalOpen);
   }
 
+  handleLoadPending = e => {
+    e.preventDefault();
+    this.props.onLoadPending();
+  }
+
   render () {
-    const { children, scrollKey, trackScroll, shouldUpdateScroll, showLoading, isLoading, hasMore, prepend, alwaysPrepend, emptyMessage, onLoadMore } = this.props;
+    const { children, scrollKey, trackScroll, shouldUpdateScroll, showLoading, isLoading, hasMore, numPending, prepend, alwaysPrepend, emptyMessage, onLoadMore } = this.props;
     const { fullscreen } = this.state;
     const childrenCount = React.Children.count(children);
 
     const loadMore     = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null;
+    const loadPending  = (numPending > 0) ? <LoadPending count={numPending} onClick={this.handleLoadPending} /> : null;
     let scrollableArea = null;
 
     if (showLoading) {
@@ -248,6 +257,8 @@ export default class ScrollableList extends PureComponent {
           <div role='feed' className='item-list'>
             {prepend}
 
+            {loadPending}
+
             {React.Children.map(this.props.children, (child, index) => (
               <IntersectionObserverArticleContainer
                 key={child.key}
diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js
index e94ce6dfe..7c08ae4e8 100644
--- a/app/javascript/flavours/glitch/components/status.js
+++ b/app/javascript/flavours/glitch/components/status.js
@@ -476,7 +476,7 @@ class Status extends ImmutablePureComponent {
       featured,
       ...other
     } = this.props;
-    const { isExpanded, isCollapsed } = this.state;
+    const { isExpanded, isCollapsed, forceFilter } = this.state;
     let background = null;
     let attachments = null;
     let media = null;
@@ -496,7 +496,8 @@ class Status extends ImmutablePureComponent {
       );
     }
 
-    if ((status.get('filtered') || status.getIn(['reblog', 'filtered'])) && (this.state.forceFilter === true || settings.get('filtering_behavior') !== 'content_warning')) {
+    const filtered = (status.get('filtered') || status.getIn(['reblog', 'filtered'])) && settings.get('filtering_behavior') !== 'content_warning';
+    if (forceFilter === undefined ? filtered : forceFilter) {
       const minHandlers = this.props.muted ? {} : {
         moveUp: this.handleHotkeyMoveUp,
         moveDown: this.handleHotkeyMoveDown,
diff --git a/app/javascript/flavours/glitch/components/status_icons.js b/app/javascript/flavours/glitch/components/status_icons.js
index 4a2c62881..3dcfade3f 100644
--- a/app/javascript/flavours/glitch/components/status_icons.js
+++ b/app/javascript/flavours/glitch/components/status_icons.js
@@ -12,6 +12,13 @@ import VisibilityIcon from './status_visibility_icon';
 const messages = defineMessages({
   collapse: { id: 'status.collapse', defaultMessage: 'Collapse' },
   uncollapse: { id: 'status.uncollapse', defaultMessage: 'Uncollapse' },
+  inReplyTo: { id: 'status.in_reply_to', defaultMessage: 'This toot is a reply' },
+  previewCard: { id: 'status.has_preview_card', defaultMessage: 'Features an attached preview card' },
+  pictures: { id: 'status.has_pictures', defaultMessage: 'Features attached pictures' },
+  poll: { id: 'status.is_poll', defaultMessage: 'This toot is a poll' },
+  video: { id: 'status.has_video', defaultMessage: 'Features attached videos' },
+  audio: { id: 'status.has_audio', defaultMessage: 'Features attached audio files' },
+  localOnly: { id: 'status.local_only', defaultMessage: 'Only visible from your instance' },
 });
 
 @injectIntl
@@ -36,6 +43,23 @@ export default class StatusIcons extends React.PureComponent {
     }
   }
 
+  mediaIconTitleText () {
+    const { intl, mediaIcon } = this.props;
+
+    switch (mediaIcon) {
+      case 'link':
+        return intl.formatMessage(messages.previewCard);
+      case 'picture-o':
+        return intl.formatMessage(messages.pictures);
+      case 'tasks':
+        return intl.formatMessage(messages.poll);
+      case 'video-camera':
+        return intl.formatMessage(messages.video);
+      case 'music':
+        return intl.formatMessage(messages.audio);
+    }
+  }
+
   //  Rendering.
   render () {
     const {
@@ -53,12 +77,20 @@ export default class StatusIcons extends React.PureComponent {
           <i
             className={`fa fa-fw fa-comment status__reply-icon`}
             aria-hidden='true'
+            title={intl.formatMessage(messages.inReplyTo)}
           />
         ) : null}
+        {status.get('local_only') &&
+          <i
+            className={`fa fa-fw fa-home`}
+            aria-hidden='true'
+            title={intl.formatMessage(messages.localOnly)}
+          />}
         {mediaIcon ? (
           <i
             className={`fa fa-fw fa-${mediaIcon} status__media-icon`}
             aria-hidden='true'
+            title={this.mediaIconTitleText()}
           />
         ) : null}
         {!directMessage && <VisibilityIcon visibility={status.get('visibility')} />}