import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { autoPlayGif, me } from 'flavours/glitch/util/initial_state';
+import { autoPlayGif, me, title, domain } from 'flavours/glitch/util/initial_state';
import { preferencesLink, profileLink, accountAdminLink } from 'flavours/glitch/util/backend_links';
import classNames from 'classnames';
import Icon from 'flavours/glitch/components/icon';
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
import AccountNoteContainer from '../containers/account_note_container';
import { PERMISSION_MANAGE_USERS } from 'flavours/glitch/permissions';
+import { Helmet } from 'react-helmet';
const messages = defineMessages({
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
languages: { id: 'account.languages', defaultMessage: 'Change subscribed languages' },
});
+const titleFromAccount = account => {
+ const displayName = account.get('display_name');
+ const acct = account.get('acct') === account.get('username') ? `${account.get('username')}@${domain}` : account.get('acct');
+ const prefix = displayName.trim().length === 0 ? account.get('username') : displayName;
+
+ return `${prefix} (@${acct})`;
+};
+
const dateFormatOptions = {
month: 'short',
day: 'numeric',
</div>
)}
</div>
+
+ <Helmet>
+ <title>{titleFromAccount(account)} - {title}</title>
+ </Helmet>
</div>
);
}
import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns';
import ColumnSettingsContainer from './containers/column_settings_container';
import { connectCommunityStream } from 'flavours/glitch/actions/streaming';
+import { Helmet } from 'react-helmet';
+import { title } from 'flavours/glitch/util/initial_state';
const messages = defineMessages({
title: { id: 'column.community', defaultMessage: 'Local timeline' },
bindToDocument={!multiColumn}
regex={this.props.regex}
/>
+
+ <Helmet>
+ <title>{intl.formatMessage(messages.title)} - {title}</title>
+ </Helmet>
</Column>
);
}
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/util/initial_state';
+import { Helmet } from 'react-helmet';
const messages = defineMessages({
title: { id: 'column.directory', defaultMessage: 'Browse profiles' },
/>
{multiColumn && !pinned ? <ScrollContainer scrollKey='directory'>{scrollableArea}</ScrollContainer> : scrollableArea}
+
+ <Helmet>
+ <title>{intl.formatMessage(messages.title)} - {title}</title>
+ </Helmet>
</Column>
);
}
import Search from 'flavours/glitch/features/compose/containers/search_container';
import SearchResults from './results';
import { showTrends } from 'flavours/glitch/util/initial_state';
+import { Helmet } from 'react-helmet';
+import { title } from 'flavours/glitch/util/initial_state';
const messages = defineMessages({
title: { id: 'explore.title', defaultMessage: 'Explore' },
<Route path='/explore/suggestions' component={Suggestions} />
<Route exact path={['/explore', '/explore/posts', '/search']} component={Statuses} componentParams={{ multiColumn }} />
</Switch>
+
+ <Helmet>
+ <title>{intl.formatMessage(messages.title)} - {title}</title>
+ </Helmet>
</React.Fragment>
)}
</div>
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/util/initial_state';
+import { Helmet } from 'react-helmet';
const messages = defineMessages({
title: { id: 'search_results.title', defaultMessage: 'Search for {q}' },
<div className='explore__search-results'>
{isLoading ? <LoadingIndicator /> : filteredResults}
</div>
+
+ <Helmet>
+ <title>{intl.formatMessage(messages.title, { q })} - {title}</title>
+ </Helmet>
</React.Fragment>
);
}
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/util/initial_state';
+import { Helmet } from 'react-helmet';
const messages = defineMessages({
followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' },
emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />}
bindToDocument={!multiColumn}
/>
+
+ <Helmet>
+ <title>{`#${id}`} - {title}</title>
+ </Helmet>
</Column>
);
}
import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns';
import ColumnSettingsContainer from './containers/column_settings_container';
import { connectPublicStream } from 'flavours/glitch/actions/streaming';
+import { Helmet } from 'react-helmet';
+import { title } from 'flavours/glitch/util/initial_state';
const messages = defineMessages({
title: { id: 'column.public', defaultMessage: 'Federated timeline' },
bindToDocument={!multiColumn}
regex={this.props.regex}
/>
+
+ <Helmet>
+ <title>{intl.formatMessage(messages.title)} - {title}</title>
+ </Helmet>
</Column>
);
}
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys';
-import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/util/initial_state';
+import { boostModal, favouriteModal, deleteModal, title } from 'flavours/glitch/util/initial_state';
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from 'flavours/glitch/util/fullscreen';
import { autoUnfoldCW } from 'flavours/glitch/util/content_warning';
import { textForScreenReader, defaultMediaVisibility } from 'flavours/glitch/components/status';
import Icon from 'flavours/glitch/components/icon';
+import { Helmet } from 'react-helmet';
const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
return mapStateToProps;
};
+const truncate = (str, num) => {
+ if (str.length > num) {
+ return str.slice(0, num) + '…';
+ } else {
+ return str;
+ }
+};
+
+const titleFromStatus = status => {
+ const displayName = status.getIn(['account', 'display_name']);
+ const username = status.getIn(['account', 'username']);
+ const prefix = displayName.trim().length === 0 ? username : displayName;
+ const text = status.get('search_index');
+
+ return `${prefix}: "${truncate(text, 30)}"`;
+};
+
export default @injectIntl
@connect(makeMapStateToProps)
class Status extends ImmutablePureComponent {
{descendants}
</div>
</ScrollContainer>
+
+ <Helmet>
+ <title>{titleFromStatus(status)} - {title}</title>
+ </Helmet>
</Column>
);
}
FollowRecommendations,
} from 'flavours/glitch/util/async-components';
import { HotKeys } from 'react-hotkeys';
-import { me } from 'flavours/glitch/util/initial_state';
+import { me, title } from 'flavours/glitch/util/initial_state';
import { closeOnboarding, INTRODUCTION_VERSION } from 'flavours/glitch/actions/onboarding';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
+import { Helmet } from 'react-helmet';
// Dummy import, to make sure that <Status /> ends up in the application bundle.
// Without this it ends up in ~8 very commonly used bundles.
<LoadingBarContainer className='loading-bar' />
<ModalContainer />
<UploadArea active={draggingOver} onClose={this.closeUploadModal} />
+
+ <Helmet>
+ <title>{title}</title>
+ </Helmet>
</div>
</HotKeys>
);
export const usePendingItems = getMeta('use_pending_items');
export const useSystemEmojiFont = getMeta('system_emoji_font');
export const showTrends = getMeta('trends');
+export const title = getMeta('title');
export const disableSwiping = getMeta('disable_swiping');
export const languages = initialState && initialState.languages;
export const server = initialState && initialState.server;