about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/javascript/flavours/glitch/components/dismissable_banner.js51
-rw-r--r--app/javascript/flavours/glitch/features/about/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/community_timeline/index.js9
-rw-r--r--app/javascript/flavours/glitch/features/directory/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/explore/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/explore/links.js11
-rw-r--r--app/javascript/flavours/glitch/features/explore/results.js3
-rw-r--r--app/javascript/flavours/glitch/features/explore/statuses.js29
-rw-r--r--app/javascript/flavours/glitch/features/explore/tags.js11
-rw-r--r--app/javascript/flavours/glitch/features/hashtag_timeline/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/home_timeline/index.js5
-rw-r--r--app/javascript/flavours/glitch/features/notifications/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/privacy_policy/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/public_timeline/index.js8
-rw-r--r--app/javascript/flavours/glitch/settings.js1
-rw-r--r--app/javascript/flavours/glitch/styles/components/columns.scss25
16 files changed, 139 insertions, 32 deletions
diff --git a/app/javascript/flavours/glitch/components/dismissable_banner.js b/app/javascript/flavours/glitch/components/dismissable_banner.js
new file mode 100644
index 000000000..ff52a619d
--- /dev/null
+++ b/app/javascript/flavours/glitch/components/dismissable_banner.js
@@ -0,0 +1,51 @@
+import React from 'react';
+import IconButton from './icon_button';
+import PropTypes from 'prop-types';
+import { injectIntl, defineMessages } from 'react-intl';
+import { bannerSettings } from 'flavours/glitch/settings';
+
+const messages = defineMessages({
+  dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' },
+});
+
+export default @injectIntl
+class DismissableBanner extends React.PureComponent {
+
+  static propTypes = {
+    id: PropTypes.string.isRequired,
+    children: PropTypes.node,
+    intl: PropTypes.object.isRequired,
+  };
+
+  state = {
+    visible: !bannerSettings.get(this.props.id),
+  };
+
+  handleDismiss = () => {
+    const { id } = this.props;
+    this.setState({ visible: false }, () => bannerSettings.set(id, true));
+  }
+
+  render () {
+    const { visible } = this.state;
+
+    if (!visible) {
+      return null;
+    }
+
+    const { children, intl } = this.props;
+
+    return (
+      <div className='dismissable-banner'>
+        <div className='dismissable-banner__message'>
+          {children}
+        </div>
+
+        <div className='dismissable-banner__action'>
+          <IconButton icon='times' title={intl.formatMessage(messages.dismiss)} onClick={this.handleDismiss} />
+        </div>
+      </div>
+    );
+  }
+
+}
diff --git a/app/javascript/flavours/glitch/features/about/index.js b/app/javascript/flavours/glitch/features/about/index.js
index 9f7c90d91..4500480f5 100644
--- a/app/javascript/flavours/glitch/features/about/index.js
+++ b/app/javascript/flavours/glitch/features/about/index.js
@@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
 import Column from 'flavours/glitch/components/column';
 import LinkFooter from 'flavours/glitch/features/ui/components/link_footer';
 import { Helmet } from 'react-helmet';
