[Glitch] Add dynamic document title to WebUI

Port part of 43b5d5e38d to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
master
Eugen Rochko 2022-09-29 04:39:33 +02:00 committed by Claire
parent 1ddd2186de
commit 9ee2746a36
10 changed files with 80 additions and 3 deletions

View File

@ -3,7 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component'; 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 { preferencesLink, profileLink, accountAdminLink } from 'flavours/glitch/util/backend_links';
import classNames from 'classnames'; import classNames from 'classnames';
import Icon from 'flavours/glitch/components/icon'; import Icon from 'flavours/glitch/components/icon';
@ -14,6 +14,7 @@ import { NavLink } from 'react-router-dom';
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
import AccountNoteContainer from '../containers/account_note_container'; import AccountNoteContainer from '../containers/account_note_container';
import { PERMISSION_MANAGE_USERS } from 'flavours/glitch/permissions'; import { PERMISSION_MANAGE_USERS } from 'flavours/glitch/permissions';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
@ -54,6 +55,14 @@ const messages = defineMessages({
languages: { id: 'account.languages', defaultMessage: 'Change subscribed languages' }, 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 = { const dateFormatOptions = {
month: 'short', month: 'short',
day: 'numeric', day: 'numeric',
@ -340,6 +349,10 @@ class Header extends ImmutablePureComponent {
</div> </div>
)} )}
</div> </div>
<Helmet>
<title>{titleFromAccount(account)} - {title}</title>
</Helmet>
</div> </div>
); );
} }

View File

@ -9,6 +9,8 @@ import { expandCommunityTimeline } from 'flavours/glitch/actions/timelines';
import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns'; import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns';
import ColumnSettingsContainer from './containers/column_settings_container'; import ColumnSettingsContainer from './containers/column_settings_container';
import { connectCommunityStream } from 'flavours/glitch/actions/streaming'; import { connectCommunityStream } from 'flavours/glitch/actions/streaming';
import { Helmet } from 'react-helmet';
import { title } from 'flavours/glitch/util/initial_state';
const messages = defineMessages({ const messages = defineMessages({
title: { id: 'column.community', defaultMessage: 'Local timeline' }, title: { id: 'column.community', defaultMessage: 'Local timeline' },
@ -132,6 +134,10 @@ class CommunityTimeline extends React.PureComponent {
bindToDocument={!multiColumn} bindToDocument={!multiColumn}
regex={this.props.regex} regex={this.props.regex}
/> />
<Helmet>
<title>{intl.formatMessage(messages.title)} - {title}</title>
</Helmet>
</Column> </Column>
); );
} }

View File

@ -13,6 +13,8 @@ import RadioButton from 'flavours/glitch/components/radio_button';
import LoadMore from 'flavours/glitch/components/load_more'; import LoadMore from 'flavours/glitch/components/load_more';
import ScrollContainer from 'flavours/glitch/containers/scroll_container'; import ScrollContainer from 'flavours/glitch/containers/scroll_container';
import LoadingIndicator from 'flavours/glitch/components/loading_indicator'; import LoadingIndicator from 'flavours/glitch/components/loading_indicator';
import { title } from 'flavours/glitch/util/initial_state';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
title: { id: 'column.directory', defaultMessage: 'Browse profiles' }, title: { id: 'column.directory', defaultMessage: 'Browse profiles' },
@ -165,6 +167,10 @@ class Directory extends React.PureComponent {
/> />
{multiColumn && !pinned ? <ScrollContainer scrollKey='directory'>{scrollableArea}</ScrollContainer> : scrollableArea} {multiColumn && !pinned ? <ScrollContainer scrollKey='directory'>{scrollableArea}</ScrollContainer> : scrollableArea}
<Helmet>
<title>{intl.formatMessage(messages.title)} - {title}</title>
</Helmet>
</Column> </Column>
); );
} }

View File

@ -12,6 +12,8 @@ import Suggestions from './suggestions';
import Search from 'flavours/glitch/features/compose/containers/search_container'; import Search from 'flavours/glitch/features/compose/containers/search_container';
import SearchResults from './results'; import SearchResults from './results';
import { showTrends } from 'flavours/glitch/util/initial_state'; import { showTrends } from 'flavours/glitch/util/initial_state';
import { Helmet } from 'react-helmet';
import { title } from 'flavours/glitch/util/initial_state';
const messages = defineMessages({ const messages = defineMessages({
title: { id: 'explore.title', defaultMessage: 'Explore' }, title: { id: 'explore.title', defaultMessage: 'Explore' },
@ -82,6 +84,10 @@ class Explore extends React.PureComponent {
<Route path='/explore/suggestions' component={Suggestions} /> <Route path='/explore/suggestions' component={Suggestions} />
<Route exact path={['/explore', '/explore/posts', '/search']} component={Statuses} componentParams={{ multiColumn }} /> <Route exact path={['/explore', '/explore/posts', '/search']} component={Statuses} componentParams={{ multiColumn }} />
</Switch> </Switch>
<Helmet>
<title>{intl.formatMessage(messages.title)} - {title}</title>
</Helmet>
</React.Fragment> </React.Fragment>
)} )}
</div> </div>

View File

@ -10,6 +10,8 @@ import { ImmutableHashtag as Hashtag } from 'flavours/glitch/components/hashtag'
import { List as ImmutableList } from 'immutable'; import { List as ImmutableList } from 'immutable';
import LoadMore from 'flavours/glitch/components/load_more'; import LoadMore from 'flavours/glitch/components/load_more';
import LoadingIndicator from 'flavours/glitch/components/loading_indicator'; import LoadingIndicator from 'flavours/glitch/components/loading_indicator';
import { title } from 'flavours/glitch/util/initial_state';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
title: { id: 'search_results.title', defaultMessage: 'Search for {q}' }, title: { id: 'search_results.title', defaultMessage: 'Search for {q}' },
@ -114,6 +116,10 @@ class Results extends React.PureComponent {
<div className='explore__search-results'> <div className='explore__search-results'>
{isLoading ? <LoadingIndicator /> : filteredResults} {isLoading ? <LoadingIndicator /> : filteredResults}
</div> </div>
<Helmet>
<title>{intl.formatMessage(messages.title, { q })} - {title}</title>
</Helmet>
</React.Fragment> </React.Fragment>
); );
} }

