Add column width customize features
This commit is contained in:
parent
2bee3e3fdb
commit
c297bf5471
53 changed files with 890 additions and 179 deletions
|
@ -95,6 +95,7 @@ class Settings::PreferencesController < Settings::BaseController
|
||||||
:setting_confirm_follow_from_bot,
|
:setting_confirm_follow_from_bot,
|
||||||
:setting_default_search_searchability,
|
:setting_default_search_searchability,
|
||||||
:setting_show_reload_button,
|
:setting_show_reload_button,
|
||||||
|
:setting_default_column_width,
|
||||||
notification_emails: %i(follow follow_request reblog favourite emoji_reaction status_reference mention digest report pending_account trending_tag),
|
notification_emails: %i(follow follow_request reblog favourite emoji_reaction status_reference mention digest report pending_account trending_tag),
|
||||||
interactions: %i(must_be_follower must_be_following must_be_following_dm must_be_dm_to_send_email must_be_following_reference)
|
interactions: %i(must_be_follower must_be_following must_be_following_dm must_be_dm_to_send_email must_be_following_reference)
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { supportsPassiveEvents } from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import { scrollTop } from '../scroll';
|
import { scrollTop } from '../scroll';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export default class Column extends React.PureComponent {
|
export default class Column extends React.PureComponent {
|
||||||
|
|
||||||
|
@ -9,6 +10,7 @@ export default class Column extends React.PureComponent {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
label: PropTypes.string,
|
label: PropTypes.string,
|
||||||
bindToDocument: PropTypes.bool,
|
bindToDocument: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
scrollTop () {
|
scrollTop () {
|
||||||
|
@ -50,10 +52,10 @@ export default class Column extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { label, children } = this.props;
|
const { label, columnWidth, children } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div role='region' aria-label={label} className='column' ref={this.setRef}>
|
<div role='region' aria-label={label} className={classNames('column', columnWidth)} ref={this.setRef}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
import { enableEmptyColumn } from 'mastodon/initial_state';
|
import { enableEmptyColumn, defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
||||||
|
@ -13,7 +14,20 @@ const messages = defineMessages({
|
||||||
moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
|
moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @injectIntl
|
const column_width_message = [
|
||||||
|
{ id: 'x080', defaultMessage: <FormattedMessage id={'column_width.x080'} defaultMessage='80%' /> },
|
||||||
|
{ id: 'x100', defaultMessage: <FormattedMessage id={'column_width.x100'} defaultMessage='100%' /> },
|
||||||
|
{ id: 'x125', defaultMessage: <FormattedMessage id={'column_width.x125'} defaultMessage='125%' /> },
|
||||||
|
{ id: 'x150', defaultMessage: <FormattedMessage id={'column_width.x150'} defaultMessage='150%' /> },
|
||||||
|
{ id: 'free', defaultMessage: <FormattedMessage id={'column_width.free'} defaultMessage='Free' /> },
|
||||||
|
];
|
||||||
|
|
||||||
|
const mapStateToProps = (state, { columnWidth }) => ({
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default @connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
class ColumnHeader extends React.PureComponent {
|
class ColumnHeader extends React.PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
|
@ -36,6 +50,8 @@ class ColumnHeader extends React.PureComponent {
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
appendContent: PropTypes.node,
|
appendContent: PropTypes.node,
|
||||||
collapseIssues: PropTypes.bool,
|
collapseIssues: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
|
onWidthChange: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -88,8 +104,15 @@ class ColumnHeader extends React.PureComponent {
|
||||||
this.props.onPin();
|
this.props.onPin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleChangeWidth = e => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (this.props.onWidthChange) {
|
||||||
|
this.props.onWidthChange(e.target.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props;
|
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues, columnWidth } = this.props;
|
||||||
const { collapsed, animating } = this.state;
|
const { collapsed, animating } = this.state;
|
||||||
|
|
||||||
const wrapperClassName = classNames('column-header__wrapper', {
|
const wrapperClassName = classNames('column-header__wrapper', {
|
||||||
|
@ -146,11 +169,25 @@ class ColumnHeader extends React.PureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const widthButton = (
|
||||||
|
<div className='column-settings__row' role='group' key='column-width'>
|
||||||
|
<div className='column-width' role='group'>
|
||||||
|
{column_width_message.map(({ id, defaultMessage }) => (
|
||||||
|
<label key={id} className={classNames('column-width__item', { active: columnWidth === id })}>
|
||||||
|
<input name='width' type='radio' value={id} checked={columnWidth === id} onChange={this.handleChangeWidth} />
|
||||||
|
{defaultMessage}
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
const collapsedContent = [
|
const collapsedContent = [
|
||||||
extraContent,
|
extraContent,
|
||||||
];
|
];
|
||||||
|
|
||||||
if (multiColumn) {
|
if (multiColumn) {
|
||||||
|
collapsedContent.unshift(widthButton);
|
||||||
collapsedContent.push(moveButtons);
|
collapsedContent.push(moveButtons);
|
||||||
collapsedContent.push(pinButton);
|
collapsedContent.push(pinButton);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,8 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
||||||
import MissingIndicator from 'mastodon/components/missing_indicator';
|
import MissingIndicator from 'mastodon/components/missing_indicator';
|
||||||
import TimelineHint from 'mastodon/components/timeline_hint';
|
import TimelineHint from 'mastodon/components/timeline_hint';
|
||||||
import { new_features_policy } from 'mastodon/initial_state';
|
import { new_features_policy, defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.account', defaultMessage: 'Account' },
|
title: { id: 'column.account', defaultMessage: 'Account' },
|
||||||
|
@ -36,6 +37,7 @@ const mapStateToProps = (state, { params: { accountId } }) => ({
|
||||||
blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false),
|
blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false),
|
||||||
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
||||||
hideRelation: state.getIn(['settings', 'account', 'other', 'hideRelation'], false),
|
hideRelation: state.getIn(['settings', 'account', 'other', 'hideRelation'], false),
|
||||||
|
columnWidth: state.getIn(['settings', 'account', 'columnWidth'], defaultColumnWidth),
|
||||||
});
|
});
|
||||||
|
|
||||||
const RemoteHint = ({ url }) => (
|
const RemoteHint = ({ url }) => (
|
||||||
|
@ -63,6 +65,7 @@ class AccountConversations extends ImmutablePureComponent {
|
||||||
isAccount: PropTypes.bool,
|
isAccount: PropTypes.bool,
|
||||||
suspended: PropTypes.bool,
|
suspended: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -93,12 +96,16 @@ class AccountConversations extends ImmutablePureComponent {
|
||||||
this.column.scrollTop();
|
this.column.scrollTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
this.props.dispatch(changeSetting(['account', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
this.column = c;
|
this.column = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { statusIds, isLoading, hasMore, blockedBy, suspended, isAccount, multiColumn, hideRelation, intl } = this.props;
|
const { statusIds, isLoading, hasMore, blockedBy, suspended, isAccount, multiColumn, hideRelation, columnWidth, intl } = this.props;
|
||||||
|
|
||||||
if (!isAccount) {
|
if (!isAccount) {
|
||||||
return (
|
return (
|
||||||
|
@ -128,7 +135,7 @@ class AccountConversations extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='user'
|
icon='user'
|
||||||
active={false}
|
active={false}
|
||||||
|
@ -136,6 +143,8 @@ class AccountConversations extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={false}
|
pinned={false}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -16,8 +16,9 @@ import ScrollContainer from 'mastodon/containers/scroll_container';
|
||||||
import LoadMore from 'mastodon/components/load_more';
|
import LoadMore from 'mastodon/components/load_more';
|
||||||
import MissingIndicator from 'mastodon/components/missing_indicator';
|
import MissingIndicator from 'mastodon/components/missing_indicator';
|
||||||
import { openModal } from 'mastodon/actions/modal';
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
import { new_features_policy } from 'mastodon/initial_state';
|
import { new_features_policy, defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.account', defaultMessage: 'Account' },
|
title: { id: 'column.account', defaultMessage: 'Account' },
|
||||||
|
@ -32,6 +33,7 @@ const mapStateToProps = (state, props) => ({
|
||||||
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
|
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
|
||||||
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
||||||
hideRelation: state.getIn(['settings', 'account', 'other', 'hideRelation'], false),
|
hideRelation: state.getIn(['settings', 'account', 'other', 'hideRelation'], false),
|
||||||
|
columnWidth: state.getIn(['settings', 'account', 'columnWidth'], defaultColumnWidth),
|
||||||
});
|
});
|
||||||
|
|
||||||
class LoadMoreMedia extends ImmutablePureComponent {
|
class LoadMoreMedia extends ImmutablePureComponent {
|
||||||
|
@ -72,6 +74,7 @@ class AccountGallery extends ImmutablePureComponent {
|
||||||
blockedBy: PropTypes.bool,
|
blockedBy: PropTypes.bool,
|
||||||
suspended: PropTypes.bool,
|
suspended: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -140,12 +143,16 @@ class AccountGallery extends ImmutablePureComponent {
|
||||||
this.column.scrollTop();
|
this.column.scrollTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
this.props.dispatch(changeSetting(['account', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
this.column = c;
|
this.column = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { attachments, isLoading, hasMore, isAccount, multiColumn, blockedBy, suspended, hideRelation, intl } = this.props;
|
const { attachments, isLoading, hasMore, isAccount, multiColumn, blockedBy, suspended, hideRelation, columnWidth, intl } = this.props;
|
||||||
const { width } = this.state;
|
const { width } = this.state;
|
||||||
|
|
||||||
if (!isAccount) {
|
if (!isAccount) {
|
||||||
|
@ -179,7 +186,7 @@ class AccountGallery extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='user'
|
icon='user'
|
||||||
active={false}
|
active={false}
|
||||||
|
@ -187,6 +194,8 @@ class AccountGallery extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={false}
|
pinned={false}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -17,9 +17,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
|
||||||
import MissingIndicator from 'mastodon/components/missing_indicator';
|
import MissingIndicator from 'mastodon/components/missing_indicator';
|
||||||
import TimelineHint from 'mastodon/components/timeline_hint';
|
import TimelineHint from 'mastodon/components/timeline_hint';
|
||||||
import { me, new_features_policy } from 'mastodon/initial_state';
|
import { me, new_features_policy, defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
import { connectTimeline, disconnectTimeline } from 'mastodon/actions/timelines';
|
import { connectTimeline, disconnectTimeline } from 'mastodon/actions/timelines';
|
||||||
import { fetchFeaturedTags } from '../../actions/featured_tags';
|
import { fetchFeaturedTags } from '../../actions/featured_tags';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
|
||||||
const emptyList = ImmutableList();
|
const emptyList = ImmutableList();
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ const mapStateToProps = (state, { params: { accountId, tagged }, about, withRepl
|
||||||
withoutReblogs,
|
withoutReblogs,
|
||||||
showPostsInAbout,
|
showPostsInAbout,
|
||||||
hideRelation,
|
hideRelation,
|
||||||
|
columnWidth: state.getIn(['settings', 'account', 'columnWidth'], defaultColumnWidth),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,6 +92,7 @@ class AccountTimeline extends ImmutablePureComponent {
|
||||||
remote: PropTypes.bool,
|
remote: PropTypes.bool,
|
||||||
remoteUrl: PropTypes.string,
|
remoteUrl: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -169,12 +172,16 @@ class AccountTimeline extends ImmutablePureComponent {
|
||||||
this.column.scrollTop();
|
this.column.scrollTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
this.props.dispatch(changeSetting(['account', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
this.column = c;
|
this.column = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, suspended, isAccount, multiColumn, remote, remoteUrl, about, withReplies, posts, advancedMode, hideFeaturedTags, showPostsInAbout, hideRelation } = this.props;
|
const { intl, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, suspended, isAccount, multiColumn, remote, remoteUrl, about, withReplies, posts, advancedMode, hideFeaturedTags, showPostsInAbout, hideRelation, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!isAccount) {
|
if (!isAccount) {
|
||||||
return (
|
return (
|
||||||
|
@ -210,7 +217,7 @@ class AccountTimeline extends ImmutablePureComponent {
|
||||||
const remoteMessage = (!about && remote) ? <RemoteHint url={remoteUrl} /> : null;
|
const remoteMessage = (!about && remote) ? <RemoteHint url={remoteUrl} /> : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='user'
|
icon='user'
|
||||||
active={false}
|
active={false}
|
||||||
|
@ -218,6 +225,8 @@ class AccountTimeline extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={false}
|
pinned={false}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||||
import AccountContainer from '../../containers/account_container';
|
import AccountContainer from '../../containers/account_container';
|
||||||
import { fetchBlocks, expandBlocks } from '../../actions/blocks';
|
import { fetchBlocks, expandBlocks } from '../../actions/blocks';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.blocks', defaultMessage: 'Blocked users' },
|
heading: { id: 'column.blocks', defaultMessage: 'Blocked users' },
|
||||||
|
@ -20,6 +21,7 @@ const mapStateToProps = state => ({
|
||||||
accountIds: state.getIn(['user_lists', 'blocks', 'items']),
|
accountIds: state.getIn(['user_lists', 'blocks', 'items']),
|
||||||
hasMore: !!state.getIn(['user_lists', 'blocks', 'next']),
|
hasMore: !!state.getIn(['user_lists', 'blocks', 'next']),
|
||||||
isLoading: state.getIn(['user_lists', 'blocks', 'isLoading'], true),
|
isLoading: state.getIn(['user_lists', 'blocks', 'isLoading'], true),
|
||||||
|
columnWidth: defaultColumnWidth,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -34,6 +36,7 @@ class Blocks extends ImmutablePureComponent {
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -45,7 +48,7 @@ class Blocks extends ImmutablePureComponent {
|
||||||
}, 300, { leading: true });
|
}, 300, { leading: true });
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, accountIds, hasMore, multiColumn, isLoading } = this.props;
|
const { intl, accountIds, hasMore, multiColumn, isLoading, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
return (
|
return (
|
||||||
|
@ -58,7 +61,7 @@ class Blocks extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.blocks' defaultMessage="You haven't blocked any users yet." />;
|
const emptyMessage = <FormattedMessage id='empty_column.blocks' defaultMessage="You haven't blocked any users yet." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} icon='ban' heading={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} icon='ban' heading={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnBackButtonSlim />
|
<ColumnBackButtonSlim />
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='blocks'
|
scrollKey='blocks'
|
||||||
|
|
|
@ -10,16 +10,27 @@ import StatusList from '../../components/status_list';
|
||||||
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 { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.bookmarks', defaultMessage: 'Bookmarks' },
|
heading: { id: 'column.bookmarks', defaultMessage: 'Bookmarks' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state, { columnId }) => {
|
||||||
statusIds: state.getIn(['status_lists', 'bookmarks', 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['status_lists', 'bookmarks', 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
hasMore: !!state.getIn(['status_lists', 'bookmarks', 'next']),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
});
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'bookmarked_statuses', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusIds: state.getIn(['status_lists', 'bookmarks', 'items']),
|
||||||
|
isLoading: state.getIn(['status_lists', 'bookmarks', 'isLoading'], true),
|
||||||
|
hasMore: !!state.getIn(['status_lists', 'bookmarks', 'next']),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -31,6 +42,7 @@ class Bookmarks extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
@ -66,14 +78,24 @@ class Bookmarks extends ImmutablePureComponent {
|
||||||
this.props.dispatch(expandBookmarkedStatuses());
|
this.props.dispatch(expandBookmarkedStatuses());
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['bookmarked_statuses', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
|
const { intl, statusIds, columnId, multiColumn, hasMore, isLoading, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.bookmarked_statuses' defaultMessage="You don't have any bookmarked toots yet. When you bookmark one, it will show up here." />;
|
const emptyMessage = <FormattedMessage id='empty_column.bookmarked_statuses' defaultMessage="You don't have any bookmarked toots yet. When you bookmark one, it will show up here." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='bookmark'
|
icon='bookmark'
|
||||||
title={intl.formatMessage(messages.heading)}
|
title={intl.formatMessage(messages.heading)}
|
||||||
|
@ -82,6 +104,8 @@ class Bookmarks extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
showBackButton
|
showBackButton
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import NewCircleForm from './components/new_circle_form';
|
||||||
import Circle from './components/circle';
|
import Circle from './components/circle';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.circles', defaultMessage: 'Circles' },
|
heading: { id: 'column.circles', defaultMessage: 'Circles' },
|
||||||
|
@ -29,6 +30,7 @@ const getOrderedCircles = createSelector([state => state.get('circles')], circle
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
circles: getOrderedCircles(state),
|
circles: getOrderedCircles(state),
|
||||||
|
columnWidth: defaultColumnWidth,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -41,6 +43,7 @@ class Circles extends ImmutablePureComponent {
|
||||||
circles: ImmutablePropTypes.list,
|
circles: ImmutablePropTypes.list,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -48,7 +51,7 @@ class Circles extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, circles, multiColumn } = this.props;
|
const { intl, circles, multiColumn, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!circles) {
|
if (!circles) {
|
||||||
return (
|
return (
|
||||||
|
@ -61,7 +64,7 @@ class Circles extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.circles' defaultMessage="You don't have any circles yet. When you create one, it will show up here." />;
|
const emptyMessage = <FormattedMessage id='empty_column.circles' defaultMessage="You don't have any circles yet. When you create one, it will show up here." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} icon='user-circle' heading={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} icon='user-circle' heading={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnBackButtonSlim />
|
<ColumnBackButtonSlim />
|
||||||
|
|
||||||
<NewCircleForm />
|
<NewCircleForm />
|
||||||
|
|
|
@ -8,12 +8,25 @@ import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import { connectDirectStream } from '../../actions/streaming';
|
import { connectDirectStream } from '../../actions/streaming';
|
||||||
import ConversationsListContainer from './containers/conversations_list_container';
|
import ConversationsListContainer from './containers/conversations_list_container';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.direct', defaultMessage: 'Direct messages' },
|
title: { id: 'column.direct', defaultMessage: 'Direct messages' },
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect()
|
const mapStateToProps = (state, { columnId }) => {
|
||||||
|
const uuid = columnId;
|
||||||
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'direct', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
class DirectTimeline extends React.PureComponent {
|
class DirectTimeline extends React.PureComponent {
|
||||||
|
|
||||||
|
@ -23,6 +36,7 @@ class DirectTimeline extends React.PureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
hasUnread: PropTypes.bool,
|
hasUnread: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePin = () => {
|
handlePin = () => {
|
||||||
|
@ -69,12 +83,22 @@ class DirectTimeline extends React.PureComponent {
|
||||||
this.props.dispatch(expandConversations({ maxId }));
|
this.props.dispatch(expandConversations({ maxId }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['direct', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, hasUnread, columnId, multiColumn } = this.props;
|
const { intl, hasUnread, columnId, multiColumn, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='envelope'
|
icon='envelope'
|
||||||
active={hasUnread}
|
active={hasUnread}
|
||||||
|
@ -84,6 +108,8 @@ class DirectTimeline extends React.PureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ConversationsListContainer
|
<ConversationsListContainer
|
||||||
|
|
|
@ -13,6 +13,8 @@ import RadioButton from 'mastodon/components/radio_button';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import LoadMore from 'mastodon/components/load_more';
|
import LoadMore from 'mastodon/components/load_more';
|
||||||
import ScrollContainer from 'mastodon/containers/scroll_container';
|
import ScrollContainer from 'mastodon/containers/scroll_container';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.directory', defaultMessage: 'Browse profiles' },
|
title: { id: 'column.directory', defaultMessage: 'Browse profiles' },
|
||||||
|
@ -26,6 +28,7 @@ const mapStateToProps = state => ({
|
||||||
accountIds: state.getIn(['user_lists', 'directory', 'items'], ImmutableList()),
|
accountIds: state.getIn(['user_lists', 'directory', 'items'], ImmutableList()),
|
||||||
isLoading: state.getIn(['user_lists', 'directory', 'isLoading'], true),
|
isLoading: state.getIn(['user_lists', 'directory', 'isLoading'], true),
|
||||||
domain: state.getIn(['meta', 'domain']),
|
domain: state.getIn(['meta', 'domain']),
|
||||||
|
columnWidth: state.getIn(['settings', 'directory', 'columnWidth'], defaultColumnWidth),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -43,6 +46,7 @@ class Directory extends React.PureComponent {
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
domain: PropTypes.string.isRequired,
|
domain: PropTypes.string.isRequired,
|
||||||
params: PropTypes.shape({
|
params: PropTypes.shape({
|
||||||
order: PropTypes.string,
|
order: PropTypes.string,
|
||||||
|
@ -123,8 +127,12 @@ class Directory extends React.PureComponent {
|
||||||
dispatch(expandDirectory(this.getParams(this.props, this.state)));
|
dispatch(expandDirectory(this.getParams(this.props, this.state)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
this.props.dispatch(changeSetting(['directory', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { isLoading, accountIds, intl, columnId, multiColumn, domain } = this.props;
|
const { isLoading, accountIds, intl, columnId, multiColumn, domain, columnWidth } = this.props;
|
||||||
const { order, local } = this.getParams(this.props, this.state);
|
const { order, local } = this.getParams(this.props, this.state);
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
|
@ -151,7 +159,7 @@ class Directory extends React.PureComponent {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='address-book-o'
|
icon='address-book-o'
|
||||||
title={intl.formatMessage(messages.title)}
|
title={intl.formatMessage(messages.title)}
|
||||||
|
@ -160,6 +168,8 @@ class Directory extends React.PureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{multiColumn && !pinned ? <ScrollContainer scrollKey='directory'>{scrollableArea}</ScrollContainer> : scrollableArea}
|
{multiColumn && !pinned ? <ScrollContainer scrollKey='directory'>{scrollableArea}</ScrollContainer> : scrollableArea}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||||
import DomainContainer from '../../containers/domain_container';
|
import DomainContainer from '../../containers/domain_container';
|
||||||
import { fetchDomainBlocks, expandDomainBlocks } from '../../actions/domain_blocks';
|
import { fetchDomainBlocks, expandDomainBlocks } from '../../actions/domain_blocks';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.domain_blocks', defaultMessage: 'Blocked domains' },
|
heading: { id: 'column.domain_blocks', defaultMessage: 'Blocked domains' },
|
||||||
|
@ -20,6 +21,7 @@ const messages = defineMessages({
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
domains: state.getIn(['domain_lists', 'blocks', 'items']),
|
domains: state.getIn(['domain_lists', 'blocks', 'items']),
|
||||||
hasMore: !!state.getIn(['domain_lists', 'blocks', 'next']),
|
hasMore: !!state.getIn(['domain_lists', 'blocks', 'next']),
|
||||||
|
columnWidth: defaultColumnWidth,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -33,6 +35,7 @@ class Blocks extends ImmutablePureComponent {
|
||||||
domains: ImmutablePropTypes.orderedSet,
|
domains: ImmutablePropTypes.orderedSet,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -44,7 +47,7 @@ class Blocks extends ImmutablePureComponent {
|
||||||
}, 300, { leading: true });
|
}, 300, { leading: true });
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, domains, hasMore, multiColumn } = this.props;
|
const { intl, domains, hasMore, multiColumn, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!domains) {
|
if (!domains) {
|
||||||
return (
|
return (
|
||||||
|
@ -57,7 +60,7 @@ class Blocks extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.domain_blocks' defaultMessage='There are no blocked domains yet.' />;
|
const emptyMessage = <FormattedMessage id='empty_column.domain_blocks' defaultMessage='There are no blocked domains yet.' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} icon='minus-circle' heading={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} icon='minus-circle' heading={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnBackButtonSlim />
|
<ColumnBackButtonSlim />
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='domain_blocks'
|
scrollKey='domain_blocks'
|
||||||
|
|
|
@ -9,11 +9,15 @@ import { expandDomainTimeline } from '../../actions/timelines';
|
||||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||||
import ColumnSettingsContainer from './containers/column_settings_container';
|
import ColumnSettingsContainer from './containers/column_settings_container';
|
||||||
import { connectDomainStream } from '../../actions/streaming';
|
import { connectDomainStream } from '../../actions/streaming';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const uuid = props.columnId;
|
const uuid = props.columnId;
|
||||||
const columns = state.getIn(['settings', 'columns']);
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
|
const columnWidth = (props.columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'domain', 'columnWidth']);
|
||||||
const onlyMedia = (props.columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'onlyMedia']) : state.getIn(['settings', 'domain', 'other', 'onlyMedia']);
|
const onlyMedia = (props.columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'onlyMedia']) : state.getIn(['settings', 'domain', 'other', 'onlyMedia']);
|
||||||
const withoutMedia = (props.columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutMedia']) : state.getIn(['settings', 'domain', 'other', 'withoutMedia']);
|
const withoutMedia = (props.columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutMedia']) : state.getIn(['settings', 'domain', 'other', 'withoutMedia']);
|
||||||
const withoutBot = (props.columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutBot']) : state.getIn(['settings', 'domain', 'other', 'withoutBot']);
|
const withoutBot = (props.columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutBot']) : state.getIn(['settings', 'domain', 'other', 'withoutBot']);
|
||||||
|
@ -26,6 +30,7 @@ const mapStateToProps = (state, props) => {
|
||||||
withoutMedia,
|
withoutMedia,
|
||||||
withoutBot,
|
withoutBot,
|
||||||
domain: domain,
|
domain: domain,
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,6 +55,7 @@ class DomainTimeline extends React.PureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
hasUnread: PropTypes.bool,
|
hasUnread: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
onlyMedia: PropTypes.bool,
|
onlyMedia: PropTypes.bool,
|
||||||
withoutMedia: PropTypes.bool,
|
withoutMedia: PropTypes.bool,
|
||||||
withoutBot: PropTypes.bool,
|
withoutBot: PropTypes.bool,
|
||||||
|
@ -109,12 +115,22 @@ class DomainTimeline extends React.PureComponent {
|
||||||
dispatch(expandDomainTimeline(domain, { maxId, onlyMedia, withoutMedia, withoutBot }));
|
dispatch(expandDomainTimeline(domain, { maxId, onlyMedia, withoutMedia, withoutBot }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['domain', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { hasUnread, columnId, multiColumn, onlyMedia, withoutMedia, withoutBot, domain } = this.props;
|
const { hasUnread, columnId, multiColumn, onlyMedia, withoutMedia, withoutBot, domain, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={domain}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={domain} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='users'
|
icon='users'
|
||||||
active={hasUnread}
|
active={hasUnread}
|
||||||
|
@ -125,6 +141,8 @@ class DomainTimeline extends React.PureComponent {
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
showBackButton
|
showBackButton
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer columnId={columnId} />
|
<ColumnSettingsContainer columnId={columnId} />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -10,16 +10,27 @@ import StatusList from '../../components/status_list';
|
||||||
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 { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.emoji_reactions', defaultMessage: 'EmojiReactions' },
|
heading: { id: 'column.emoji_reactions', defaultMessage: 'EmojiReactions' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state, { columnId }) => {
|
||||||
statusIds: state.getIn(['status_lists', 'emoji_reactions', 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['status_lists', 'emoji_reactions', 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
hasMore: !!state.getIn(['status_lists', 'emoji_reactions', 'next']),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
});
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'emoji_reactioned_statuses', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusIds: state.getIn(['status_lists', 'emoji_reactions', 'items']),
|
||||||
|
isLoading: state.getIn(['status_lists', 'emoji_reactions', 'isLoading'], true),
|
||||||
|
hasMore: !!state.getIn(['status_lists', 'emoji_reactions', 'next']),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -31,6 +42,7 @@ class EmojiReactions extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
@ -66,14 +78,24 @@ class EmojiReactions extends ImmutablePureComponent {
|
||||||
this.props.dispatch(expandEmojiReactionedStatuses());
|
this.props.dispatch(expandEmojiReactionedStatuses());
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['emoji_reactioned_statuses', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
|
const { intl, statusIds, columnId, multiColumn, hasMore, isLoading, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.emoji_reactioned_statuses' defaultMessage="You don't have any reaction posts yet. When you reaction one, it will show up here." />;
|
const emptyMessage = <FormattedMessage id='empty_column.emoji_reactioned_statuses' defaultMessage="You don't have any reaction posts yet. When you reaction one, it will show up here." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='star'
|
icon='star'
|
||||||
title={intl.formatMessage(messages.heading)}
|
title={intl.formatMessage(messages.heading)}
|
||||||
|
@ -82,6 +104,8 @@ class EmojiReactions extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
showBackButton
|
showBackButton
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ import { createSelector } from 'reselect';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
import ReactedHeaderContaier from '../reactioned/containers/header_container';
|
import ReactedHeaderContaier from '../reactioned/containers/header_container';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||||
|
@ -23,12 +26,20 @@ const messages = defineMessages({
|
||||||
|
|
||||||
const customEmojiMap = createSelector([state => state.get('custom_emojis')], items => items.reduce((map, emoji) => map.set(emoji.get('shortcode'), emoji), ImmutableMap()));
|
const customEmojiMap = createSelector([state => state.get('custom_emojis')], items => items.reduce((map, emoji) => map.set(emoji.get('shortcode'), emoji), ImmutableMap()));
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => ({
|
const mapStateToProps = (state, { columnId, params }) => {
|
||||||
emojiReactions: state.getIn(['user_lists', 'emoji_reactioned_by', props.params.statusId, 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['user_lists', 'emoji_reactioned_by', props.params.statusId, 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
hasMore: !!state.getIn(['user_lists', 'emoji_reactioned_by', props.params.statusId, 'next']),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
emojiMap: customEmojiMap(state),
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'emoji_reactions', 'columnWidth']);
|
||||||
});
|
|
||||||
|
return {
|
||||||
|
emojiReactions: state.getIn(['user_lists', 'emoji_reactioned_by', params.statusId, 'items']),
|
||||||
|
isLoading: state.getIn(['user_lists', 'emoji_reactioned_by', params.statusId, 'isLoading'], true),
|
||||||
|
hasMore: !!state.getIn(['user_lists', 'emoji_reactioned_by', params.statusId, 'next']),
|
||||||
|
emojiMap: customEmojiMap(state),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
class Reaction extends ImmutablePureComponent {
|
class Reaction extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
@ -65,6 +76,7 @@ class EmojiReactions extends ImmutablePureComponent {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
emojiReactions: ImmutablePropTypes.list,
|
emojiReactions: ImmutablePropTypes.list,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
emojiMap: ImmutablePropTypes.map.isRequired,
|
emojiMap: ImmutablePropTypes.map.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
|
@ -91,8 +103,18 @@ class EmojiReactions extends ImmutablePureComponent {
|
||||||
this.props.dispatch(expandEmojiReactions(this.props.params.statusId));
|
this.props.dispatch(expandEmojiReactions(this.props.params.statusId));
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['emoji_reactions', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, emojiReactions, multiColumn, emojiMap, hasMore, isLoading } = this.props;
|
const { intl, emojiReactions, multiColumn, emojiMap, hasMore, isLoading, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!emojiReactions) {
|
if (!emojiReactions) {
|
||||||
return (
|
return (
|
||||||
|
@ -105,10 +127,12 @@ class EmojiReactions extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.emoji_reactions' defaultMessage='No one has reactioned this post yet. When someone does, they will show up here.' />;
|
const emptyMessage = <FormattedMessage id='empty_column.emoji_reactions' defaultMessage='No one has reactioned this post yet. When someone does, they will show up here.' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn}>
|
<Column bindToDocument={!multiColumn} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
showBackButton
|
showBackButton
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
extraButton={(
|
extraButton={(
|
||||||
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -10,16 +10,27 @@ import StatusList from '../../components/status_list';
|
||||||
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 { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.favourites', defaultMessage: 'Favourites' },
|
heading: { id: 'column.favourites', defaultMessage: 'Favourites' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state, { columnId }) => {
|
||||||
statusIds: state.getIn(['status_lists', 'favourites', 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['status_lists', 'favourites', 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
hasMore: !!state.getIn(['status_lists', 'favourites', 'next']),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
});
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'favourited_statuses', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusIds: state.getIn(['status_lists', 'favourites', 'items']),
|
||||||
|
isLoading: state.getIn(['status_lists', 'favourites', 'isLoading'], true),
|
||||||
|
hasMore: !!state.getIn(['status_lists', 'favourites', 'next']),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -31,6 +42,7 @@ class Favourites extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
@ -66,14 +78,24 @@ class Favourites extends ImmutablePureComponent {
|
||||||
this.props.dispatch(expandFavouritedStatuses());
|
this.props.dispatch(expandFavouritedStatuses());
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['favourited_statuses', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
|
const { intl, statusIds, columnId, multiColumn, hasMore, isLoading, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.favourited_statuses' defaultMessage="You don't have any favourite posts yet. When you favourite one, it will show up here." />;
|
const emptyMessage = <FormattedMessage id='empty_column.favourited_statuses' defaultMessage="You don't have any favourite posts yet. When you favourite one, it will show up here." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='star'
|
icon='star'
|
||||||
title={intl.formatMessage(messages.heading)}
|
title={intl.formatMessage(messages.heading)}
|
||||||
|
@ -82,6 +104,8 @@ class Favourites extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
showBackButton
|
showBackButton
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -13,16 +13,27 @@ import Icon from 'mastodon/components/icon';
|
||||||
import ColumnHeader from '../../components/column_header';
|
import ColumnHeader from '../../components/column_header';
|
||||||
import ReactedHeaderContaier from '../reactioned/containers/header_container';
|
import ReactedHeaderContaier from '../reactioned/containers/header_container';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => ({
|
const mapStateToProps = (state, { columnId, params }) => {
|
||||||
accountIds: state.getIn(['user_lists', 'favourited_by', props.params.statusId, 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['user_lists', 'favourited_by', props.params.statusId, 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
hasMore: !!state.getIn(['user_lists', 'favourited_by', props.params.statusId, 'next']),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
});
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'favourites', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
accountIds: state.getIn(['user_lists', 'favourited_by', params.statusId, 'items']),
|
||||||
|
isLoading: state.getIn(['user_lists', 'favourited_by', params.statusId, 'isLoading'], true),
|
||||||
|
hasMore: !!state.getIn(['user_lists', 'favourited_by', params.statusId, 'next']),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -33,6 +44,7 @@ class Favourites extends ImmutablePureComponent {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
accountIds: ImmutablePropTypes.list,
|
accountIds: ImmutablePropTypes.list,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
|
@ -58,8 +70,18 @@ class Favourites extends ImmutablePureComponent {
|
||||||
this.props.dispatch(expandFavourites(this.props.params.statusId));
|
this.props.dispatch(expandFavourites(this.props.params.statusId));
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['favourites', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, accountIds, multiColumn, hasMore, isLoading } = this.props;
|
const { intl, accountIds, multiColumn, hasMore, isLoading, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
return (
|
return (
|
||||||
|
@ -72,10 +94,12 @@ class Favourites extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.favourites' defaultMessage='No one has favourited this post yet. When someone does, they will show up here.' />;
|
const emptyMessage = <FormattedMessage id='empty_column.favourites' defaultMessage='No one has favourited this post yet. When someone does, they will show up here.' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn}>
|
<Column bindToDocument={!multiColumn} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
showBackButton
|
showBackButton
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
extraButton={(
|
extraButton={(
|
||||||
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||||
import AccountAuthorizeContainer from './containers/account_authorize_container';
|
import AccountAuthorizeContainer from './containers/account_authorize_container';
|
||||||
import { fetchFollowRequests, expandFollowRequests } from '../../actions/accounts';
|
import { fetchFollowRequests, expandFollowRequests } from '../../actions/accounts';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
import { me } from '../../initial_state';
|
import { me, defaultColumnWidth } from '../../initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.follow_requests', defaultMessage: 'Follow requests' },
|
heading: { id: 'column.follow_requests', defaultMessage: 'Follow requests' },
|
||||||
|
@ -23,6 +23,7 @@ const mapStateToProps = state => ({
|
||||||
hasMore: !!state.getIn(['user_lists', 'follow_requests', 'next']),
|
hasMore: !!state.getIn(['user_lists', 'follow_requests', 'next']),
|
||||||
locked: !!state.getIn(['accounts', me, 'locked']),
|
locked: !!state.getIn(['accounts', me, 'locked']),
|
||||||
domain: state.getIn(['meta', 'domain']),
|
domain: state.getIn(['meta', 'domain']),
|
||||||
|
columnWidth: defaultColumnWidth,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -39,6 +40,7 @@ class FollowRequests extends ImmutablePureComponent {
|
||||||
domain: PropTypes.string,
|
domain: PropTypes.string,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -50,7 +52,7 @@ class FollowRequests extends ImmutablePureComponent {
|
||||||
}, 300, { leading: true });
|
}, 300, { leading: true });
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, accountIds, hasMore, multiColumn, locked, domain, isLoading } = this.props;
|
const { intl, accountIds, hasMore, multiColumn, locked, domain, isLoading, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
return (
|
return (
|
||||||
|
@ -72,7 +74,7 @@ class FollowRequests extends ImmutablePureComponent {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} icon='user-plus' heading={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} icon='user-plus' heading={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnBackButtonSlim />
|
<ColumnBackButtonSlim />
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='follow_requests'
|
scrollKey='follow_requests'
|
||||||
|
|
|
@ -19,7 +19,8 @@ import HeaderContainer from '../account_timeline/containers/header_container';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
import MissingIndicator from 'mastodon/components/missing_indicator';
|
import MissingIndicator from 'mastodon/components/missing_indicator';
|
||||||
import TimelineHint from 'mastodon/components/timeline_hint';
|
import TimelineHint from 'mastodon/components/timeline_hint';
|
||||||
import { new_features_policy } from 'mastodon/initial_state';
|
import { new_features_policy, defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.account', defaultMessage: 'Account' },
|
title: { id: 'column.account', defaultMessage: 'Account' },
|
||||||
|
@ -34,6 +35,7 @@ const mapStateToProps = (state, props) => ({
|
||||||
isLoading: state.getIn(['user_lists', 'followers', props.params.accountId, 'isLoading'], true),
|
isLoading: state.getIn(['user_lists', 'followers', props.params.accountId, 'isLoading'], true),
|
||||||
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
|
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
|
||||||
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
||||||
|
columnWidth: state.getIn(['settings', 'account', 'columnWidth'], defaultColumnWidth),
|
||||||
});
|
});
|
||||||
|
|
||||||
const RemoteHint = ({ url }) => (
|
const RemoteHint = ({ url }) => (
|
||||||
|
@ -60,6 +62,7 @@ class Followers extends ImmutablePureComponent {
|
||||||
remote: PropTypes.bool,
|
remote: PropTypes.bool,
|
||||||
remoteUrl: PropTypes.string,
|
remoteUrl: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -84,12 +87,16 @@ class Followers extends ImmutablePureComponent {
|
||||||
this.column.scrollTop();
|
this.column.scrollTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
this.props.dispatch(changeSetting(['account', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
this.column = c;
|
this.column = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, remote, remoteUrl, intl } = this.props;
|
const { accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, remote, remoteUrl, columnWidth, intl } = this.props;
|
||||||
|
|
||||||
if (!isAccount) {
|
if (!isAccount) {
|
||||||
return (
|
return (
|
||||||
|
@ -120,7 +127,7 @@ class Followers extends ImmutablePureComponent {
|
||||||
const remoteMessage = remote ? <RemoteHint url={remoteUrl} /> : null;
|
const remoteMessage = remote ? <RemoteHint url={remoteUrl} /> : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='user'
|
icon='user'
|
||||||
active={false}
|
active={false}
|
||||||
|
@ -128,6 +135,8 @@ class Followers extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={false}
|
pinned={false}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -19,7 +19,8 @@ import HeaderContainer from '../account_timeline/containers/header_container';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
import MissingIndicator from 'mastodon/components/missing_indicator';
|
import MissingIndicator from 'mastodon/components/missing_indicator';
|
||||||
import TimelineHint from 'mastodon/components/timeline_hint';
|
import TimelineHint from 'mastodon/components/timeline_hint';
|
||||||
import { new_features_policy } from 'mastodon/initial_state';
|
import { new_features_policy, defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.account', defaultMessage: 'Account' },
|
title: { id: 'column.account', defaultMessage: 'Account' },
|
||||||
|
@ -34,6 +35,7 @@ const mapStateToProps = (state, props) => ({
|
||||||
isLoading: state.getIn(['user_lists', 'following', props.params.accountId, 'isLoading'], true),
|
isLoading: state.getIn(['user_lists', 'following', props.params.accountId, 'isLoading'], true),
|
||||||
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
|
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
|
||||||
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
||||||
|
columnWidth: state.getIn(['settings', 'account', 'columnWidth'], defaultColumnWidth),
|
||||||
});
|
});
|
||||||
|
|
||||||
const RemoteHint = ({ url }) => (
|
const RemoteHint = ({ url }) => (
|
||||||
|
@ -60,6 +62,7 @@ class Following extends ImmutablePureComponent {
|
||||||
remote: PropTypes.bool,
|
remote: PropTypes.bool,
|
||||||
remoteUrl: PropTypes.string,
|
remoteUrl: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -84,12 +87,16 @@ class Following extends ImmutablePureComponent {
|
||||||
this.column.scrollTop();
|
this.column.scrollTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
this.props.dispatch(changeSetting(['account', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
this.column = c;
|
this.column = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, remote, remoteUrl, intl } = this.props;
|
const { accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, remote, remoteUrl, columnWidth, intl } = this.props;
|
||||||
|
|
||||||
if (!isAccount) {
|
if (!isAccount) {
|
||||||
return (
|
return (
|
||||||
|
@ -120,7 +127,7 @@ class Following extends ImmutablePureComponent {
|
||||||
const remoteMessage = remote ? <RemoteHint url={remoteUrl} /> : null;
|
const remoteMessage = remote ? <RemoteHint url={remoteUrl} /> : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='user'
|
icon='user'
|
||||||
active={false}
|
active={false}
|
||||||
|
@ -128,6 +135,8 @@ class Following extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={false}
|
pinned={false}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { me, profile_directory, showTrends, enable_limited_timeline, enableEmptyColumn } from '../../initial_state';
|
import { me, profile_directory, showTrends, enable_limited_timeline, enableEmptyColumn, defaultColumnWidth } from '../../initial_state';
|
||||||
import { fetchFollowRequests } from 'mastodon/actions/accounts';
|
import { fetchFollowRequests } from 'mastodon/actions/accounts';
|
||||||
import { fetchFavouriteDomains } from 'mastodon/actions/favourite_domains';
|
import { fetchFavouriteDomains } from 'mastodon/actions/favourite_domains';
|
||||||
import { fetchFavouriteTags } from 'mastodon/actions/favourite_tags';
|
import { fetchFavouriteTags } from 'mastodon/actions/favourite_tags';
|
||||||
|
@ -61,6 +61,7 @@ const mapStateToProps = state => ({
|
||||||
lists: getOrderedLists(state),
|
lists: getOrderedLists(state),
|
||||||
favourite_domains: getOrderedDomains(state),
|
favourite_domains: getOrderedDomains(state),
|
||||||
favourite_tags: getOrderedTags(state),
|
favourite_tags: getOrderedTags(state),
|
||||||
|
columnWidth: defaultColumnWidth,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
@ -94,6 +95,7 @@ class GettingStarted extends ImmutablePureComponent {
|
||||||
myAccount: ImmutablePropTypes.map.isRequired,
|
myAccount: ImmutablePropTypes.map.isRequired,
|
||||||
columns: ImmutablePropTypes.list,
|
columns: ImmutablePropTypes.list,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
fetchFollowRequests: PropTypes.func.isRequired,
|
fetchFollowRequests: PropTypes.func.isRequired,
|
||||||
fetchFavouriteDomains: PropTypes.func.isRequired,
|
fetchFavouriteDomains: PropTypes.func.isRequired,
|
||||||
fetchFavouriteTags: PropTypes.func.isRequired,
|
fetchFavouriteTags: PropTypes.func.isRequired,
|
||||||
|
@ -118,7 +120,7 @@ class GettingStarted extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, myAccount, columns, multiColumn, unreadFollowRequests, lists, favourite_domains, favourite_tags } = this.props;
|
const { intl, myAccount, columns, multiColumn, unreadFollowRequests, lists, favourite_domains, favourite_tags, columnWidth } = this.props;
|
||||||
|
|
||||||
const navItems = [];
|
const navItems = [];
|
||||||
let height = (multiColumn) ? 0 : 60;
|
let height = (multiColumn) ? 0 : 60;
|
||||||
|
@ -264,7 +266,7 @@ class GettingStarted extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.menu)}>
|
<Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.menu)} columnWidth={columnWidth}>
|
||||||
{multiColumn && <div className='column-header__wrapper'>
|
{multiColumn && <div className='column-header__wrapper'>
|
||||||
<h1 className='column-header'>
|
<h1 className='column-header'>
|
||||||
<button>
|
<button>
|
||||||
|
|
|
@ -13,6 +13,8 @@ import RadioButton from 'mastodon/components/radio_button';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import LoadMore from 'mastodon/components/load_more';
|
import LoadMore from 'mastodon/components/load_more';
|
||||||
import { ScrollContainer } from 'react-router-scroll-4';
|
import { ScrollContainer } from 'react-router-scroll-4';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.group_directory', defaultMessage: 'Browse groups' },
|
title: { id: 'column.group_directory', defaultMessage: 'Browse groups' },
|
||||||
|
@ -23,6 +25,7 @@ const messages = defineMessages({
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
accountIds: state.getIn(['user_lists', 'group_directory', 'items'], ImmutableList()),
|
accountIds: state.getIn(['user_lists', 'group_directory', 'items'], ImmutableList()),
|
||||||
isLoading: state.getIn(['user_lists', 'group_directory', 'isLoading'], true),
|
isLoading: state.getIn(['user_lists', 'group_directory', 'isLoading'], true),
|
||||||
|
columnWidth: state.getIn(['settings', 'group_directory', 'columnWidth'], defaultColumnWidth),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -40,6 +43,7 @@ class GroupDirectory extends React.PureComponent {
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
params: PropTypes.shape({
|
params: PropTypes.shape({
|
||||||
order: PropTypes.string,
|
order: PropTypes.string,
|
||||||
}),
|
}),
|
||||||
|
@ -107,8 +111,12 @@ class GroupDirectory extends React.PureComponent {
|
||||||
dispatch(expandGroupDirectory(this.getParams(this.props, this.state)));
|
dispatch(expandGroupDirectory(this.getParams(this.props, this.state)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
this.props.dispatch(changeSetting(['group_directory', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { isLoading, accountIds, intl, columnId, multiColumn } = this.props;
|
const { isLoading, accountIds, intl, columnId, multiColumn, columnWidth } = this.props;
|
||||||
const { order } = this.getParams(this.props, this.state);
|
const { order } = this.getParams(this.props, this.state);
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
|
@ -130,7 +138,7 @@ class GroupDirectory extends React.PureComponent {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='address-book-o'
|
icon='address-book-o'
|
||||||
title={intl.formatMessage(messages.title)}
|
title={intl.formatMessage(messages.title)}
|
||||||
|
@ -139,6 +147,8 @@ class GroupDirectory extends React.PureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{multiColumn && !pinned ? <ScrollContainer scrollKey='group_directory'>{scrollableArea}</ScrollContainer> : scrollableArea}
|
{multiColumn && !pinned ? <ScrollContainer scrollKey='group_directory'>{scrollableArea}</ScrollContainer> : scrollableArea}
|
||||||
|
|
|
@ -15,6 +15,9 @@ import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||||
import ColumnSettingsContainer from './containers/column_settings_container';
|
import ColumnSettingsContainer from './containers/column_settings_container';
|
||||||
import GroupDetail from './components/group_detail';
|
import GroupDetail from './components/group_detail';
|
||||||
import { connectGroupStream } from '../../actions/streaming';
|
import { connectGroupStream } from '../../actions/streaming';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.group', defaultMessage: 'Group timeline' },
|
title: { id: 'column.group', defaultMessage: 'Group timeline' },
|
||||||
|
@ -32,6 +35,7 @@ const makeMapStateToProps = () => {
|
||||||
const onlyMedia = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'onlyMedia']) : state.getIn(['settings', 'group', 'other', 'onlyMedia']);
|
const onlyMedia = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'onlyMedia']) : state.getIn(['settings', 'group', 'other', 'onlyMedia']);
|
||||||
const withoutMedia = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutMedia']) : state.getIn(['settings', 'group', 'other', 'withoutMedia']);
|
const withoutMedia = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutMedia']) : state.getIn(['settings', 'group', 'other', 'withoutMedia']);
|
||||||
const timelineState = state.getIn(['timelines', `group:${id}${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}${tagged ? `:${tagged}` : ''}`]);
|
const timelineState = state.getIn(['timelines', `group:${id}${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}${tagged ? `:${tagged}` : ''}`]);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'group', 'columnWidth']);
|
||||||
const account = getAccount(state, id);
|
const account = getAccount(state, id);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -39,6 +43,7 @@ const makeMapStateToProps = () => {
|
||||||
onlyMedia,
|
onlyMedia,
|
||||||
withoutMedia,
|
withoutMedia,
|
||||||
account,
|
account,
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,6 +71,7 @@ class GroupTimeline extends React.PureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
hasUnread: PropTypes.bool,
|
hasUnread: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
onlyMedia: PropTypes.bool,
|
onlyMedia: PropTypes.bool,
|
||||||
withoutMedia: PropTypes.bool,
|
withoutMedia: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
@ -138,8 +144,18 @@ class GroupTimeline extends React.PureComponent {
|
||||||
this.setState({ animating: false });
|
this.setState({ animating: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['group', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, hasUnread, columnId, multiColumn, onlyMedia, withoutMedia, params: { id, tagged }, account } = this.props;
|
const { intl, hasUnread, columnId, multiColumn, onlyMedia, withoutMedia, params: { id, tagged }, account, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
const { collapsed, animating } = this.state;
|
const { collapsed, animating } = this.state;
|
||||||
|
@ -179,7 +195,7 @@ class GroupTimeline extends React.PureComponent {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={title}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={title} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='users'
|
icon='users'
|
||||||
active={hasUnread}
|
active={hasUnread}
|
||||||
|
@ -190,6 +206,8 @@ class GroupTimeline extends React.PureComponent {
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
extraButton={groupDetailButton}
|
extraButton={groupDetailButton}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer columnId={columnId} />
|
<ColumnSettingsContainer columnId={columnId} />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -14,16 +14,27 @@ import { isEqual } from 'lodash';
|
||||||
import { fetchHashtag, followHashtag, unfollowHashtag } from 'mastodon/actions/tags';
|
import { fetchHashtag, followHashtag, unfollowHashtag } from 'mastodon/actions/tags';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' },
|
followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' },
|
||||||
unfollowHashtag: { id: 'hashtag.unfollow', defaultMessage: 'Unfollow hashtag' },
|
unfollowHashtag: { id: 'hashtag.unfollow', defaultMessage: 'Unfollow hashtag' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => ({
|
const mapStateToProps = (state, { columnId, params }) => {
|
||||||
hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}`, 'unread']) > 0,
|
const uuid = columnId;
|
||||||
tag: state.getIn(['tags', props.params.id]),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
});
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'hashtag', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasUnread: state.getIn(['timelines', `hashtag:${params.id}`, 'unread']) > 0,
|
||||||
|
tag: state.getIn(['tags', params.id]),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -38,6 +49,7 @@ class HashtagTimeline extends React.PureComponent {
|
||||||
hasUnread: PropTypes.bool,
|
hasUnread: PropTypes.bool,
|
||||||
tag: ImmutablePropTypes.map,
|
tag: ImmutablePropTypes.map,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
intl: PropTypes.object,
|
intl: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,8 +178,18 @@ class HashtagTimeline extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['hashtag', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { hasUnread, columnId, multiColumn, tag, intl } = this.props;
|
const { hasUnread, columnId, multiColumn, tag, columnWidth, intl } = this.props;
|
||||||
const { id } = this.props.params;
|
const { id } = this.props.params;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
|
@ -184,7 +206,7 @@ class HashtagTimeline extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={`#${id}`}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={`#${id}`} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='hashtag'
|
icon='hashtag'
|
||||||
active={hasUnread}
|
active={hasUnread}
|
||||||
|
@ -196,6 +218,8 @@ class HashtagTimeline extends React.PureComponent {
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
extraButton={followButton}
|
extraButton={followButton}
|
||||||
showBackButton
|
showBackButton
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
{columnId && <ColumnSettingsContainer columnId={columnId} />}
|
{columnId && <ColumnSettingsContainer columnId={columnId} />}
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -14,6 +14,9 @@ import { fetchAnnouncements, toggleShowAnnouncements } from 'mastodon/actions/an
|
||||||
import AnnouncementsContainer from 'mastodon/features/getting_started/containers/announcements_container';
|
import AnnouncementsContainer from 'mastodon/features/getting_started/containers/announcements_container';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import IconWithBadge from 'mastodon/components/icon_with_badge';
|
import IconWithBadge from 'mastodon/components/icon_with_badge';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.home', defaultMessage: 'Home' },
|
title: { id: 'column.home', defaultMessage: 'Home' },
|
||||||
|
@ -21,14 +24,22 @@ const messages = defineMessages({
|
||||||
hide_announcements: { id: 'home.hide_announcements', defaultMessage: 'Hide announcements' },
|
hide_announcements: { id: 'home.hide_announcements', defaultMessage: 'Hide announcements' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state, { columnId }) => {
|
||||||
hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0,
|
const uuid = columnId;
|
||||||
isPartial: state.getIn(['timelines', 'home', 'isPartial']),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
hasAnnouncements: !state.getIn(['announcements', 'items']).isEmpty(),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
unreadAnnouncements: state.getIn(['announcements', 'items']).count(item => !item.get('read')),
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'home', 'columnWidth']);
|
||||||
showAnnouncements: state.getIn(['announcements', 'show']),
|
|
||||||
visibilities: getHomeVisibilities(state),
|
return {
|
||||||
});
|
hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0,
|
||||||
|
isPartial: state.getIn(['timelines', 'home', 'isPartial']),
|
||||||
|
hasAnnouncements: !state.getIn(['announcements', 'items']).isEmpty(),
|
||||||
|
unreadAnnouncements: state.getIn(['announcements', 'items']).count(item => !item.get('read')),
|
||||||
|
showAnnouncements: state.getIn(['announcements', 'show']),
|
||||||
|
visibilities: getHomeVisibilities(state),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -41,6 +52,7 @@ class HomeTimeline extends React.PureComponent {
|
||||||
isPartial: PropTypes.bool,
|
isPartial: PropTypes.bool,
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
hasAnnouncements: PropTypes.bool,
|
hasAnnouncements: PropTypes.bool,
|
||||||
unreadAnnouncements: PropTypes.number,
|
unreadAnnouncements: PropTypes.number,
|
||||||
showAnnouncements: PropTypes.bool,
|
showAnnouncements: PropTypes.bool,
|
||||||
|
@ -121,8 +133,18 @@ class HomeTimeline extends React.PureComponent {
|
||||||
this.props.dispatch(toggleShowAnnouncements());
|
this.props.dispatch(toggleShowAnnouncements());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['home', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, hasUnread, columnId, multiColumn, hasAnnouncements, unreadAnnouncements, showAnnouncements } = this.props;
|
const { intl, hasUnread, columnId, multiColumn, hasAnnouncements, unreadAnnouncements, showAnnouncements, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
let announcementsButton = null;
|
let announcementsButton = null;
|
||||||
|
@ -142,7 +164,7 @@ class HomeTimeline extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='home'
|
icon='home'
|
||||||
active={hasUnread}
|
active={hasUnread}
|
||||||
|
@ -154,6 +176,8 @@ class HomeTimeline extends React.PureComponent {
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
extraButton={announcementsButton}
|
extraButton={announcementsButton}
|
||||||
appendContent={hasAnnouncements && showAnnouncements && <AnnouncementsContainer />}
|
appendContent={hasAnnouncements && showAnnouncements && <AnnouncementsContainer />}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -4,24 +4,31 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' },
|
heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' },
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @injectIntl
|
const mapStateToProps = state => ({
|
||||||
|
columnWidth: defaultColumnWidth,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default @connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
class KeyboardShortcuts extends ImmutablePureComponent {
|
class KeyboardShortcuts extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, multiColumn } = this.props;
|
const { intl, multiColumn, columnWidth } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} icon='question' heading={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} icon='question' heading={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnBackButtonSlim />
|
<ColumnBackButtonSlim />
|
||||||
<div className='keyboard-shortcuts scrollable optionally-scrollable'>
|
<div className='keyboard-shortcuts scrollable optionally-scrollable'>
|
||||||
<table>
|
<table>
|
||||||
|
|
|
@ -9,15 +9,26 @@ import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||||
import { getLimitedVisibilities } from 'mastodon/selectors';
|
import { getLimitedVisibilities } from 'mastodon/selectors';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import ColumnSettingsContainer from './containers/column_settings_container';
|
import ColumnSettingsContainer from './containers/column_settings_container';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.limited', defaultMessage: 'Limited' },
|
title: { id: 'column.limited', defaultMessage: 'Limited' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state, { columnId }) => {
|
||||||
hasUnread: state.getIn(['timelines', 'limited', 'unread']) > 0,
|
const uuid = columnId;
|
||||||
visibilities: getLimitedVisibilities(state),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
});
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'limited', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasUnread: state.getIn(['timelines', 'limited', 'unread']) > 0,
|
||||||
|
visibilities: getLimitedVisibilities(state),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -30,6 +41,7 @@ class LimitedTimeline extends React.PureComponent {
|
||||||
visibilities: PropTypes.arrayOf(PropTypes.string),
|
visibilities: PropTypes.arrayOf(PropTypes.string),
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePin = () => {
|
handlePin = () => {
|
||||||
|
@ -75,12 +87,22 @@ class LimitedTimeline extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['limited', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, hasUnread, columnId, multiColumn } = this.props;
|
const { intl, hasUnread, columnId, multiColumn, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='lock'
|
icon='lock'
|
||||||
active={hasUnread}
|
active={hasUnread}
|
||||||
|
@ -90,6 +112,8 @@ class LimitedTimeline extends React.PureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -16,6 +16,9 @@ import MissingIndicator from '../../components/missing_indicator';
|
||||||
import LoadingIndicator from '../../components/loading_indicator';
|
import LoadingIndicator from '../../components/loading_indicator';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
import RadioButton from 'mastodon/components/radio_button';
|
import RadioButton from 'mastodon/components/radio_button';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
||||||
|
@ -25,10 +28,18 @@ const messages = defineMessages({
|
||||||
list: { id: 'lists.replies_policy.list', defaultMessage: 'Members of the list' },
|
list: { id: 'lists.replies_policy.list', defaultMessage: 'Members of the list' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => ({
|
const mapStateToProps = (state, { columnId, params }) => {
|
||||||
list: state.getIn(['lists', props.params.id]),
|
const uuid = columnId;
|
||||||
hasUnread: state.getIn(['timelines', `list:${props.params.id}`, 'unread']) > 0,
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
});
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'list', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
list: state.getIn(['lists', params.id]),
|
||||||
|
hasUnread: state.getIn(['timelines', `list:${params.id}`, 'unread']) > 0,
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -44,6 +55,7 @@ class ListTimeline extends React.PureComponent {
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
hasUnread: PropTypes.bool,
|
hasUnread: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
list: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
|
list: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
@ -140,8 +152,18 @@ class ListTimeline extends React.PureComponent {
|
||||||
dispatch(updateList(id, undefined, false, target.value));
|
dispatch(updateList(id, undefined, false, target.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['list', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { hasUnread, columnId, multiColumn, list, intl } = this.props;
|
const { hasUnread, columnId, multiColumn, list, columnWidth, intl } = this.props;
|
||||||
const { id } = this.props.params;
|
const { id } = this.props.params;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
const title = list ? list.get('title') : id;
|
const title = list ? list.get('title') : id;
|
||||||
|
@ -165,7 +187,7 @@ class ListTimeline extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={title}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={title} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='list-ul'
|
icon='list-ul'
|
||||||
active={hasUnread}
|
active={hasUnread}
|
||||||
|
@ -175,6 +197,8 @@ class ListTimeline extends React.PureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<div className='column-settings__row column-header__links'>
|
<div className='column-settings__row column-header__links'>
|
||||||
<button className='text-btn column-header__setting-btn' tabIndex='0' onClick={this.handleEditClick}>
|
<button className='text-btn column-header__setting-btn' tabIndex='0' onClick={this.handleEditClick}>
|
||||||
|
|
|
@ -13,6 +13,7 @@ import NewListForm from './components/new_list_form';
|
||||||
import List from './components/list';
|
import List from './components/list';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.lists', defaultMessage: 'Lists' },
|
heading: { id: 'column.lists', defaultMessage: 'Lists' },
|
||||||
|
@ -29,6 +30,7 @@ const getOrderedLists = createSelector([state => state.get('lists')], lists => {
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
lists: getOrderedLists(state),
|
lists: getOrderedLists(state),
|
||||||
|
columnWidth: defaultColumnWidth,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -41,6 +43,7 @@ class Lists extends ImmutablePureComponent {
|
||||||
lists: ImmutablePropTypes.list,
|
lists: ImmutablePropTypes.list,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -48,7 +51,7 @@ class Lists extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, lists, multiColumn } = this.props;
|
const { intl, lists, multiColumn, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!lists) {
|
if (!lists) {
|
||||||
return (
|
return (
|
||||||
|
@ -61,7 +64,7 @@ class Lists extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.lists' defaultMessage="You don't have any lists yet. When you create one, it will show up here." />;
|
const emptyMessage = <FormattedMessage id='empty_column.lists' defaultMessage="You don't have any lists yet. When you create one, it will show up here." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} icon='list-ul' heading={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} icon='list-ul' heading={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnBackButtonSlim />
|
<ColumnBackButtonSlim />
|
||||||
|
|
||||||
<NewListForm />
|
<NewListForm />
|
||||||
|
|
|
@ -11,12 +11,23 @@ import Column from '../ui/components/column';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
import ColumnHeader from '../../components/column_header';
|
import ColumnHeader from '../../components/column_header';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => ({
|
const mapStateToProps = (state, { columnId, params }) => {
|
||||||
accountIds: state.getIn(['user_lists', 'mentioned_by', props.params.statusId, 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['user_lists', 'mentioned_by', props.params.statusId, 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
hasMore: !!state.getIn(['user_lists', 'mentioned_by', props.params.statusId, 'next']),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
});
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'mentions', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
accountIds: state.getIn(['user_lists', 'mentioned_by', params.statusId, 'items']),
|
||||||
|
isLoading: state.getIn(['user_lists', 'mentioned_by', params.statusId, 'isLoading'], true),
|
||||||
|
hasMore: !!state.getIn(['user_lists', 'mentioned_by', params.statusId, 'next']),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -27,6 +38,7 @@ class Mentions extends ImmutablePureComponent {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
accountIds: ImmutablePropTypes.list,
|
accountIds: ImmutablePropTypes.list,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
|
@ -48,8 +60,18 @@ class Mentions extends ImmutablePureComponent {
|
||||||
this.props.dispatch(expandMentions(this.props.params.statusId));
|
this.props.dispatch(expandMentions(this.props.params.statusId));
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['mentions', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { accountIds, multiColumn, hasMore, isLoading } = this.props;
|
const { accountIds, multiColumn, hasMore, isLoading, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
return (
|
return (
|
||||||
|
@ -62,10 +84,12 @@ class Mentions extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.mentions' defaultMessage='No one has mentioned this toot.' />;
|
const emptyMessage = <FormattedMessage id='empty_column.mentions' defaultMessage='No one has mentioned this toot.' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn}>
|
<Column bindToDocument={!multiColumn} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
showBackButton
|
showBackButton
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
|
|
|
@ -11,6 +11,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||||
import AccountContainer from '../../containers/account_container';
|
import AccountContainer from '../../containers/account_container';
|
||||||
import { fetchMutes, expandMutes } from '../../actions/mutes';
|
import { fetchMutes, expandMutes } from '../../actions/mutes';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.mutes', defaultMessage: 'Muted users' },
|
heading: { id: 'column.mutes', defaultMessage: 'Muted users' },
|
||||||
|
@ -20,6 +21,7 @@ const mapStateToProps = state => ({
|
||||||
accountIds: state.getIn(['user_lists', 'mutes', 'items']),
|
accountIds: state.getIn(['user_lists', 'mutes', 'items']),
|
||||||
hasMore: !!state.getIn(['user_lists', 'mutes', 'next']),
|
hasMore: !!state.getIn(['user_lists', 'mutes', 'next']),
|
||||||
isLoading: state.getIn(['user_lists', 'mutes', 'isLoading'], true),
|
isLoading: state.getIn(['user_lists', 'mutes', 'isLoading'], true),
|
||||||
|
columnWidth: defaultColumnWidth,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -34,6 +36,7 @@ class Mutes extends ImmutablePureComponent {
|
||||||
accountIds: ImmutablePropTypes.list,
|
accountIds: ImmutablePropTypes.list,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -45,7 +48,7 @@ class Mutes extends ImmutablePureComponent {
|
||||||
}, 300, { leading: true });
|
}, 300, { leading: true });
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, hasMore, accountIds, multiColumn, isLoading } = this.props;
|
const { intl, hasMore, accountIds, multiColumn, isLoading, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
return (
|
return (
|
||||||
|
@ -58,7 +61,7 @@ class Mutes extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />;
|
const emptyMessage = <FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} icon='volume-off' heading={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} icon='volume-off' heading={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnBackButtonSlim />
|
<ColumnBackButtonSlim />
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='mutes'
|
scrollKey='mutes'
|
||||||
|
|
|
@ -26,6 +26,9 @@ import LoadGap from '../../components/load_gap';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
import compareId from 'mastodon/compare_id';
|
import compareId from 'mastodon/compare_id';
|
||||||
import NotificationsPermissionBanner from './components/notifications_permission_banner';
|
import NotificationsPermissionBanner from './components/notifications_permission_banner';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.notifications', defaultMessage: 'Notifications' },
|
title: { id: 'column.notifications', defaultMessage: 'Notifications' },
|
||||||
|
@ -53,17 +56,25 @@ const getNotifications = createSelector([
|
||||||
return notifications.filter(item => item === null || allowedType === item.get('type'));
|
return notifications.filter(item => item === null || allowedType === item.get('type'));
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state, { columnId }) => {
|
||||||
showFilterBar: state.getIn(['settings', 'notifications', 'quickFilter', 'show']),
|
const uuid = columnId;
|
||||||
notifications: getNotifications(state),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
isLoading: state.getIn(['notifications', 'isLoading'], true),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
isUnread: state.getIn(['notifications', 'unread']) > 0 || state.getIn(['notifications', 'pendingItems']).size > 0,
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'notifications', 'columnWidth']);
|
||||||
hasMore: state.getIn(['notifications', 'hasMore']),
|
|
||||||
numPending: state.getIn(['notifications', 'pendingItems'], ImmutableList()).size,
|
return {
|
||||||
lastReadId: state.getIn(['settings', 'notifications', 'showUnread']) ? state.getIn(['notifications', 'readMarkerId']) : '0',
|
showFilterBar: state.getIn(['settings', 'notifications', 'quickFilter', 'show']),
|
||||||
canMarkAsRead: state.getIn(['settings', 'notifications', 'showUnread']) && state.getIn(['notifications', 'readMarkerId']) !== '0' && getNotifications(state).some(item => item !== null && compareId(item.get('id'), state.getIn(['notifications', 'readMarkerId'])) > 0),
|
notifications: getNotifications(state),
|
||||||
needsNotificationPermission: state.getIn(['settings', 'notifications', 'alerts']).includes(true) && state.getIn(['notifications', 'browserSupport']) && state.getIn(['notifications', 'browserPermission']) === 'default' && !state.getIn(['settings', 'notifications', 'dismissPermissionBanner']),
|
isLoading: state.getIn(['notifications', 'isLoading'], true),
|
||||||
});
|
isUnread: state.getIn(['notifications', 'unread']) > 0 || state.getIn(['notifications', 'pendingItems']).size > 0,
|
||||||
|
hasMore: state.getIn(['notifications', 'hasMore']),
|
||||||
|
numPending: state.getIn(['notifications', 'pendingItems'], ImmutableList()).size,
|
||||||
|
lastReadId: state.getIn(['settings', 'notifications', 'showUnread']) ? state.getIn(['notifications', 'readMarkerId']) : '0',
|
||||||
|
canMarkAsRead: state.getIn(['settings', 'notifications', 'showUnread']) && state.getIn(['notifications', 'readMarkerId']) !== '0' && getNotifications(state).some(item => item !== null && compareId(item.get('id'), state.getIn(['notifications', 'readMarkerId'])) > 0),
|
||||||
|
needsNotificationPermission: state.getIn(['settings', 'notifications', 'alerts']).includes(true) && state.getIn(['notifications', 'browserSupport']) && state.getIn(['notifications', 'browserPermission']) === 'default' && !state.getIn(['settings', 'notifications', 'dismissPermissionBanner']),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -78,6 +89,7 @@ class Notifications extends React.PureComponent {
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
isUnread: PropTypes.bool,
|
isUnread: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
numPending: PropTypes.number,
|
numPending: PropTypes.number,
|
||||||
lastReadId: PropTypes.string,
|
lastReadId: PropTypes.string,
|
||||||
|
@ -174,8 +186,18 @@ class Notifications extends React.PureComponent {
|
||||||
this.props.dispatch(submitMarkers({ immediate: true }));
|
this.props.dispatch(submitMarkers({ immediate: true }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['notifications', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, notifications, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, showFilterBar, lastReadId, canMarkAsRead, needsNotificationPermission } = this.props;
|
const { intl, notifications, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, showFilterBar, lastReadId, canMarkAsRead, needsNotificationPermission, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. When other people interact with you, you will see it here." />;
|
const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. When other people interact with you, you will see it here." />;
|
||||||
|
|
||||||
|
@ -248,7 +270,7 @@ class Notifications extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setColumnRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setColumnRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='bell'
|
icon='bell'
|
||||||
active={isUnread}
|
active={isUnread}
|
||||||
|
@ -259,6 +281,8 @@ class Notifications extends React.PureComponent {
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
extraButton={extraButton}
|
extraButton={extraButton}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||||
import StatusList from '../../components/status_list';
|
import StatusList from '../../components/status_list';
|
||||||
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 { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.pins', defaultMessage: 'Pinned toot' },
|
heading: { id: 'column.pins', defaultMessage: 'Pinned toot' },
|
||||||
|
@ -16,6 +17,7 @@ const messages = defineMessages({
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
statusIds: state.getIn(['status_lists', 'pins', 'items']),
|
statusIds: state.getIn(['status_lists', 'pins', 'items']),
|
||||||
hasMore: !!state.getIn(['status_lists', 'pins', 'next']),
|
hasMore: !!state.getIn(['status_lists', 'pins', 'next']),
|
||||||
|
columnWidth: defaultColumnWidth,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -28,6 +30,7 @@ class PinnedStatuses extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
hasMore: PropTypes.bool.isRequired,
|
hasMore: PropTypes.bool.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -43,10 +46,10 @@ class PinnedStatuses extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, statusIds, hasMore, multiColumn } = this.props;
|
const { intl, statusIds, hasMore, multiColumn, columnWidth } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} icon='thumb-tack' heading={intl.formatMessage(messages.heading)} ref={this.setRef}>
|
<Column bindToDocument={!multiColumn} icon='thumb-tack' heading={intl.formatMessage(messages.heading)} ref={this.setRef} columnWidth={columnWidth}>
|
||||||
<ColumnBackButtonSlim />
|
<ColumnBackButtonSlim />
|
||||||
<StatusList
|
<StatusList
|
||||||
statusIds={statusIds}
|
statusIds={statusIds}
|
||||||
|
|
|
@ -9,6 +9,9 @@ import { expandPublicTimeline } from '../../actions/timelines';
|
||||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||||
import ColumnSettingsContainer from './containers/column_settings_container';
|
import ColumnSettingsContainer from './containers/column_settings_container';
|
||||||
import { connectPublicStream } from '../../actions/streaming';
|
import { connectPublicStream } from '../../actions/streaming';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.public', defaultMessage: 'Federated timeline' },
|
title: { id: 'column.public', defaultMessage: 'Federated timeline' },
|
||||||
|
@ -22,6 +25,7 @@ const mapStateToProps = (state, { columnId }) => {
|
||||||
const withoutMedia = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutMedia']) : state.getIn(['settings', 'public', 'other', 'withoutMedia']);
|
const withoutMedia = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutMedia']) : state.getIn(['settings', 'public', 'other', 'withoutMedia']);
|
||||||
const withoutBot = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutBot']) : state.getIn(['settings', 'public', 'other', 'withoutBot']);
|
const withoutBot = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'withoutBot']) : state.getIn(['settings', 'public', 'other', 'withoutBot']);
|
||||||
const onlyRemote = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'onlyRemote']) : state.getIn(['settings', 'public', 'other', 'onlyRemote']);
|
const onlyRemote = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'onlyRemote']) : state.getIn(['settings', 'public', 'other', 'onlyRemote']);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'public', 'columnWidth']);
|
||||||
const timelineState = state.getIn(['timelines', `public${onlyRemote ? ':remote' : ''}${withoutBot ? ':nobot' : ':bot'}${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}`]);
|
const timelineState = state.getIn(['timelines', `public${onlyRemote ? ':remote' : ''}${withoutBot ? ':nobot' : ':bot'}${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}`]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -30,6 +34,7 @@ const mapStateToProps = (state, { columnId }) => {
|
||||||
withoutMedia,
|
withoutMedia,
|
||||||
withoutBot,
|
withoutBot,
|
||||||
onlyRemote,
|
onlyRemote,
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,6 +58,7 @@ class PublicTimeline extends React.PureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
hasUnread: PropTypes.bool,
|
hasUnread: PropTypes.bool,
|
||||||
onlyMedia: PropTypes.bool,
|
onlyMedia: PropTypes.bool,
|
||||||
withoutMedia: PropTypes.bool,
|
withoutMedia: PropTypes.bool,
|
||||||
|
@ -79,6 +85,16 @@ class PublicTimeline extends React.PureComponent {
|
||||||
this.column.scrollTop();
|
this.column.scrollTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['public', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { dispatch, onlyMedia, withoutMedia, withoutBot, onlyRemote } = this.props;
|
const { dispatch, onlyMedia, withoutMedia, withoutBot, onlyRemote } = this.props;
|
||||||
|
|
||||||
|
@ -114,11 +130,11 @@ class PublicTimeline extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, columnId, hasUnread, multiColumn, onlyMedia, withoutMedia, withoutBot, onlyRemote } = this.props;
|
const { intl, columnId, hasUnread, multiColumn, onlyMedia, withoutMedia, withoutBot, onlyRemote, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='globe'
|
icon='globe'
|
||||||
active={hasUnread}
|
active={hasUnread}
|
||||||
|
@ -128,6 +144,8 @@ class PublicTimeline extends React.PureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer columnId={columnId} />
|
<ColumnSettingsContainer columnId={columnId} />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -13,16 +13,27 @@ import Icon from 'mastodon/components/icon';
|
||||||
import ColumnHeader from '../../components/column_header';
|
import ColumnHeader from '../../components/column_header';
|
||||||
import ReactedHeaderContaier from '../reactioned/containers/header_container';
|
import ReactedHeaderContaier from '../reactioned/containers/header_container';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => ({
|
const mapStateToProps = (state, { columnId, params }) => {
|
||||||
accountIds: state.getIn(['user_lists', 'reblogged_by', props.params.statusId, 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['user_lists', 'reblogged_by', props.params.statusId, 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
hasMore: !!state.getIn(['user_lists', 'reblogged_by', props.params.statusId, 'next']),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
});
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'reblogs', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
accountIds: state.getIn(['user_lists', 'reblogged_by', params.statusId, 'items']),
|
||||||
|
isLoading: state.getIn(['user_lists', 'reblogged_by', params.statusId, 'isLoading'], true),
|
||||||
|
hasMore: !!state.getIn(['user_lists', 'reblogged_by', params.statusId, 'next']),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -33,6 +44,7 @@ class Reblogs extends ImmutablePureComponent {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
accountIds: ImmutablePropTypes.list,
|
accountIds: ImmutablePropTypes.list,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
|
@ -58,8 +70,18 @@ class Reblogs extends ImmutablePureComponent {
|
||||||
this.props.dispatch(expandReblogs(this.props.params.statusId));
|
this.props.dispatch(expandReblogs(this.props.params.statusId));
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['reblogs', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, accountIds, multiColumn, hasMore, isLoading } = this.props;
|
const { intl, accountIds, multiColumn, hasMore, isLoading, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
return (
|
return (
|
||||||
|
@ -72,10 +94,12 @@ class Reblogs extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='status.reblogs.empty' defaultMessage='No one has boosted this toot yet. When someone does, they will show up here.' />;
|
const emptyMessage = <FormattedMessage id='status.reblogs.empty' defaultMessage='No one has boosted this toot yet. When someone does, they will show up here.' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn}>
|
<Column bindToDocument={!multiColumn} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
showBackButton
|
showBackButton
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
extraButton={(
|
extraButton={(
|
||||||
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -12,17 +12,28 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ReactedHeaderContaier from '../reactioned/containers/header_container';
|
import ReactedHeaderContaier from '../reactioned/containers/header_container';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||||
heading: { id: 'column.referred_by_statuses', defaultMessage: 'Referred by posts' },
|
heading: { id: 'column.referred_by_statuses', defaultMessage: 'Referred by posts' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => ({
|
const mapStateToProps = (state, { columnId, params }) => {
|
||||||
statusIds: state.getIn(['status_status_lists', 'referred_by', props.params.statusId, 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['status_status_lists', 'referred_by', props.params.statusId, 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
hasMore: !!state.getIn(['status_status_lists', 'referred_by', props.params.statusId, 'next']),
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
});
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'referred_by_statuses', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusIds: state.getIn(['status_status_lists', 'referred_by', params.statusId, 'items']),
|
||||||
|
isLoading: state.getIn(['status_status_lists', 'referred_by', params.statusId, 'isLoading'], true),
|
||||||
|
hasMore: !!state.getIn(['status_status_lists', 'referred_by', params.statusId, 'next']),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -33,6 +44,7 @@ class ReferredByStatuses extends ImmutablePureComponent {
|
||||||
statusIds: ImmutablePropTypes.list,
|
statusIds: ImmutablePropTypes.list,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
@ -57,8 +69,18 @@ class ReferredByStatuses extends ImmutablePureComponent {
|
||||||
this.props.dispatch(expandReferredByStatuses(this.props.params.statusId));
|
this.props.dispatch(expandReferredByStatuses(this.props.params.statusId));
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['referred_by_statuses', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, statusIds, multiColumn, hasMore, isLoading } = this.props;
|
const { intl, statusIds, multiColumn, hasMore, isLoading, columnWidth } = this.props;
|
||||||
|
|
||||||
if (!statusIds) {
|
if (!statusIds) {
|
||||||
return (
|
return (
|
||||||
|
@ -71,10 +93,12 @@ class ReferredByStatuses extends ImmutablePureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.referred_by_statuses' defaultMessage="There are no referred by posts yet. When someone refers a post, it will appear here." />;
|
const emptyMessage = <FormattedMessage id='empty_column.referred_by_statuses' defaultMessage="There are no referred by posts yet. When someone refers a post, it will appear here." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
showBackButton
|
showBackButton
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
extraButton={(
|
extraButton={(
|
||||||
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -65,6 +65,9 @@ import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from
|
||||||
import { textForScreenReader, defaultMediaVisibility } from '../../components/status';
|
import { textForScreenReader, defaultMediaVisibility } from '../../components/status';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
import DetailedHeaderContaier from './containers/header_container';
|
import DetailedHeaderContaier from './containers/header_container';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
||||||
|
@ -148,8 +151,12 @@ const makeMapStateToProps = () => {
|
||||||
return ImmutableList(contextReference.get(statusId));
|
return ImmutableList(contextReference.get(statusId));
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, { columnId, params }) => {
|
||||||
const status = getStatus(state, { id: props.params.statusId });
|
const uuid = columnId;
|
||||||
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'status', 'columnWidth']);
|
||||||
|
const status = getStatus(state, { id: params.statusId });
|
||||||
const ancestorsIds = status ? getAncestorsIds(state, { id: status.get('in_reply_to_id') }) : ImmutableList();
|
const ancestorsIds = status ? getAncestorsIds(state, { id: status.get('in_reply_to_id') }) : ImmutableList();
|
||||||
const descendantsIds = status ? getDescendantsIds(state, { id: status.get('id') }) : ImmutableList();
|
const descendantsIds = status ? getDescendantsIds(state, { id: status.get('id') }) : ImmutableList();
|
||||||
const referencesIds = status ? getReferencesIds(state, { id: status.get('id') }) : ImmutableList();
|
const referencesIds = status ? getReferencesIds(state, { id: status.get('id') }) : ImmutableList();
|
||||||
|
@ -161,10 +168,11 @@ const makeMapStateToProps = () => {
|
||||||
descendantsIds,
|
descendantsIds,
|
||||||
askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0,
|
askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0,
|
||||||
domain: state.getIn(['meta', 'domain']),
|
domain: state.getIn(['meta', 'domain']),
|
||||||
pictureInPicture: getPictureInPicture(state, { id: props.params.statusId }),
|
pictureInPicture: getPictureInPicture(state, { id: params.statusId }),
|
||||||
emojiMap: customEmojiMap(state),
|
emojiMap: customEmojiMap(state),
|
||||||
referenced: state.getIn(['compose', 'references']).has(id),
|
referenced: state.getIn(['compose', 'references']).has(id),
|
||||||
contextReferenced: state.getIn(['compose', 'context_references']).has(id),
|
contextReferenced: state.getIn(['compose', 'context_references']).has(id),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -190,6 +198,7 @@ class Status extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
askReplyConfirmation: PropTypes.bool,
|
askReplyConfirmation: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
domain: PropTypes.string.isRequired,
|
domain: PropTypes.string.isRequired,
|
||||||
pictureInPicture: ImmutablePropTypes.contains({
|
pictureInPicture: ImmutablePropTypes.contains({
|
||||||
inUse: PropTypes.bool,
|
inUse: PropTypes.bool,
|
||||||
|
@ -561,9 +570,19 @@ class Status extends ImmutablePureComponent {
|
||||||
this.setState({ fullscreen: isFullscreen() });
|
this.setState({ fullscreen: isFullscreen() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['status', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let ancestors, descendants;
|
let ancestors, descendants;
|
||||||
const { status, ancestorsIds, descendantsIds, intl, domain, multiColumn, pictureInPicture, emojiMap, referenced, contextReferenced } = this.props;
|
const { status, ancestorsIds, descendantsIds, intl, domain, multiColumn, pictureInPicture, emojiMap, referenced, contextReferenced, columnWidth } = this.props;
|
||||||
const { fullscreen } = this.state;
|
const { fullscreen } = this.state;
|
||||||
|
|
||||||
if (status === null) {
|
if (status === null) {
|
||||||
|
@ -599,10 +618,12 @@ class Status extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.detailedStatus)}>
|
<Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.detailedStatus)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
showBackButton
|
showBackButton
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
extraButton={(
|
extraButton={(
|
||||||
<button className='column-header__button' title={intl.formatMessage(status.get('hidden') ? messages.revealAll : messages.hideAll)} aria-label={intl.formatMessage(status.get('hidden') ? messages.revealAll : messages.hideAll)} onClick={this.handleToggleAll} aria-pressed={status.get('hidden') ? 'false' : 'true'}><Icon id={status.get('hidden') ? 'eye-slash' : 'eye'} /></button>
|
<button className='column-header__button' title={intl.formatMessage(status.get('hidden') ? messages.revealAll : messages.hideAll)} aria-label={intl.formatMessage(status.get('hidden') ? messages.revealAll : messages.hideAll)} onClick={this.handleToggleAll} aria-pressed={status.get('hidden') ? 'false' : 'true'}><Icon id={status.get('hidden') ? 'eye-slash' : 'eye'} /></button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -22,6 +22,9 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen';
|
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
import DetailedHeaderContaier from '../status/containers/header_container';
|
import DetailedHeaderContaier from '../status/containers/header_container';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
|
revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
|
||||||
|
@ -39,13 +42,18 @@ const makeMapStateToProps = () => {
|
||||||
return ImmutableList(contextReference.get(statusId));
|
return ImmutableList(contextReference.get(statusId));
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, { columnId, params }) => {
|
||||||
const status = getStatus(state, { id: props.params.statusId });
|
const uuid = columnId;
|
||||||
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'status_references', 'columnWidth']);
|
||||||
|
const status = getStatus(state, { id: params.statusId });
|
||||||
const referencesIds = status ? getReferencesIds(state, { id: status.get('id') }) : ImmutableList();
|
const referencesIds = status ? getReferencesIds(state, { id: status.get('id') }) : ImmutableList();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status,
|
status,
|
||||||
referencesIds,
|
referencesIds,
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,6 +75,7 @@ class StatusReferences extends ImmutablePureComponent {
|
||||||
referencesIds: ImmutablePropTypes.list,
|
referencesIds: ImmutablePropTypes.list,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -154,8 +163,18 @@ class StatusReferences extends ImmutablePureComponent {
|
||||||
this.setState({ fullscreen: isFullscreen() });
|
this.setState({ fullscreen: isFullscreen() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['status_references', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { status, referencesIds, intl, multiColumn } = this.props;
|
const { status, referencesIds, intl, multiColumn, columnWidth } = this.props;
|
||||||
const { fullscreen } = this.state;
|
const { fullscreen } = this.state;
|
||||||
|
|
||||||
if (status === null) {
|
if (status === null) {
|
||||||
|
@ -173,10 +192,12 @@ class StatusReferences extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.detailedStatus)}>
|
<Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.detailedStatus)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
showBackButton
|
showBackButton
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
extraButton={(
|
extraButton={(
|
||||||
<button className='column-header__button' title={intl.formatMessage(status.get('hidden') ? messages.revealAll : messages.hideAll)} aria-label={intl.formatMessage(status.get('hidden') ? messages.revealAll : messages.hideAll)} onClick={this.handleToggleAll} aria-pressed={status.get('hidden') ? 'false' : 'true'}><Icon id={status.get('hidden') ? 'eye-slash' : 'eye'} /></button>
|
<button className='column-header__button' title={intl.formatMessage(status.get('hidden') ? messages.revealAll : messages.hideAll)} aria-label={intl.formatMessage(status.get('hidden') ? messages.revealAll : messages.hideAll)} onClick={this.handleToggleAll} aria-pressed={status.get('hidden') ? 'false' : 'true'}><Icon id={status.get('hidden') ? 'eye-slash' : 'eye'} /></button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -18,7 +18,8 @@ import ColumnSettingsContainer from '../account_timeline/containers/column_setti
|
||||||
import HeaderContainer from '../account_timeline/containers/header_container';
|
import HeaderContainer from '../account_timeline/containers/header_container';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
import MissingIndicator from 'mastodon/components/missing_indicator';
|
import MissingIndicator from 'mastodon/components/missing_indicator';
|
||||||
import { new_features_policy } from 'mastodon/initial_state';
|
import { new_features_policy, defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.account', defaultMessage: 'Account' },
|
title: { id: 'column.account', defaultMessage: 'Account' },
|
||||||
|
@ -31,6 +32,7 @@ const mapStateToProps = (state, props) => ({
|
||||||
isLoading: state.getIn(['user_lists', 'subscribing', props.params.accountId, 'isLoading'], true),
|
isLoading: state.getIn(['user_lists', 'subscribing', props.params.accountId, 'isLoading'], true),
|
||||||
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
|
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
|
||||||
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
advancedMode: state.getIn(['settings', 'account', 'other', 'advancedMode'], new_features_policy === 'conservative' ? false : true),
|
||||||
|
columnWidth: state.getIn(['settings', 'account', 'columnWidth'], defaultColumnWidth),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
|
@ -46,6 +48,7 @@ class Subscribing extends ImmutablePureComponent {
|
||||||
blockedBy: PropTypes.bool,
|
blockedBy: PropTypes.bool,
|
||||||
isAccount: PropTypes.bool,
|
isAccount: PropTypes.bool,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -70,12 +73,16 @@ class Subscribing extends ImmutablePureComponent {
|
||||||
this.column.scrollTop();
|
this.column.scrollTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
this.props.dispatch(changeSetting(['account', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
this.column = c;
|
this.column = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, intl } = this.props;
|
const { accountIds, hasMore, blockedBy, isAccount, multiColumn, isLoading, columnWidth, intl } = this.props;
|
||||||
|
|
||||||
if (!isAccount) {
|
if (!isAccount) {
|
||||||
return (
|
return (
|
||||||
|
@ -96,7 +103,7 @@ class Subscribing extends ImmutablePureComponent {
|
||||||
const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' /> : <FormattedMessage id='account.subscribes.empty' defaultMessage="This user doesn't subscribe anyone yet." />;
|
const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' /> : <FormattedMessage id='account.subscribes.empty' defaultMessage="This user doesn't subscribe anyone yet." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='user'
|
icon='user'
|
||||||
active={false}
|
active={false}
|
||||||
|
@ -104,6 +111,8 @@ class Subscribing extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={false}
|
pinned={false}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
|
@ -11,6 +11,9 @@ import ScrollableList from 'mastodon/components/scrollable_list';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import AccountContainer from 'mastodon/containers/account_container';
|
import AccountContainer from 'mastodon/containers/account_container';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
import { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'suggestions.heading', defaultMessage: 'Suggestions' },
|
heading: { id: 'suggestions.heading', defaultMessage: 'Suggestions' },
|
||||||
|
@ -18,10 +21,18 @@ const messages = defineMessages({
|
||||||
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
|
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state, { columnId }) => {
|
||||||
suggestions: state.getIn(['suggestions', 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['suggestions', 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
});
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'suggestions', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
suggestions: state.getIn(['suggestions', 'items']),
|
||||||
|
isLoading: state.getIn(['suggestions', 'isLoading'], true),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -33,6 +44,7 @@ class Suggestions extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,14 +87,24 @@ class Suggestions extends ImmutablePureComponent {
|
||||||
this.column = c;
|
this.column = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['suggestions', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, suggestions, columnId, multiColumn, isLoading } = this.props;
|
const { intl, suggestions, columnId, multiColumn, isLoading, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.suggestions' defaultMessage='No one has suggestions yet.' />;
|
const emptyMessage = <FormattedMessage id='empty_column.suggestions' defaultMessage='No one has suggestions yet.' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='user-plus'
|
icon='user-plus'
|
||||||
title={intl.formatMessage(messages.heading)}
|
title={intl.formatMessage(messages.heading)}
|
||||||
|
@ -91,6 +113,8 @@ class Suggestions extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
showBackButton
|
showBackButton
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,9 @@ import ScrollableList from 'mastodon/components/scrollable_list';
|
||||||
import Hashtag from 'mastodon/components/hashtag';
|
import Hashtag from 'mastodon/components/hashtag';
|
||||||
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 { defaultColumnWidth } from 'mastodon/initial_state';
|
||||||
|
import { changeSetting } from '../../actions/settings';
|
||||||
|
import { changeColumnParams } from '../../actions/columns';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'trends.heading', defaultMessage: 'Trends' },
|
heading: { id: 'trends.heading', defaultMessage: 'Trends' },
|
||||||
|
@ -19,10 +22,18 @@ const messages = defineMessages({
|
||||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state, { columnId }) => {
|
||||||
trends: state.getIn(['trends', 'items']),
|
const uuid = columnId;
|
||||||
isLoading: state.getIn(['trends', 'isLoading'], true),
|
const columns = state.getIn(['settings', 'columns']);
|
||||||
});
|
const index = columns.findIndex(c => c.get('uuid') === uuid);
|
||||||
|
const columnWidth = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'columnWidth']) : state.getIn(['settings', 'trends', 'columnWidth']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
trends: state.getIn(['trends', 'items']),
|
||||||
|
isLoading: state.getIn(['trends', 'isLoading'], true),
|
||||||
|
columnWidth: columnWidth ?? defaultColumnWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
|
@ -34,6 +45,7 @@ class Trends extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
columnId: PropTypes.string,
|
columnId: PropTypes.string,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,14 +93,24 @@ class Trends extends ImmutablePureComponent {
|
||||||
this.column = c;
|
this.column = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleWidthChange = (value) => {
|
||||||
|
const { columnId, dispatch } = this.props;
|
||||||
|
|
||||||
|
if (columnId) {
|
||||||
|
dispatch(changeColumnParams(columnId, 'columnWidth', value));
|
||||||
|
} else {
|
||||||
|
dispatch(changeSetting(['trends', 'columnWidth'], value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, trends, columnId, multiColumn, isLoading } = this.props;
|
const { intl, trends, columnId, multiColumn, isLoading, columnWidth } = this.props;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
|
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.trends' defaultMessage='No one has trends yet.' />;
|
const emptyMessage = <FormattedMessage id='empty_column.trends' defaultMessage='No one has trends yet.' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}>
|
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)} columnWidth={columnWidth}>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='line-chart'
|
icon='line-chart'
|
||||||
title={intl.formatMessage(messages.heading)}
|
title={intl.formatMessage(messages.heading)}
|
||||||
|
@ -97,6 +119,8 @@ class Trends extends ImmutablePureComponent {
|
||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
onWidthChange={this.handleWidthChange}
|
||||||
showBackButton
|
showBackButton
|
||||||
extraButton={(
|
extraButton={(
|
||||||
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { scrollTop } from '../../../scroll';
|
import { scrollTop } from '../../../scroll';
|
||||||
import { isMobile } from '../../../is_mobile';
|
import { isMobile } from '../../../is_mobile';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export default class Column extends React.PureComponent {
|
export default class Column extends React.PureComponent {
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ export default class Column extends React.PureComponent {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
active: PropTypes.bool,
|
active: PropTypes.bool,
|
||||||
hideHeadingOnMobile: PropTypes.bool,
|
hideHeadingOnMobile: PropTypes.bool,
|
||||||
|
columnWidth: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHeaderClick = () => {
|
handleHeaderClick = () => {
|
||||||
|
@ -47,7 +49,7 @@ export default class Column extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { heading, icon, children, active, hideHeadingOnMobile } = this.props;
|
const { heading, icon, children, active, hideHeadingOnMobile, columnWidth } = this.props;
|
||||||
|
|
||||||
const showHeading = heading && (!hideHeadingOnMobile || (hideHeadingOnMobile && !isMobile(window.innerWidth)));
|
const showHeading = heading && (!hideHeadingOnMobile || (hideHeadingOnMobile && !isMobile(window.innerWidth)));
|
||||||
|
|
||||||
|
@ -60,7 +62,7 @@ export default class Column extends React.PureComponent {
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
role='region'
|
role='region'
|
||||||
aria-labelledby={columnHeaderId}
|
aria-labelledby={columnHeaderId}
|
||||||
className='column'
|
className={classNames('column', columnWidth)}
|
||||||
onScroll={this.handleScroll}
|
onScroll={this.handleScroll}
|
||||||
>
|
>
|
||||||
{header}
|
{header}
|
||||||
|
|
|
@ -52,5 +52,6 @@ export const maxReferences = initialState?.status_references?.max_references;
|
||||||
export const matchVisibilityOfReferences = getMeta('match_visibility_of_references');
|
export const matchVisibilityOfReferences = getMeta('match_visibility_of_references');
|
||||||
export const enableEmptyColumn = getMeta('enable_empty_column');
|
export const enableEmptyColumn = getMeta('enable_empty_column');
|
||||||
export const showReloadButton = getMeta('show_reload_button');
|
export const showReloadButton = getMeta('show_reload_button');
|
||||||
|
export const defaultColumnWidth = getMeta('default_column_width');
|
||||||
|
|
||||||
export default initialState;
|
export default initialState;
|
||||||
|
|
|
@ -140,6 +140,11 @@
|
||||||
"column_subheading.favourite_lists": "Favourite lists",
|
"column_subheading.favourite_lists": "Favourite lists",
|
||||||
"column_subheading.favourite_tags": "Favourite tags",
|
"column_subheading.favourite_tags": "Favourite tags",
|
||||||
"column_subheading.settings": "Settings",
|
"column_subheading.settings": "Settings",
|
||||||
|
"column_width.free": "Free",
|
||||||
|
"column_width.x080": "80%",
|
||||||
|
"column_width.x100": "100%",
|
||||||
|
"column_width.x125": "125%",
|
||||||
|
"column_width.x150": "150%",
|
||||||
"community.column_settings.local_only": "Local only",
|
"community.column_settings.local_only": "Local only",
|
||||||
"community.column_settings.media_only": "Media only",
|
"community.column_settings.media_only": "Media only",
|
||||||
"community.column_settings.remote_only": "Remote only",
|
"community.column_settings.remote_only": "Remote only",
|
||||||
|
|
|
@ -140,6 +140,11 @@
|
||||||
"column_subheading.favourite_lists": "お気に入りリスト",
|
"column_subheading.favourite_lists": "お気に入りリスト",
|
||||||
"column_subheading.favourite_tags": "お気に入りハッシュタグ",
|
"column_subheading.favourite_tags": "お気に入りハッシュタグ",
|
||||||
"column_subheading.settings": "設定",
|
"column_subheading.settings": "設定",
|
||||||
|
"column_width.free": "フリー",
|
||||||
|
"column_width.x080": "80%",
|
||||||
|
"column_width.x100": "100%",
|
||||||
|
"column_width.x125": "125%",
|
||||||
|
"column_width.x150": "150%",
|
||||||
"community.column_settings.local_only": "ローカルのみ表示",
|
"community.column_settings.local_only": "ローカルのみ表示",
|
||||||
"community.column_settings.media_only": "メディアのみ表示",
|
"community.column_settings.media_only": "メディアのみ表示",
|
||||||
"community.column_settings.remote_only": "リモートのみ表示",
|
"community.column_settings.remote_only": "リモートのみ表示",
|
||||||
|
|
|
@ -2346,6 +2346,57 @@ a.account__display-name {
|
||||||
> .scrollable {
|
> .scrollable {
|
||||||
background: $ui-base-color;
|
background: $ui-base-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layout-multiple-columns &.free {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-multiple-columns &.x080 {
|
||||||
|
width: 350px * 0.8;
|
||||||
|
|
||||||
|
.status__action-bar {
|
||||||
|
zoom: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-multiple-columns &.x125 {
|
||||||
|
width: 350px * 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-multiple-columns &.x150 {
|
||||||
|
width: 350px * 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-multiple-columns &.x200 {
|
||||||
|
width: 350px * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.column-width {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 36px;
|
||||||
|
padding: 4px;
|
||||||
|
margin: 0 2px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: $ui-base-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item.active {
|
||||||
|
color: $primary-text-color;
|
||||||
|
background-color: $ui-highlight-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=radio] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui {
|
.ui {
|
||||||
|
|
|
@ -89,6 +89,7 @@ class UserSettingsDecorator
|
||||||
user.settings['confirm_follow_from_bot'] = confirm_follow_from_bot_preference if change?('setting_confirm_follow_from_bot')
|
user.settings['confirm_follow_from_bot'] = confirm_follow_from_bot_preference if change?('setting_confirm_follow_from_bot')
|
||||||
user.settings['default_search_searchability'] = default_search_searchability_preference if change?('setting_default_search_searchability')
|
user.settings['default_search_searchability'] = default_search_searchability_preference if change?('setting_default_search_searchability')
|
||||||
user.settings['show_reload_button'] = show_reload_button_preference if change?('setting_show_reload_button')
|
user.settings['show_reload_button'] = show_reload_button_preference if change?('setting_show_reload_button')
|
||||||
|
user.settings['default_column_width'] = default_column_width_preference if change?('setting_default_column_width')
|
||||||
end
|
end
|
||||||
|
|
||||||
def merged_notification_emails
|
def merged_notification_emails
|
||||||
|
@ -331,6 +332,10 @@ end
|
||||||
boolean_cast_setting 'setting_show_reload_button'
|
boolean_cast_setting 'setting_show_reload_button'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def default_column_width_preference
|
||||||
|
settings['setting_default_column_width']
|
||||||
|
end
|
||||||
|
|
||||||
def boolean_cast_setting(key)
|
def boolean_cast_setting(key)
|
||||||
ActiveModel::Type::Boolean.new.cast(settings[key])
|
ActiveModel::Type::Boolean.new.cast(settings[key])
|
||||||
end
|
end
|
||||||
|
|
|
@ -142,7 +142,7 @@ class User < ApplicationRecord
|
||||||
:mobile_customize, :mobile_content_font_size, :mobile_info_font_size, :mobile_content_emoji_reaction_size,
|
:mobile_customize, :mobile_content_font_size, :mobile_info_font_size, :mobile_content_emoji_reaction_size,
|
||||||
:hide_bot_on_public_timeline, :confirm_follow_from_bot,
|
:hide_bot_on_public_timeline, :confirm_follow_from_bot,
|
||||||
:default_search_searchability,
|
:default_search_searchability,
|
||||||
:show_reload_button,
|
:show_reload_button, :default_column_width,
|
||||||
|
|
||||||
to: :settings, prefix: :setting, allow_nil: false
|
to: :settings, prefix: :setting, allow_nil: false
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ class InitialStateSerializer < ActiveModel::Serializer
|
||||||
store[:hide_bot_on_public_timeline] = object.current_account.user.setting_hide_bot_on_public_timeline
|
store[:hide_bot_on_public_timeline] = object.current_account.user.setting_hide_bot_on_public_timeline
|
||||||
store[:confirm_follow_from_bot] = object.current_account.user.setting_confirm_follow_from_bot
|
store[:confirm_follow_from_bot] = object.current_account.user.setting_confirm_follow_from_bot
|
||||||
store[:show_reload_button] = object.current_account.user.setting_show_reload_button
|
store[:show_reload_button] = object.current_account.user.setting_show_reload_button
|
||||||
|
store[:default_column_width] = object.current_account.user.setting_default_column_width
|
||||||
else
|
else
|
||||||
store[:auto_play_gif] = Setting.auto_play_gif
|
store[:auto_play_gif] = Setting.auto_play_gif
|
||||||
store[:display_media] = Setting.display_media
|
store[:display_media] = Setting.display_media
|
||||||
|
|
|
@ -62,6 +62,9 @@
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :setting_enable_empty_column, as: :boolean, wrapper: :with_label, fedibird_features: true
|
= f.input :setting_enable_empty_column, as: :boolean, wrapper: :with_label, fedibird_features: true
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :setting_default_column_width, collection: ['x080', 'x100', 'x125', 'x150', 'free'], label_method: lambda { |item| t("simple_form.hints.defaults.setting_default_column_width_#{item}") }, wrapper: :with_label, include_blank: false, fedibird_features: true
|
||||||
|
|
||||||
%h4= t 'appearance.animations_and_accessibility'
|
%h4= t 'appearance.animations_and_accessibility'
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
|
|
|
@ -57,6 +57,11 @@ en:
|
||||||
setting_aggregate_reblogs: Do not show new boosts for posts that have been recently boosted (only affects newly-received boosts)
|
setting_aggregate_reblogs: Do not show new boosts for posts that have been recently boosted (only affects newly-received boosts)
|
||||||
setting_compact_reaction: Emoji reaction display to be only the number of cases, except for the detail display
|
setting_compact_reaction: Emoji reaction display to be only the number of cases, except for the detail display
|
||||||
setting_confirm_follow_from_bot: Manually approve followers from bot accounts
|
setting_confirm_follow_from_bot: Manually approve followers from bot accounts
|
||||||
|
setting_default_column_width_free: Free - Column width changes according to screen
|
||||||
|
setting_default_column_width_x080: 80% - Fix to 80% of standard width
|
||||||
|
setting_default_column_width_x100: 100% - Fix to Mastodon standard column width
|
||||||
|
setting_default_column_width_x125: 125% - Fix to 125% of standard width
|
||||||
|
setting_default_column_width_x150: 150% - Fix to 150% of standard width
|
||||||
setting_default_search_searchability: For clients that do not support advanced range settings, switch the settings here. Mastodon's standard behavior is "Reacted-users-only". Targeting "Public" makes it easier to discover unknown information, but if the results are noisy, narrowing the search range is effective.
|
setting_default_search_searchability: For clients that do not support advanced range settings, switch the settings here. Mastodon's standard behavior is "Reacted-users-only". Targeting "Public" makes it easier to discover unknown information, but if the results are noisy, narrowing the search range is effective.
|
||||||
setting_default_sensitive: Sensitive media is hidden by default and can be revealed with a click
|
setting_default_sensitive: Sensitive media is hidden by default and can be revealed with a click
|
||||||
setting_disable_joke_appearance: Disable April Fools' Day and other joke functions
|
setting_disable_joke_appearance: Disable April Fools' Day and other joke functions
|
||||||
|
@ -219,6 +224,7 @@ en:
|
||||||
setting_content_emoji_reaction_size: Emoji reaction size
|
setting_content_emoji_reaction_size: Emoji reaction size
|
||||||
setting_content_font_size: Content font size
|
setting_content_font_size: Content font size
|
||||||
setting_crop_images: Crop images in non-expanded posts to 16x9
|
setting_crop_images: Crop images in non-expanded posts to 16x9
|
||||||
|
setting_default_column_width: Default column width
|
||||||
setting_default_language: Posting language
|
setting_default_language: Posting language
|
||||||
setting_default_privacy: Posting privacy
|
setting_default_privacy: Posting privacy
|
||||||
setting_default_search_searchability: Search range
|
setting_default_search_searchability: Search range
|
||||||
|
|
|
@ -57,6 +57,11 @@ ja:
|
||||||
setting_aggregate_reblogs: 最近ブーストされた投稿が新たにブーストされても表示しません (設定後受信したものにのみ影響)
|
setting_aggregate_reblogs: 最近ブーストされた投稿が新たにブーストされても表示しません (設定後受信したものにのみ影響)
|
||||||
setting_compact_reaction: 詳細表示以外の絵文字リアクション表示を件数のみにする
|
setting_compact_reaction: 詳細表示以外の絵文字リアクション表示を件数のみにする
|
||||||
setting_confirm_follow_from_bot: Botアカウントからのフォローを手動で承認する
|
setting_confirm_follow_from_bot: Botアカウントからのフォローを手動で承認する
|
||||||
|
setting_default_column_width_free: フリー - 画面に応じてカラム幅が変わります
|
||||||
|
setting_default_column_width_x080: 80% - 標準の80%の幅に固定します
|
||||||
|
setting_default_column_width_x100: 100% - Mastodon標準のカラム幅に固定します
|
||||||
|
setting_default_column_width_x125: 125% - 標準の125%の幅に固定します
|
||||||
|
setting_default_column_width_x150: 150% - 標準の150%の幅に固定します
|
||||||
setting_default_search_searchability: 範囲の詳細設定に対応していないクライアントでは、ここで設定を切り替えてください。Mastodonの標準動作は『リアクション限定』です。『公開』を対象にすると未知の情報を発見しやすくなりますが、結果にノイズが多い場合は検索範囲を狭めると効果的です。
|
setting_default_search_searchability: 範囲の詳細設定に対応していないクライアントでは、ここで設定を切り替えてください。Mastodonの標準動作は『リアクション限定』です。『公開』を対象にすると未知の情報を発見しやすくなりますが、結果にノイズが多い場合は検索範囲を狭めると効果的です。
|
||||||
setting_default_sensitive: 閲覧注意状態のメディアはデフォルトでは内容が伏せられ、クリックして初めて閲覧できるようになります
|
setting_default_sensitive: 閲覧注意状態のメディアはデフォルトでは内容が伏せられ、クリックして初めて閲覧できるようになります
|
||||||
setting_disable_joke_appearance: エイプリルフール等のジョーク機能を無効にします
|
setting_disable_joke_appearance: エイプリルフール等のジョーク機能を無効にします
|
||||||
|
@ -219,6 +224,7 @@ ja:
|
||||||
setting_content_emoji_reaction_size: 投稿の絵文字リアクションのサイズ
|
setting_content_emoji_reaction_size: 投稿の絵文字リアクションのサイズ
|
||||||
setting_content_font_size: 投稿のフォントサイズ
|
setting_content_font_size: 投稿のフォントサイズ
|
||||||
setting_crop_images: 投稿の詳細以外では画像を16:9に切り抜く
|
setting_crop_images: 投稿の詳細以外では画像を16:9に切り抜く
|
||||||
|
setting_default_column_width: デフォルトのカラム幅
|
||||||
setting_default_language: 投稿する言語
|
setting_default_language: 投稿する言語
|
||||||
setting_default_privacy: 投稿の公開範囲
|
setting_default_privacy: 投稿の公開範囲
|
||||||
setting_default_search_searchability: 検索の対象とする範囲
|
setting_default_search_searchability: 検索の対象とする範囲
|
||||||
|
|
|
@ -110,6 +110,7 @@ defaults: &defaults
|
||||||
confirm_follow_from_bot: true
|
confirm_follow_from_bot: true
|
||||||
default_search_searchability: 'private'
|
default_search_searchability: 'private'
|
||||||
show_reload_button: true
|
show_reload_button: true
|
||||||
|
default_column_width: 'x100'
|
||||||
|
|
||||||
development:
|
development:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
|
Loading…
Reference in a new issue