-import { title } from 'flavours/glitch/initial_state';
 
 const messages = defineMessages({
   title: { id: 'column.about', defaultMessage: 'About' },
@@ -25,7 +24,7 @@ class About extends React.PureComponent {
         <LinkFooter />
 
         <Helmet>
-          <title>{intl.formatMessage(messages.title)} - {title}</title>
+          <title>{intl.formatMessage(messages.title)}</title>
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/flavours/glitch/features/community_timeline/index.js b/app/javascript/flavours/glitch/features/community_timeline/index.js
index 5ee46ca3b..77809574d 100644
--- a/app/javascript/flavours/glitch/features/community_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/community_timeline/index.js
@@ -10,7 +10,8 @@ import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/col
 import ColumnSettingsContainer from './containers/column_settings_container';
 import { connectCommunityStream } from 'flavours/glitch/actions/streaming';
 import { Helmet } from 'react-helmet';
-import { title } from 'flavours/glitch/initial_state';
+import { domain } from 'flavours/glitch/initial_state';
+import DismissableBanner from 'flavours/glitch/components/dismissable_banner';
 
 const messages = defineMessages({
   title: { id: 'column.community', defaultMessage: 'Local timeline' },
@@ -138,6 +139,10 @@ class CommunityTimeline extends React.PureComponent {
           <ColumnSettingsContainer columnId={columnId} />
         </ColumnHeader>
 
+        <DismissableBanner id='community_timeline'>
+          <FormattedMessage id='dismissable_banner.community_timeline' defaultMessage='These are the most recent public posts from people whose accounts are hosted by {domain}.' values={{ domain }} />
+        </DismissableBanner>
+
         <StatusListContainer
           trackScroll={!pinned}
           scrollKey={`community_timeline-${columnId}`}
@@ -149,7 +154,7 @@ class CommunityTimeline extends React.PureComponent {
         />
 
         <Helmet>
-          <title>{intl.formatMessage(messages.title)} - {title}</title>
+          <title>{intl.formatMessage(messages.title)}</title>
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/flavours/glitch/features/directory/index.js b/app/javascript/flavours/glitch/features/directory/index.js
index dce8fa4e7..672a11430 100644
--- a/app/javascript/flavours/glitch/features/directory/index.js
+++ b/app/javascript/flavours/glitch/features/directory/index.js
@@ -13,7 +13,6 @@ import RadioButton from 'flavours/glitch/components/radio_button';
 import LoadMore from 'flavours/glitch/components/load_more';
 import ScrollContainer from 'flavours/glitch/containers/scroll_container';
 import LoadingIndicator from 'flavours/glitch/components/loading_indicator';
-import { title } from 'flavours/glitch/initial_state';
 import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
@@ -169,7 +168,7 @@ class Directory extends React.PureComponent {
         {multiColumn && !pinned ? <ScrollContainer scrollKey='directory'>{scrollableArea}</ScrollContainer> : scrollableArea}
 
         <Helmet>
-          <title>{intl.formatMessage(messages.title)} - {title}</title>
+          <title>{intl.formatMessage(messages.title)}</title>
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/flavours/glitch/features/explore/index.js b/app/javascript/flavours/glitch/features/explore/index.js
index f37793732..934e309f8 100644
--- a/app/javascript/flavours/glitch/features/explore/index.js
+++ b/app/javascript/flavours/glitch/features/explore/index.js
@@ -13,7 +13,6 @@ import Search from 'flavours/glitch/features/compose/containers/search_container
 import SearchResults from './results';
 import { showTrends } from 'flavours/glitch/initial_state';
 import { Helmet } from 'react-helmet';
-import { title } from 'flavours/glitch/initial_state';
 
 const messages = defineMessages({
   title: { id: 'explore.title', defaultMessage: 'Explore' },
@@ -85,7 +84,7 @@ class Explore extends React.PureComponent {
               </Switch>
 
               <Helmet>
-                <title>{intl.formatMessage(messages.title)} - {title}</title>
+                <title>{intl.formatMessage(messages.title)}</title>
               </Helmet>
             </React.Fragment>
           )}
diff --git a/app/javascript/flavours/glitch/features/explore/links.js b/app/javascript/flavours/glitch/features/explore/links.js
index 6adc2f6fb..092f86b29 100644
--- a/app/javascript/flavours/glitch/features/explore/links.js
+++ b/app/javascript/flavours/glitch/features/explore/links.js
@@ -6,6 +6,7 @@ import LoadingIndicator from 'flavours/glitch/components/loading_indicator';
 import { connect } from 'react-redux';
 import { fetchTrendingLinks } from 'flavours/glitch/actions/trends';
 import { FormattedMessage } from 'react-intl';
+import DismissableBanner from 'flavours/glitch/components/dismissable_banner';
 
 const mapStateToProps = state => ({
   links: state.getIn(['trends', 'links', 'items']),
@@ -29,9 +30,17 @@ class Links extends React.PureComponent {
   render () {
     const { isLoading, links } = this.props;
 
+    const banner = (
+      <DismissableBanner id='explore/links'>
+        <FormattedMessage id='dismissable_banner.explore_links' defaultMessage='These news stories are being talked about by people on this and other servers of the decentralized network right now.' />
+      </DismissableBanner>
+    );
+
     if (!isLoading && links.isEmpty()) {
       return (
         <div className='explore__links scrollable scrollable--flex'>
+          {banner}
+
           <div className='empty-column-indicator'>
             <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />
           </div>
@@ -41,6 +50,8 @@ class Links extends React.PureComponent {
 
     return (
       <div className='explore__links'>
+        {banner}
+
         {isLoading ? (<LoadingIndicator />) : links.map(link => (
           <Story
             key={link.get('id')}
diff --git a/app/javascript/flavours/glitch/features/explore/results.js b/app/javascript/flavours/glitch/features/explore/results.js
index e37379686..892980d95 100644
--- a/app/javascript/flavours/glitch/features/explore/results.js
+++ b/app/javascript/flavours/glitch/features/explore/results.js
@@ -10,7 +10,6 @@ import { ImmutableHashtag as Hashtag } from 'flavours/glitch/components/hashtag'
 import { List as ImmutableList } from 'immutable';
 import LoadMore from 'flavours/glitch/components/load_more';
 import LoadingIndicator from 'flavours/glitch/components/loading_indicator';
-import { title } from 'flavours/glitch/initial_state';
 import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
@@ -118,7 +117,7 @@ class Results extends React.PureComponent {
         </div>
 
         <Helmet>
-          <title>{intl.formatMessage(messages.title, { q })} - {title}</title>
+          <title>{intl.formatMessage(messages.title, { q })}</title>
         </Helmet>
       </React.Fragment>
     );
diff --git a/app/javascript/flavours/glitch/features/explore/statuses.js b/app/javascript/flavours/glitch/features/explore/statuses.js
index fe08ce466..0a5c9de23 100644
--- a/app/javascript/flavours/glitch/features/explore/statuses.js
+++ b/app/javascript/flavours/glitch/features/explore/statuses.js
@@ -6,6 +6,7 @@ import { FormattedMessage } from 'react-intl';
 import { connect } from 'react-redux';
 import { fetchTrendingStatuses, expandTrendingStatuses } from 'flavours/glitch/actions/trends';
 import { debounce } from 'lodash';
+import DismissableBanner from 'flavours/glitch/components/dismissable_banner';
 
 const mapStateToProps = state => ({
   statusIds: state.getIn(['status_lists', 'trending', 'items']),
@@ -40,17 +41,23 @@ class Statuses extends React.PureComponent {
     const emptyMessage = <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />;
 
     return (
-      <StatusList
-        trackScroll
-        statusIds={statusIds}
-        scrollKey='explore-statuses'
-        hasMore={hasMore}
-        isLoading={isLoading}
-        onLoadMore={this.handleLoadMore}
-        emptyMessage={emptyMessage}
-        bindToDocument={!multiColumn}
-        withCounters
-      />
+      <>
+        <DismissableBanner id='explore/statuses'>
+          <FormattedMessage id='dismissable_banner.explore_statuses' defaultMessage='These posts from this and other servers in the decentralized network are gaining traction on this server right now.' />
+        </DismissableBanner>
+
+        <StatusList
+          trackScroll
+          statusIds={statusIds}
+          scrollKey='explore-statuses'
+          hasMore={hasMore}
+          isLoading={isLoading}
+          onLoadMore={this.handleLoadMore}
+          emptyMessage={emptyMessage}
+          bindToDocument={!multiColumn}
+          withCounters
+        />
+      </>
     );
   }
 
diff --git a/app/javascript/flavours/glitch/features/explore/tags.js b/app/javascript/flavours/glitch/features/explore/tags.js
index 465fad0df..938036b64 100644
--- a/app/javascript/flavours/glitch/features/explore/tags.js
+++ b/app/javascript/flavours/glitch/features/explore/tags.js
@@ -6,6 +6,7 @@ import LoadingIndicator from 'flavours/glitch/components/loading_indicator';
 import { connect } from 'react-redux';
 import { fetchTrendingHashtags } from 'flavours/glitch/actions/trends';
 import { FormattedMessage } from 'react-intl';
+import DismissableBanner from 'flavours/glitch/components/dismissable_banner';
 
 const mapStateToProps = state => ({
   hashtags: state.getIn(['trends', 'tags', 'items']),
@@ -29,9 +30,17 @@ class Tags extends React.PureComponent {
   render () {
     const { isLoading, hashtags } = this.props;
 
+    const banner = (
+      <DismissableBanner id='explore/tags'>
+        <FormattedMessage id='dismissable_banner.explore_tags' defaultMessage='These hashtags are gaining traction among people on this and other servers of the decentralized network right now.' />
+      </DismissableBanner>
+    );
+
     if (!isLoading && hashtags.isEmpty()) {
       return (
         <div className='explore__links scrollable scrollable--flex'>
+          {banner}
+
           <div className='empty-column-indicator'>
             <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />
           </div>
@@ -41,6 +50,8 @@ class Tags extends React.PureComponent {
 
     return (
       <div className='explore__links'>
+        {banner}
+
         {isLoading ? (<LoadingIndicator />) : hashtags.map(hashtag => (
           <Hashtag key={hashtag.get('name')} hashtag={hashtag} />
         ))}
diff --git a/app/javascript/flavours/glitch/features/hashtag_timeline/index.js b/app/javascript/flavours/glitch/features/hashtag_timeline/index.js
index 5e098514a..80b4c82be 100644
--- a/app/javascript/flavours/glitch/features/hashtag_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/hashtag_timeline/index.js
@@ -14,7 +14,6 @@ import { isEqual } from 'lodash';
 import { fetchHashtag, followHashtag, unfollowHashtag } from 'flavours/glitch/actions/tags';
 import Icon from 'flavours/glitch/components/icon';
 import classNames from 'classnames';
-import { title } from 'flavours/glitch/initial_state';
 import { Helmet } from 'react-helmet';
 
 const messages = defineMessages({
@@ -228,7 +227,7 @@ class HashtagTimeline extends React.PureComponent {
         />
 
         <Helmet>
-          <title>{`#${id}`} - {title}</title>
+          <title>#{id}</title>
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/flavours/glitch/features/home_timeline/index.js b/app/javascript/flavours/glitch/features/home_timeline/index.js
index 86aaa0258..aa319b576 100644
--- a/app/javascript/flavours/glitch/features/home_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/home_timeline/index.js
@@ -15,13 +15,12 @@ import classNames from 'classnames';
 import IconWithBadge from 'flavours/glitch/components/icon_with_badge';
 import NotSignedInIndicator from 'flavours/glitch/components/not_signed_in_indicator';
 import { Helmet } from 'react-helmet';
-import { title } from 'flavours/glitch/initial_state';
 
 const messages = defineMessages({
   title: { id: 'column.home', defaultMessage: 'Home' },
   show_announcements: { id: 'home.show_announcements', defaultMessage: 'Show announcements' },
   hide_announcements: { id: 'home.hide_announcements', defaultMessage: 'Hide announcements' },
-});
+});  
 
 const mapStateToProps = state => ({
   hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0,
@@ -170,7 +169,7 @@ class HomeTimeline extends React.PureComponent {
         ) : <NotSignedInIndicator />}
 
         <Helmet>
-          <title>{intl.formatMessage(messages.title)} - {title}</title>
+          <title>{intl.formatMessage(messages.title)}</title>
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/flavours/glitch/features/notifications/index.js b/app/javascript/flavours/glitch/features/notifications/index.js
index 26eeba168..0b26a3d9e 100644
--- a/app/javascript/flavours/glitch/features/notifications/index.js
+++ b/app/javascript/flavours/glitch/features/notifications/index.js
@@ -30,7 +30,6 @@ import compareId from 'flavours/glitch/compare_id';
 import NotificationsPermissionBanner from './components/notifications_permission_banner';
 import NotSignedInIndicator from 'flavours/glitch/components/not_signed_in_indicator';
 import { Helmet } from 'react-helmet';
-import { title } from 'flavours/glitch/initial_state';
 
 import NotificationPurgeButtonsContainer from 'flavours/glitch/containers/notification_purge_buttons_container';
 
@@ -373,7 +372,7 @@ class Notifications extends React.PureComponent {
         {scrollContainer}
 
         <Helmet>
-          <title>{intl.formatMessage(messages.title)} - {title}</title>
+          <title>{intl.formatMessage(messages.title)}</title>
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/flavours/glitch/features/privacy_policy/index.js b/app/javascript/flavours/glitch/features/privacy_policy/index.js
index 816010294..c1f7c4f1e 100644
--- a/app/javascript/flavours/glitch/features/privacy_policy/index.js
+++ b/app/javascript/flavours/glitch/features/privacy_policy/index.js
@@ -1,6 +1,5 @@
 import React from 'react';
 import PropTypes from 'prop-types';
-import { title } from 'flavours/glitch/initial_state';
 import { Helmet } from 'react-helmet';
 import { FormattedMessage, FormattedDate, injectIntl, defineMessages } from 'react-intl';
 import Column from 'flavours/glitch/components/column';
@@ -51,7 +50,7 @@ class PrivacyPolicy extends React.PureComponent {
         </div>
 
         <Helmet>
-          <title>{intl.formatMessage(messages.title)} - {title}</title>
+          <title>{intl.formatMessage(messages.title)}</title>
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/flavours/glitch/features/public_timeline/index.js b/app/javascript/flavours/glitch/features/public_timeline/index.js
index aa70acf15..49015c2fb 100644
--- a/app/javascript/flavours/glitch/features/public_timeline/index.js
+++ b/app/javascript/flavours/glitch/features/public_timeline/index.js
@@ -10,7 +10,7 @@ import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/col
 import ColumnSettingsContainer from './containers/column_settings_container';
 import { connectPublicStream } from 'flavours/glitch/actions/streaming';
 import { Helmet } from 'react-helmet';
-import { title } from 'flavours/glitch/initial_state';
+import DismissableBanner from 'flavours/glitch/components/dismissable_banner';
 
 const messages = defineMessages({
   title: { id: 'column.public', defaultMessage: 'Federated timeline' },
@@ -143,6 +143,10 @@ class PublicTimeline extends React.PureComponent {
           <ColumnSettingsContainer columnId={columnId} />
         </ColumnHeader>
 
+        <DismissableBanner id='public_timeline'>
+          <FormattedMessage id='dismissable_banner.public_timeline' defaultMessage='These are the most recent public posts from people on this and other servers of the decentralized network that this server knows about.' />
+        </DismissableBanner>
+
         <StatusListContainer
           timelineId={`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`}
           onLoadMore={this.handleLoadMore}
@@ -154,7 +158,7 @@ class PublicTimeline extends React.PureComponent {
         />
 
         <Helmet>
-          <title>{intl.formatMessage(messages.title)} - {title}</title>
+          <title>{intl.formatMessage(messages.title)}</title>
         </Helmet>
       </Column>
     );
diff --git a/app/javascript/flavours/glitch/settings.js b/app/javascript/flavours/glitch/settings.js
index 7643a508e..46cfadfa3 100644
--- a/app/javascript/flavours/glitch/settings.js
+++ b/app/javascript/flavours/glitch/settings.js
@@ -45,3 +45,4 @@ export default class Settings {
 
 export const pushNotificationsSetting = new Settings('mastodon_push_notification_data');
 export const tagHistory = new Settings('mastodon_tag_history');
+export const bannerSettings = new Settings('mastodon_banner_settings');
diff --git a/app/javascript/flavours/glitch/styles/components/columns.scss b/app/javascript/flavours/glitch/styles/components/columns.scss
index 1827e8c01..6f878f791 100644
--- a/app/javascript/flavours/glitch/styles/components/columns.scss
+++ b/app/javascript/flavours/glitch/styles/components/columns.scss
@@ -936,3 +936,28 @@ $ui-header-height: 55px;
     color: $darker-text-color;
   }
 }
+
+.dismissable-banner {
+  background: $ui-base-color;
+  border-bottom: 1px solid lighten($ui-base-color, 8%);
+  display: flex;
+  align-items: center;
+  gap: 30px;
+
+  &__message {
+    flex: 1 1 auto;
+    padding: 20px 15px;
+    cursor: default;
+    font-size: 14px;
+    line-height: 18px;
+    color: $primary-text-color;
+  }
+
+  &__action {
+    padding: 15px;
+    flex: 0 0 auto;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+}