View File

@ -14,6 +14,8 @@ import { isEqual } from 'lodash';
import { fetchHashtag, followHashtag, unfollowHashtag } from 'flavours/glitch/actions/tags'; import { fetchHashtag, followHashtag, unfollowHashtag } from 'flavours/glitch/actions/tags';
import Icon from 'flavours/glitch/components/icon'; import Icon from 'flavours/glitch/components/icon';
import classNames from 'classnames'; import classNames from 'classnames';
import { title } from 'flavours/glitch/util/initial_state';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' }, followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' },
@ -218,6 +220,10 @@ class HashtagTimeline extends React.PureComponent {
emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />} emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />}
bindToDocument={!multiColumn} bindToDocument={!multiColumn}
/> />
<Helmet>
<title>{`#${id}`} - {title}</title>
</Helmet>
</Column> </Column>
); );
} }

View File

@ -9,6 +9,8 @@ import { expandPublicTimeline } from 'flavours/glitch/actions/timelines';
import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns'; import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns';
import ColumnSettingsContainer from './containers/column_settings_container'; import ColumnSettingsContainer from './containers/column_settings_container';
import { connectPublicStream } from 'flavours/glitch/actions/streaming'; import { connectPublicStream } from 'flavours/glitch/actions/streaming';
import { Helmet } from 'react-helmet';
import { title } from 'flavours/glitch/util/initial_state';
const messages = defineMessages({ const messages = defineMessages({
title: { id: 'column.public', defaultMessage: 'Federated timeline' }, title: { id: 'column.public', defaultMessage: 'Federated timeline' },
@ -138,6 +140,10 @@ class PublicTimeline extends React.PureComponent {
bindToDocument={!multiColumn} bindToDocument={!multiColumn}
regex={this.props.regex} regex={this.props.regex}
/> />
<Helmet>
<title>{intl.formatMessage(messages.title)} - {title}</title>
</Helmet>
</Column> </Column>
); );
} }

View File

@ -47,11 +47,12 @@ import { openModal } from 'flavours/glitch/actions/modal';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys'; 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 { attachFullscreenListener, detachFullscreenListener, isFullscreen } from 'flavours/glitch/util/fullscreen';
import { autoUnfoldCW } from 'flavours/glitch/util/content_warning'; import { autoUnfoldCW } from 'flavours/glitch/util/content_warning';
import { textForScreenReader, defaultMediaVisibility } from 'flavours/glitch/components/status'; import { textForScreenReader, defaultMediaVisibility } from 'flavours/glitch/components/status';
import Icon from 'flavours/glitch/components/icon'; import Icon from 'flavours/glitch/components/icon';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
@ -147,6 +148,23 @@ const makeMapStateToProps = () => {
return mapStateToProps; 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 export default @injectIntl
@connect(makeMapStateToProps) @connect(makeMapStateToProps)
class Status extends ImmutablePureComponent { class Status extends ImmutablePureComponent {
@ -633,6 +651,10 @@ class Status extends ImmutablePureComponent {
{descendants} {descendants}
</div> </div>
</ScrollContainer> </ScrollContainer>
<Helmet>
<title>{titleFromStatus(status)} - {title}</title>
</Helmet>
</Column> </Column>
); );
} }

View File

@ -54,9 +54,10 @@ import {
FollowRecommendations, FollowRecommendations,
} from 'flavours/glitch/util/async-components'; } from 'flavours/glitch/util/async-components';
import { HotKeys } from 'react-hotkeys'; 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 { closeOnboarding, INTRODUCTION_VERSION } from 'flavours/glitch/actions/onboarding';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; 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. // Dummy import, to make sure that <Status /> ends up in the application bundle.
// Without this it ends up in ~8 very commonly used bundles. // Without this it ends up in ~8 very commonly used bundles.
@ -660,6 +661,10 @@ class UI extends React.Component {
<LoadingBarContainer className='loading-bar' /> <LoadingBarContainer className='loading-bar' />
<ModalContainer /> <ModalContainer />
<UploadArea active={draggingOver} onClose={this.closeUploadModal} /> <UploadArea active={draggingOver} onClose={this.closeUploadModal} />
<Helmet>
<title>{title}</title>
</Helmet>
</div> </div>
</HotKeys> </HotKeys>
); );

View File

@ -37,6 +37,7 @@ export const useBlurhash = getMeta('use_blurhash');
export const usePendingItems = getMeta('use_pending_items'); export const usePendingItems = getMeta('use_pending_items');
export const useSystemEmojiFont = getMeta('system_emoji_font'); export const useSystemEmojiFont = getMeta('system_emoji_font');
export const showTrends = getMeta('trends'); export const showTrends = getMeta('trends');
export const title = getMeta('title');
export const disableSwiping = getMeta('disable_swiping'); export const disableSwiping = getMeta('disable_swiping');
export const languages = initialState && initialState.languages; export const languages = initialState && initialState.languages;
export const server = initialState && initialState.server; export const server = initialState && initialState.server;