[Glitch] Add responsive panels to the single-column layout
Port a1bceb2cb6 to glitch-soc
Signed-off-by: Thibaut Girka <thib@sitedethib.com>
			
			
This commit is contained in:
		
							parent
							
								
									9a3e47d27c
								
							
						
					
					
						commit
						04edd3fbdb
					
				
					 19 changed files with 374 additions and 94 deletions
				
			
		| 
						 | 
					@ -68,6 +68,14 @@ const messages = defineMessages({
 | 
				
			||||||
  uploadErrorPoll:  { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
 | 
					  uploadErrorPoll:  { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const COMPOSE_PANEL_BREAKPOINT = 600 + (285 * 1) + (10 * 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const ensureComposeIsVisible = (getState, routerHistory) => {
 | 
				
			||||||
 | 
					  if (!getState().getIn(['compose', 'mounted']) && window.innerWidth < COMPOSE_PANEL_BREAKPOINT) {
 | 
				
			||||||
 | 
					    routerHistory.push('/statuses/new');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function changeCompose(text) {
 | 
					export function changeCompose(text) {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    type: COMPOSE_CHANGE,
 | 
					    type: COMPOSE_CHANGE,
 | 
				
			||||||
| 
						 | 
					@ -81,16 +89,14 @@ export function cycleElefriendCompose() {
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function replyCompose(status, router) {
 | 
					export function replyCompose(status, routerHistory) {
 | 
				
			||||||
  return (dispatch, getState) => {
 | 
					  return (dispatch, getState) => {
 | 
				
			||||||
    dispatch({
 | 
					    dispatch({
 | 
				
			||||||
      type: COMPOSE_REPLY,
 | 
					      type: COMPOSE_REPLY,
 | 
				
			||||||
      status: status,
 | 
					      status: status,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (router && !getState().getIn(['compose', 'mounted'])) {
 | 
					    ensureComposeIsVisible(getState, routerHistory);
 | 
				
			||||||
      router.push('/statuses/new');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,29 +112,25 @@ export function resetCompose() {
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function mentionCompose(account, router) {
 | 
					export function mentionCompose(account, routerHistory) {
 | 
				
			||||||
  return (dispatch, getState) => {
 | 
					  return (dispatch, getState) => {
 | 
				
			||||||
    dispatch({
 | 
					    dispatch({
 | 
				
			||||||
      type: COMPOSE_MENTION,
 | 
					      type: COMPOSE_MENTION,
 | 
				
			||||||
      account: account,
 | 
					      account: account,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!getState().getIn(['compose', 'mounted'])) {
 | 
					    ensureComposeIsVisible(getState, routerHistory);
 | 
				
			||||||
      router.push('/statuses/new');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function directCompose(account, router) {
 | 
					export function directCompose(account, routerHistory) {
 | 
				
			||||||
  return (dispatch, getState) => {
 | 
					  return (dispatch, getState) => {
 | 
				
			||||||
    dispatch({
 | 
					    dispatch({
 | 
				
			||||||
      type: COMPOSE_DIRECT,
 | 
					      type: COMPOSE_DIRECT,
 | 
				
			||||||
      account: account,
 | 
					      account: account,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!getState().getIn(['compose', 'mounted'])) {
 | 
					    ensureComposeIsVisible(getState, routerHistory);
 | 
				
			||||||
      router.push('/statuses/new');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import api from 'flavours/glitch/util/api';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { deleteFromTimelines } from './timelines';
 | 
					import { deleteFromTimelines } from './timelines';
 | 
				
			||||||
import { importFetchedStatus, importFetchedStatuses } from './importer';
 | 
					import { importFetchedStatus, importFetchedStatuses } from './importer';
 | 
				
			||||||
 | 
					import { ensureComposeIsVisible } from './compose';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
 | 
					export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
 | 
				
			||||||
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
 | 
					export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
 | 
				
			||||||
| 
						 | 
					@ -80,7 +81,7 @@ export function redraft(status, raw_text, content_type) {
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function deleteStatus(id, router, withRedraft = false) {
 | 
					export function deleteStatus(id, routerHistory, withRedraft = false) {
 | 
				
			||||||
  return (dispatch, getState) => {
 | 
					  return (dispatch, getState) => {
 | 
				
			||||||
    let status = getState().getIn(['statuses', id]);
 | 
					    let status = getState().getIn(['statuses', id]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,9 +98,7 @@ export function deleteStatus(id, router, withRedraft = false) {
 | 
				
			||||||
      if (withRedraft) {
 | 
					      if (withRedraft) {
 | 
				
			||||||
        dispatch(redraft(status, response.data.text, response.data.content_type));
 | 
					        dispatch(redraft(status, response.data.text, response.data.content_type));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!getState().getIn(['compose', 'mounted'])) {
 | 
					        ensureComposeIsVisible(getState, routerHistory);
 | 
				
			||||||
          router.push('/statuses/new');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }).catch(error => {
 | 
					    }).catch(error => {
 | 
				
			||||||
      dispatch(deleteStatusFail(id, error));
 | 
					      dispatch(deleteStatusFail(id, error));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
 | 
				
			||||||
    autoFocus: PropTypes.bool,
 | 
					    autoFocus: PropTypes.bool,
 | 
				
			||||||
    className: PropTypes.string,
 | 
					    className: PropTypes.string,
 | 
				
			||||||
    id: PropTypes.string,
 | 
					    id: PropTypes.string,
 | 
				
			||||||
    searchTokens: ImmutablePropTypes.list,
 | 
					    searchTokens: PropTypes.arrayOf(PropTypes.string),
 | 
				
			||||||
    maxLength: PropTypes.number,
 | 
					    maxLength: PropTypes.number,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ export default class NavigationBar extends ImmutablePureComponent {
 | 
				
			||||||
      <div className='drawer--account'>
 | 
					      <div className='drawer--account'>
 | 
				
			||||||
        <Permalink className='avatar' href={this.props.account.get('url')} to={`/accounts/${this.props.account.get('id')}`}>
 | 
					        <Permalink className='avatar' href={this.props.account.get('url')} to={`/accounts/${this.props.account.get('id')}`}>
 | 
				
			||||||
          <span style={{ display: 'none' }}>{this.props.account.get('acct')}</span>
 | 
					          <span style={{ display: 'none' }}>{this.props.account.get('acct')}</span>
 | 
				
			||||||
          <Avatar account={this.props.account} size={40} />
 | 
					          <Avatar account={this.props.account} size={48} />
 | 
				
			||||||
        </Permalink>
 | 
					        </Permalink>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <Permalink className='acct' href={this.props.account.get('url')} to={`/accounts/${this.props.account.get('id')}`}>
 | 
					        <Permalink className='acct' href={this.props.account.get('url')} to={`/accounts/${this.props.account.get('id')}`}>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,6 +60,10 @@ class SearchPopout extends React.PureComponent {
 | 
				
			||||||
export default @injectIntl
 | 
					export default @injectIntl
 | 
				
			||||||
class Search extends React.PureComponent {
 | 
					class Search extends React.PureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static contextTypes = {
 | 
				
			||||||
 | 
					    router: PropTypes.object.isRequired,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static propTypes = {
 | 
					  static propTypes = {
 | 
				
			||||||
    value: PropTypes.string.isRequired,
 | 
					    value: PropTypes.string.isRequired,
 | 
				
			||||||
    submitted: PropTypes.bool,
 | 
					    submitted: PropTypes.bool,
 | 
				
			||||||
| 
						 | 
					@ -67,6 +71,7 @@ class Search extends React.PureComponent {
 | 
				
			||||||
    onSubmit: PropTypes.func.isRequired,
 | 
					    onSubmit: PropTypes.func.isRequired,
 | 
				
			||||||
    onClear: PropTypes.func.isRequired,
 | 
					    onClear: PropTypes.func.isRequired,
 | 
				
			||||||
    onShow: PropTypes.func.isRequired,
 | 
					    onShow: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					    openInRoute: PropTypes.bool,
 | 
				
			||||||
    intl: PropTypes.object.isRequired,
 | 
					    intl: PropTypes.object.isRequired,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,8 +114,10 @@ class Search extends React.PureComponent {
 | 
				
			||||||
    const { onSubmit } = this.props;
 | 
					    const { onSubmit } = this.props;
 | 
				
			||||||
    switch (e.key) {
 | 
					    switch (e.key) {
 | 
				
			||||||
    case 'Enter':
 | 
					    case 'Enter':
 | 
				
			||||||
      if (onSubmit) {
 | 
					 | 
				
			||||||
      onSubmit();
 | 
					      onSubmit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (this.props.openInRoute) {
 | 
				
			||||||
 | 
					        this.context.router.history.push('/search');
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    case 'Escape':
 | 
					    case 'Escape':
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,12 +10,10 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
				
			||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
					import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
				
			||||||
import { me, invitesEnabled, version } from 'flavours/glitch/util/initial_state';
 | 
					import { me, invitesEnabled, version } from 'flavours/glitch/util/initial_state';
 | 
				
			||||||
import { fetchFollowRequests } from 'flavours/glitch/actions/accounts';
 | 
					import { fetchFollowRequests } from 'flavours/glitch/actions/accounts';
 | 
				
			||||||
import { changeSetting } from 'flavours/glitch/actions/settings';
 | 
					 | 
				
			||||||
import { List as ImmutableList } from 'immutable';
 | 
					import { List as ImmutableList } from 'immutable';
 | 
				
			||||||
import { createSelector } from 'reselect';
 | 
					import { createSelector } from 'reselect';
 | 
				
			||||||
import { fetchLists } from 'flavours/glitch/actions/lists';
 | 
					import { fetchLists } from 'flavours/glitch/actions/lists';
 | 
				
			||||||
import { preferencesLink, profileLink, signOutLink } from 'flavours/glitch/util/backend_links';
 | 
					import { preferencesLink, profileLink, signOutLink } from 'flavours/glitch/util/backend_links';
 | 
				
			||||||
import Toggle from 'react-toggle';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  heading: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
 | 
					  heading: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
 | 
				
			||||||
| 
						 | 
					@ -54,7 +52,6 @@ const makeMapStateToProps = () => {
 | 
				
			||||||
    columns: state.getIn(['settings', 'columns']),
 | 
					    columns: state.getIn(['settings', 'columns']),
 | 
				
			||||||
    unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
 | 
					    unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
 | 
				
			||||||
    unreadNotifications: state.getIn(['notifications', 'unread']),
 | 
					    unreadNotifications: state.getIn(['notifications', 'unread']),
 | 
				
			||||||
    forceSingleColumn: state.getIn(['settings', 'forceSingleColumn'], false),
 | 
					 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return mapStateToProps;
 | 
					  return mapStateToProps;
 | 
				
			||||||
| 
						 | 
					@ -64,7 +61,6 @@ const mapDispatchToProps = dispatch => ({
 | 
				
			||||||
  fetchFollowRequests: () => dispatch(fetchFollowRequests()),
 | 
					  fetchFollowRequests: () => dispatch(fetchFollowRequests()),
 | 
				
			||||||
  fetchLists: () => dispatch(fetchLists()),
 | 
					  fetchLists: () => dispatch(fetchLists()),
 | 
				
			||||||
  openSettings: () => dispatch(openModal('SETTINGS', {})),
 | 
					  openSettings: () => dispatch(openModal('SETTINGS', {})),
 | 
				
			||||||
  changeForceSingleColumn: checked => dispatch(changeSetting(['forceSingleColumn'], checked)),
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const badgeDisplay = (number, limit) => {
 | 
					const badgeDisplay = (number, limit) => {
 | 
				
			||||||
| 
						 | 
					@ -92,8 +88,6 @@ export default class GettingStarted extends ImmutablePureComponent {
 | 
				
			||||||
    lists: ImmutablePropTypes.list,
 | 
					    lists: ImmutablePropTypes.list,
 | 
				
			||||||
    fetchLists: PropTypes.func.isRequired,
 | 
					    fetchLists: PropTypes.func.isRequired,
 | 
				
			||||||
    openSettings: PropTypes.func.isRequired,
 | 
					    openSettings: PropTypes.func.isRequired,
 | 
				
			||||||
    forceSingleColumn: PropTypes.bool,
 | 
					 | 
				
			||||||
    changeForceSingleColumn: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  componentWillMount () {
 | 
					  componentWillMount () {
 | 
				
			||||||
| 
						 | 
					@ -108,12 +102,8 @@ export default class GettingStarted extends ImmutablePureComponent {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleForceSingleColumnChange = ({ target }) => {
 | 
					 | 
				
			||||||
    this.props.changeForceSingleColumn(target.checked);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { intl, myAccount, columns, multiColumn, unreadFollowRequests, unreadNotifications, lists, openSettings, forceSingleColumn } = this.props;
 | 
					    const { intl, myAccount, columns, multiColumn, unreadFollowRequests, unreadNotifications, lists, openSettings } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const navItems = [];
 | 
					    const navItems = [];
 | 
				
			||||||
    let listItems = [];
 | 
					    let listItems = [];
 | 
				
			||||||
| 
						 | 
					@ -193,11 +183,6 @@ export default class GettingStarted extends ImmutablePureComponent {
 | 
				
			||||||
            </p>
 | 
					            </p>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					 | 
				
			||||||
        <label className='navigational-toggle'>
 | 
					 | 
				
			||||||
          <FormattedMessage id='getting_started.use_simple_layout' defaultMessage='Use simple layout' />
 | 
					 | 
				
			||||||
          <Toggle checked={forceSingleColumn} onChange={this.handleForceSingleColumnChange} />
 | 
					 | 
				
			||||||
        </label>
 | 
					 | 
				
			||||||
      </Column>
 | 
					      </Column>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								app/javascript/flavours/glitch/features/search/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/javascript/flavours/glitch/features/search/index.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import SearchContainer from 'flavours/glitch/features/compose/containers/search_container';
 | 
				
			||||||
 | 
					import SearchResultsContainer from 'flavours/glitch/features/compose/containers/search_results_container';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Search = () => (
 | 
				
			||||||
 | 
					  <div className='column search-page'>
 | 
				
			||||||
 | 
					    <SearchContainer />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div className='drawer__pager'>
 | 
				
			||||||
 | 
					      <div className='drawer__inner darker'>
 | 
				
			||||||
 | 
					        <SearchResultsContainer />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Search;
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,8 @@ import ColumnLoading from './column_loading';
 | 
				
			||||||
import DrawerLoading from './drawer_loading';
 | 
					import DrawerLoading from './drawer_loading';
 | 
				
			||||||
import BundleColumnError from './bundle_column_error';
 | 
					import BundleColumnError from './bundle_column_error';
 | 
				
			||||||
import { Compose, Notifications, HomeTimeline, CommunityTimeline, PublicTimeline, HashtagTimeline, DirectTimeline, FavouritedStatuses, BookmarkedStatuses, ListTimeline } from 'flavours/glitch/util/async-components';
 | 
					import { Compose, Notifications, HomeTimeline, CommunityTimeline, PublicTimeline, HashtagTimeline, DirectTimeline, FavouritedStatuses, BookmarkedStatuses, ListTimeline } from 'flavours/glitch/util/async-components';
 | 
				
			||||||
 | 
					import ComposePanel from './compose_panel';
 | 
				
			||||||
 | 
					import NavigationPanel from './navigation_panel';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import detectPassiveEvents from 'detect-passive-events';
 | 
					import detectPassiveEvents from 'detect-passive-events';
 | 
				
			||||||
import { scrollRight } from 'flavours/glitch/util/scroll';
 | 
					import { scrollRight } from 'flavours/glitch/util/scroll';
 | 
				
			||||||
| 
						 | 
					@ -173,14 +175,22 @@ export default class ColumnsArea extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return (
 | 
					      return (
 | 
				
			||||||
        <div className='columns-area__panels'>
 | 
					        <div className='columns-area__panels'>
 | 
				
			||||||
          <div className='columns-area__panels__pane' />
 | 
					          <div className='columns-area__panels__pane columns-area__panels__pane--compositional'>
 | 
				
			||||||
 | 
					            <div className='columns-area__panels__pane__inner'>
 | 
				
			||||||
 | 
					              <ComposePanel />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <div className='columns-area__panels__main'>
 | 
					          <div className='columns-area__panels__main'>
 | 
				
			||||||
            <TabsBar key='tabs' />
 | 
					            <TabsBar key='tabs' />
 | 
				
			||||||
            {content}
 | 
					            {content}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <div className='columns-area__panels__pane' />
 | 
					          <div className='columns-area__panels__pane columns-area__panels__pane--start columns-area__panels__pane--navigational'>
 | 
				
			||||||
 | 
					            <div className='columns-area__panels__pane__inner'>
 | 
				
			||||||
 | 
					              <NavigationPanel />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          {floatingActionButton}
 | 
					          {floatingActionButton}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import SearchContainer from 'flavours/glitch/features/compose/containers/search_container';
 | 
				
			||||||
 | 
					import ComposeFormContainer from 'flavours/glitch/features/compose/containers/compose_form_container';
 | 
				
			||||||
 | 
					import NavigationContainer from 'flavours/glitch/features/compose/containers/navigation_container';
 | 
				
			||||||
 | 
					import { invitesEnabled, version, repository, source_url } from 'mastodon/initial_state';
 | 
				
			||||||
 | 
					import { Link } from 'react-router-dom';
 | 
				
			||||||
 | 
					import { FormattedMessage } from 'react-intl';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ComposePanel = () => (
 | 
				
			||||||
 | 
					  <div className='compose-panel'>
 | 
				
			||||||
 | 
					    <SearchContainer openInRoute />
 | 
				
			||||||
 | 
					    <NavigationContainer />
 | 
				
			||||||
 | 
					    <ComposeFormContainer />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div className='flex-spacer' />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div className='getting-started__footer'>
 | 
				
			||||||
 | 
					      <ul>
 | 
				
			||||||
 | 
					        {invitesEnabled && <li><a href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
 | 
				
			||||||
 | 
					        <li><Link to='/keyboard-shortcuts'><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></Link> · </li>
 | 
				
			||||||
 | 
					        <li><a href='/auth/edit'><FormattedMessage id='getting_started.security' defaultMessage='Security' /></a> · </li>
 | 
				
			||||||
 | 
					        <li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></a> · </li>
 | 
				
			||||||
 | 
					        <li><a href='https://joinmastodon.org/apps' target='_blank'><FormattedMessage id='navigation_bar.apps' defaultMessage='Mobile apps' /></a> · </li>
 | 
				
			||||||
 | 
					        <li><a href='/terms' target='_blank'><FormattedMessage id='getting_started.terms' defaultMessage='Terms of service' /></a> · </li>
 | 
				
			||||||
 | 
					        <li><a href='/settings/applications' target='_blank'><FormattedMessage id='getting_started.developers' defaultMessage='Developers' /></a> · </li>
 | 
				
			||||||
 | 
					        <li><a href='https://docs.joinmastodon.org' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a> · </li>
 | 
				
			||||||
 | 
					        <li><a href='/auth/sign_out' data-method='delete'><FormattedMessage id='navigation_bar.logout' defaultMessage='Logout' /></a></li>
 | 
				
			||||||
 | 
					      </ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <p>
 | 
				
			||||||
 | 
					        <FormattedMessage
 | 
				
			||||||
 | 
					          id='getting_started.open_source_notice'
 | 
				
			||||||
 | 
					          defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}.'
 | 
				
			||||||
 | 
					          values={{ github: <span><a href={source_url} rel='noopener' target='_blank'>{repository}</a> (v{version})</span> }}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ComposePanel;
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,55 @@
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
 | 
					import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
				
			||||||
 | 
					import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
				
			||||||
 | 
					import { fetchLists } from 'flavours/glitch/actions/lists';
 | 
				
			||||||
 | 
					import { connect } from 'react-redux';
 | 
				
			||||||
 | 
					import { createSelector } from 'reselect';
 | 
				
			||||||
 | 
					import { NavLink, withRouter } from 'react-router-dom';
 | 
				
			||||||
 | 
					import Icon from 'flavours/glitch/components/icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getOrderedLists = createSelector([state => state.get('lists')], lists => {
 | 
				
			||||||
 | 
					  if (!lists) {
 | 
				
			||||||
 | 
					    return lists;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return lists.toList().filter(item => !!item).sort((a, b) => a.get('title').localeCompare(b.get('title')));
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mapStateToProps = state => ({
 | 
				
			||||||
 | 
					  lists: getOrderedLists(state),
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default @withRouter
 | 
				
			||||||
 | 
					@connect(mapStateToProps)
 | 
				
			||||||
 | 
					class ListPanel extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static propTypes = {
 | 
				
			||||||
 | 
					    dispatch: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					    lists: ImmutablePropTypes.list,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  componentDidMount () {
 | 
				
			||||||
 | 
					    const { dispatch } = this.props;
 | 
				
			||||||
 | 
					    dispatch(fetchLists());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  render () {
 | 
				
			||||||
 | 
					    const { lists } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!lists) {
 | 
				
			||||||
 | 
					      return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					        <hr />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {lists.map(list => (
 | 
				
			||||||
 | 
					          <NavLink key={list.get('id')} className='column-link column-link--transparent' strict to={`/timelines/list/${list.get('id')}`}><Icon className='column-link__icon' icon='list-ul' fixedWidth />{list.get('title')}</NavLink>
 | 
				
			||||||
 | 
					        ))}
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import { NavLink, withRouter } from 'react-router-dom';
 | 
				
			||||||
 | 
					import { FormattedMessage } from 'react-intl';
 | 
				
			||||||
 | 
					import Icon from 'flavours/glitch/components/icon';
 | 
				
			||||||
 | 
					import NotificationsCounterIcon from './notifications_counter_icon';
 | 
				
			||||||
 | 
					import ListPanel from './list_panel';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const NavigationPanel = () => (
 | 
				
			||||||
 | 
					  <div className='navigation-panel'>
 | 
				
			||||||
 | 
					    <NavLink className='column-link column-link--transparent' to='/timelines/home' data-preview-title-id='column.home' data-preview-icon='home' ><Icon className='column-link__icon' icon='home' fixedWidth /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>
 | 
				
			||||||
 | 
					    <NavLink className='column-link column-link--transparent' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><NotificationsCounterIcon className='column-link__icon' /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>
 | 
				
			||||||
 | 
					    <NavLink className='column-link column-link--transparent' to='/timelines/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><Icon className='column-link__icon' icon='users' fixedWidth /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>
 | 
				
			||||||
 | 
					    <NavLink className='column-link column-link--transparent' exact to='/timelines/public' data-preview-title-id='column.public' data-preview-icon='globe' ><Icon className='column-link__icon' icon='globe' fixedWidth /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>
 | 
				
			||||||
 | 
					    <NavLink className='column-link column-link--transparent' to='/timelines/direct'><Icon className='column-link__icon' icon='envelope' fixedWidth /><FormattedMessage id='navigation_bar.direct' defaultMessage='Direct messages' /></NavLink>
 | 
				
			||||||
 | 
					    <NavLink className='column-link column-link--transparent' to='/favourites'><Icon className='column-link__icon' icon='star' fixedWidth /><FormattedMessage id='navigation_bar.favourites' defaultMessage='Favourites' /></NavLink>
 | 
				
			||||||
 | 
					    <NavLink className='column-link column-link--transparent' to='/lists'><Icon className='column-link__icon' icon='list-ul' fixedWidth /><FormattedMessage id='navigation_bar.lists' defaultMessage='Lists' /></NavLink>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <ListPanel />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <hr />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <a className='column-link column-link--transparent' href='/settings/preferences' target='_blank'><Icon className='column-link__icon' icon='cog' fixedWidth /><FormattedMessage id='navigation_bar.preferences' defaultMessage='Preferences' /></a>
 | 
				
			||||||
 | 
					    <a className='column-link column-link--transparent' href='/relationships' target='_blank'><Icon className='column-link__icon' icon='address-book-o' fixedWidth /><FormattedMessage id='navigation_bar.follows_and_followers' defaultMessage='Follows and followers' /></a>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default withRouter(NavigationPanel);
 | 
				
			||||||
| 
						 | 
					@ -10,15 +10,17 @@ const mapStateToProps = state => ({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const formatNumber = num => num > 99 ? '99+' : num;
 | 
					const formatNumber = num => num > 99 ? '99+' : num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const NotificationsCounterIcon = ({ count, showBadge }) => (
 | 
					const NotificationsCounterIcon = ({ count, className, showBadge }) => (
 | 
				
			||||||
  <i className='icon-with-badge'>
 | 
					  <i className='icon-with-badge'>
 | 
				
			||||||
    <Icon icon='bell' fixedWidth />
 | 
					    <Icon icon='bell' fixedWidth className={className} />
 | 
				
			||||||
    {showBadge && count > 0 && <i className='icon-with-badge__badge'>{formatNumber(count)}</i>}
 | 
					    {showBadge && count > 0 && <i className='icon-with-badge__badge'>{formatNumber(count)}</i>}
 | 
				
			||||||
  </i>
 | 
					  </i>
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NotificationsCounterIcon.propTypes = {
 | 
					NotificationsCounterIcon.propTypes = {
 | 
				
			||||||
  count: PropTypes.number.isRequired,
 | 
					  count: PropTypes.number.isRequired,
 | 
				
			||||||
 | 
					  showBadge: PropTypes.bool,
 | 
				
			||||||
 | 
					  className: PropTypes.string,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default connect(mapStateToProps)(NotificationsCounterIcon);
 | 
					export default connect(mapStateToProps)(NotificationsCounterIcon);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,14 +7,13 @@ import { isUserTouching } from 'flavours/glitch/util/is_mobile';
 | 
				
			||||||
import NotificationsCounterIcon from './notifications_counter_icon';
 | 
					import NotificationsCounterIcon from './notifications_counter_icon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const links = [
 | 
					export const links = [
 | 
				
			||||||
  <NavLink className='tabs-bar__link primary' to='/timelines/home' data-preview-title-id='column.home' data-preview-icon='home' ><i className='fa fa-fw fa-home' /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>,
 | 
					  <NavLink className='tabs-bar__link' to='/timelines/home' data-preview-title-id='column.home' data-preview-icon='home' ><i className='fa fa-fw fa-home' /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>,
 | 
				
			||||||
  <NavLink className='tabs-bar__link primary' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><NotificationsCounterIcon /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>,
 | 
					  <NavLink className='tabs-bar__link' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><NotificationsCounterIcon /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <NavLink className='tabs-bar__link secondary' to='/timelines/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><i className='fa fa-fw fa-users' /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>,
 | 
					  <NavLink className='tabs-bar__link' to='/timelines/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><i className='fa fa-fw fa-users' /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>,
 | 
				
			||||||
  <NavLink className='tabs-bar__link secondary' exact to='/timelines/public' data-preview-title-id='column.public' data-preview-icon='globe' ><i className='fa fa-fw fa-globe' /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>,
 | 
					  <NavLink className='tabs-bar__link' exact to='/timelines/public' data-preview-title-id='column.public' data-preview-icon='globe' ><i className='fa fa-fw fa-globe' /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>,
 | 
				
			||||||
  <NavLink className='tabs-bar__link primary' to='/search' data-preview-title-id='tabs_bar.search' data-preview-icon='bell' ><i className='fa fa-fw fa-search' /><FormattedMessage id='tabs_bar.search' defaultMessage='Search' /></NavLink>,
 | 
					  <NavLink className='tabs-bar__link optional' to='/search' data-preview-title-id='tabs_bar.search' data-preview-icon='bell' ><i className='fa fa-fw fa-search' /><FormattedMessage id='tabs_bar.search' defaultMessage='Search' /></NavLink>,
 | 
				
			||||||
 | 
					  <NavLink className='tabs-bar__link' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started' data-preview-title-id='getting_started.heading' data-preview-icon='bars' ><i className='fa fa-fw fa-bars' /></NavLink>,
 | 
				
			||||||
  <NavLink className='tabs-bar__link primary' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started' data-preview-title-id='getting_started.heading' data-preview-icon='bars' ><i className='fa fa-fw fa-bars' /></NavLink>,
 | 
					 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getIndex (path) {
 | 
					export function getIndex (path) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,10 +44,11 @@ import {
 | 
				
			||||||
  Mutes,
 | 
					  Mutes,
 | 
				
			||||||
  PinnedStatuses,
 | 
					  PinnedStatuses,
 | 
				
			||||||
  Lists,
 | 
					  Lists,
 | 
				
			||||||
 | 
					  Search,
 | 
				
			||||||
  GettingStartedMisc,
 | 
					  GettingStartedMisc,
 | 
				
			||||||
} from 'flavours/glitch/util/async-components';
 | 
					} from 'flavours/glitch/util/async-components';
 | 
				
			||||||
import { HotKeys } from 'react-hotkeys';
 | 
					import { HotKeys } from 'react-hotkeys';
 | 
				
			||||||
import { me } from 'flavours/glitch/util/initial_state';
 | 
					import { me, forceSingleColumn } from 'flavours/glitch/util/initial_state';
 | 
				
			||||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
					import { defineMessages, injectIntl } from 'react-intl';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
 | 
					// Dummy import, to make sure that <Status /> ends up in the application bundle.
 | 
				
			||||||
| 
						 | 
					@ -68,7 +69,6 @@ const mapStateToProps = state => ({
 | 
				
			||||||
  unreadNotifications: state.getIn(['notifications', 'unread']),
 | 
					  unreadNotifications: state.getIn(['notifications', 'unread']),
 | 
				
			||||||
  showFaviconBadge: state.getIn(['local_settings', 'notifications', 'favicon_badge']),
 | 
					  showFaviconBadge: state.getIn(['local_settings', 'notifications', 'favicon_badge']),
 | 
				
			||||||
  hicolorPrivacyIcons: state.getIn(['local_settings', 'hicolor_privacy_icons']),
 | 
					  hicolorPrivacyIcons: state.getIn(['local_settings', 'hicolor_privacy_icons']),
 | 
				
			||||||
  forceSingleColumn: state.getIn(['settings', 'forceSingleColumn'], false),
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const keyMap = {
 | 
					const keyMap = {
 | 
				
			||||||
| 
						 | 
					@ -126,7 +126,6 @@ export default class UI extends React.Component {
 | 
				
			||||||
    dropdownMenuIsOpen: PropTypes.bool,
 | 
					    dropdownMenuIsOpen: PropTypes.bool,
 | 
				
			||||||
    unreadNotifications: PropTypes.number,
 | 
					    unreadNotifications: PropTypes.number,
 | 
				
			||||||
    showFaviconBadge: PropTypes.bool,
 | 
					    showFaviconBadge: PropTypes.bool,
 | 
				
			||||||
    forceSingleColumn: PropTypes.bool,
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  state = {
 | 
					  state = {
 | 
				
			||||||
| 
						 | 
					@ -432,7 +431,7 @@ export default class UI extends React.Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { width, draggingOver } = this.state;
 | 
					    const { width, draggingOver } = this.state;
 | 
				
			||||||
    const { children, layout, isWide, navbarUnder, dropdownMenuIsOpen, forceSingleColumn } = this.props;
 | 
					    const { children, layout, isWide, navbarUnder, dropdownMenuIsOpen } = this.props;
 | 
				
			||||||
    const singleColumn = forceSingleColumn || isMobile(width, layout);
 | 
					    const singleColumn = forceSingleColumn || isMobile(width, layout);
 | 
				
			||||||
    const redirect = singleColumn ? <Redirect from='/' to='/timelines/home' exact /> : <Redirect from='/' to='/getting-started' exact />;
 | 
					    const redirect = singleColumn ? <Redirect from='/' to='/timelines/home' exact /> : <Redirect from='/' to='/getting-started' exact />;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -494,7 +493,7 @@ export default class UI extends React.Component {
 | 
				
			||||||
              <WrappedRoute path='/bookmarks' component={BookmarkedStatuses} content={children} />
 | 
					              <WrappedRoute path='/bookmarks' component={BookmarkedStatuses} content={children} />
 | 
				
			||||||
              <WrappedRoute path='/pinned' component={PinnedStatuses} content={children} />
 | 
					              <WrappedRoute path='/pinned' component={PinnedStatuses} content={children} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <WrappedRoute path='/search' component={Compose} content={children} componentParams={{ isSearchPage: true }} />
 | 
					              <WrappedRoute path='/search' component={Search} content={children} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <WrappedRoute path='/statuses/new' component={Compose} content={children} />
 | 
					              <WrappedRoute path='/statuses/new' component={Compose} content={children} />
 | 
				
			||||||
              <WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />
 | 
					              <WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,8 +15,6 @@ const initialState = ImmutableMap({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  skinTone: 1,
 | 
					  skinTone: 1,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  forceSingleColumn: false,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  home: ImmutableMap({
 | 
					  home: ImmutableMap({
 | 
				
			||||||
    shows: ImmutableMap({
 | 
					    shows: ImmutableMap({
 | 
				
			||||||
      reblog: true,
 | 
					      reblog: true,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,12 @@
 | 
				
			||||||
      display: flex;
 | 
					      display: flex;
 | 
				
			||||||
      justify-content: flex-end;
 | 
					      justify-content: flex-end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      &--start {
 | 
				
			||||||
 | 
					        justify-content: flex-start;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      &__inner {
 | 
					      &__inner {
 | 
				
			||||||
 | 
					        width: 285px;
 | 
				
			||||||
        pointer-events: auto;
 | 
					        pointer-events: auto;
 | 
				
			||||||
        height: 100%;
 | 
					        height: 100%;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -178,9 +183,31 @@
 | 
				
			||||||
  padding: 15px;
 | 
					  padding: 15px;
 | 
				
			||||||
  text-decoration: none;
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &:hover {
 | 
					  &:hover,
 | 
				
			||||||
 | 
					  &:focus,
 | 
				
			||||||
 | 
					  &:active {
 | 
				
			||||||
    background: lighten($ui-base-color, 11%);
 | 
					    background: lighten($ui-base-color, 11%);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &:focus {
 | 
				
			||||||
 | 
					    outline: 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &--transparent {
 | 
				
			||||||
 | 
					    background: transparent;
 | 
				
			||||||
 | 
					    color: $ui-secondary-color;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &:hover,
 | 
				
			||||||
 | 
					    &:focus,
 | 
				
			||||||
 | 
					    &:active {
 | 
				
			||||||
 | 
					      background: transparent;
 | 
				
			||||||
 | 
					      color: $primary-text-color;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &.active {
 | 
				
			||||||
 | 
					      color: $ui-highlight-color;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.column-link__icon {
 | 
					.column-link__icon {
 | 
				
			||||||
| 
						 | 
					@ -506,31 +533,3 @@
 | 
				
			||||||
    margin: 0 5px;
 | 
					    margin: 0 5px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
.floating-action-button {
 | 
					 | 
				
			||||||
  position: fixed;
 | 
					 | 
				
			||||||
  display: flex;
 | 
					 | 
				
			||||||
  justify-content: center;
 | 
					 | 
				
			||||||
  align-items: center;
 | 
					 | 
				
			||||||
  width: 3.9375rem;
 | 
					 | 
				
			||||||
  height: 3.9375rem;
 | 
					 | 
				
			||||||
  bottom: 1.3125rem;
 | 
					 | 
				
			||||||
  right: 1.3125rem;
 | 
					 | 
				
			||||||
  background: darken($ui-highlight-color, 3%);
 | 
					 | 
				
			||||||
  color: $white;
 | 
					 | 
				
			||||||
  border-radius: 50%;
 | 
					 | 
				
			||||||
  font-size: 21px;
 | 
					 | 
				
			||||||
  line-height: 21px;
 | 
					 | 
				
			||||||
  text-decoration: none;
 | 
					 | 
				
			||||||
  box-shadow: 2px 3px 9px rgba($base-shadow-color, 0.4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  &:hover,
 | 
					 | 
				
			||||||
  &:focus,
 | 
					 | 
				
			||||||
  &:active {
 | 
					 | 
				
			||||||
    background: lighten($ui-highlight-color, 7%);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @media screen and (min-width: 630px) {
 | 
					 | 
				
			||||||
    display: none;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -564,6 +564,7 @@
 | 
				
			||||||
  display: block;
 | 
					  display: block;
 | 
				
			||||||
  flex: 1 1 auto;
 | 
					  flex: 1 1 auto;
 | 
				
			||||||
  padding: 15px 10px;
 | 
					  padding: 15px 10px;
 | 
				
			||||||
 | 
					  padding-bottom: 13px;
 | 
				
			||||||
  color: $primary-text-color;
 | 
					  color: $primary-text-color;
 | 
				
			||||||
  text-decoration: none;
 | 
					  text-decoration: none;
 | 
				
			||||||
  text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
| 
						 | 
					@ -588,6 +589,7 @@
 | 
				
			||||||
  &:active {
 | 
					  &:active {
 | 
				
			||||||
    @include multi-columns('screen and (min-width: 631px)') {
 | 
					    @include multi-columns('screen and (min-width: 631px)') {
 | 
				
			||||||
      background: lighten($ui-base-color, 14%);
 | 
					      background: lighten($ui-base-color, 14%);
 | 
				
			||||||
 | 
					      border-bottom-color: lighten($ui-base-color, 14%);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -617,11 +619,21 @@
 | 
				
			||||||
    padding: 0;
 | 
					    padding: 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .search__input,
 | 
					 | 
				
			||||||
  .autosuggest-textarea__textarea {
 | 
					  .autosuggest-textarea__textarea {
 | 
				
			||||||
    font-size: 16px;
 | 
					    font-size: 16px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .search__input {
 | 
				
			||||||
 | 
					    line-height: 18px;
 | 
				
			||||||
 | 
					    font-size: 16px;
 | 
				
			||||||
 | 
					    padding: 15px;
 | 
				
			||||||
 | 
					    padding-right: 30px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .search__icon .fa {
 | 
				
			||||||
 | 
					    top: 15px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @media screen and (min-width: 360px) {
 | 
					  @media screen and (min-width: 360px) {
 | 
				
			||||||
    padding: 10px 0;
 | 
					    padding: 10px 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -677,6 +689,58 @@
 | 
				
			||||||
        margin-top: 10px;
 | 
					        margin-top: 10px;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .account {
 | 
				
			||||||
 | 
					      padding: 15px 10px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .notification {
 | 
				
			||||||
 | 
					      &__message {
 | 
				
			||||||
 | 
					        margin-left: 48px + 15px * 2;
 | 
				
			||||||
 | 
					        padding-top: 15px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      &__favourite-icon-wrapper {
 | 
				
			||||||
 | 
					        left: -32px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .status {
 | 
				
			||||||
 | 
					        padding-top: 8px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .account {
 | 
				
			||||||
 | 
					        padding-top: 8px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      .account__avatar-wrapper {
 | 
				
			||||||
 | 
					        margin-left: 17px;
 | 
				
			||||||
 | 
					        margin-right: 15px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.floating-action-button {
 | 
				
			||||||
 | 
					  position: fixed;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  width: 3.9375rem;
 | 
				
			||||||
 | 
					  height: 3.9375rem;
 | 
				
			||||||
 | 
					  bottom: 1.3125rem;
 | 
				
			||||||
 | 
					  right: 1.3125rem;
 | 
				
			||||||
 | 
					  background: darken($ui-highlight-color, 3%);
 | 
				
			||||||
 | 
					  color: $white;
 | 
				
			||||||
 | 
					  border-radius: 50%;
 | 
				
			||||||
 | 
					  font-size: 21px;
 | 
				
			||||||
 | 
					  line-height: 21px;
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					  box-shadow: 2px 3px 9px rgba($base-shadow-color, 0.4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &:hover,
 | 
				
			||||||
 | 
					  &:focus,
 | 
				
			||||||
 | 
					  &:active {
 | 
				
			||||||
 | 
					    background: lighten($ui-highlight-color, 7%);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -698,12 +762,41 @@
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media screen and (max-width: 600px + (285px * 1) + (10px * 1)) {
 | 
				
			||||||
 | 
					  .columns-area__panels__pane--compositional {
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media screen and (min-width: 600px + (285px * 1) + (10px * 1)) {
 | 
				
			||||||
 | 
					  .floating-action-button,
 | 
				
			||||||
 | 
					  .tabs-bar__link.optional {
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .search-page .search {
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media screen and (max-width: 600px + (285px * 2) + (10px * 2)) {
 | 
				
			||||||
 | 
					  .columns-area__panels__pane--navigational {
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media screen and (min-width: 600px + (285px * 2) + (10px * 2)) {
 | 
				
			||||||
 | 
					  .tabs-bar {
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.icon-with-badge {
 | 
					.icon-with-badge {
 | 
				
			||||||
  position: relative;
 | 
					  position: relative;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &__badge {
 | 
					  &__badge {
 | 
				
			||||||
    position: absolute;
 | 
					    position: absolute;
 | 
				
			||||||
    right: -13px;
 | 
					    left: 9px;
 | 
				
			||||||
    top: -13px;
 | 
					    top: -13px;
 | 
				
			||||||
    background: $ui-highlight-color;
 | 
					    background: $ui-highlight-color;
 | 
				
			||||||
    border: 2px solid lighten($ui-base-color, 8%);
 | 
					    border: 2px solid lighten($ui-base-color, 8%);
 | 
				
			||||||
| 
						 | 
					@ -716,6 +809,57 @@
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.column-link--transparent .icon-with-badge__badge {
 | 
				
			||||||
 | 
					  border-color: darken($ui-base-color, 8%);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.compose-panel {
 | 
				
			||||||
 | 
					  width: 285px;
 | 
				
			||||||
 | 
					  margin-top: 10px;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .search__input {
 | 
				
			||||||
 | 
					    line-height: 18px;
 | 
				
			||||||
 | 
					    font-size: 16px;
 | 
				
			||||||
 | 
					    padding: 15px;
 | 
				
			||||||
 | 
					    padding-right: 30px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .search__icon .fa {
 | 
				
			||||||
 | 
					    top: 15px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .navigation-bar {
 | 
				
			||||||
 | 
					    padding-top: 20px;
 | 
				
			||||||
 | 
					    padding-bottom: 20px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .flex-spacer {
 | 
				
			||||||
 | 
					    background: transparent;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .autosuggest-textarea__textarea {
 | 
				
			||||||
 | 
					    max-height: 200px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .compose-form__upload-thumbnail {
 | 
				
			||||||
 | 
					    height: 80px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.navigation-panel {
 | 
				
			||||||
 | 
					  margin-top: 10px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  hr {
 | 
				
			||||||
 | 
					    border: 0;
 | 
				
			||||||
 | 
					    background: transparent;
 | 
				
			||||||
 | 
					    border-top: 1px solid lighten($ui-base-color, 4%);
 | 
				
			||||||
 | 
					    margin: 10px 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.scrollable {
 | 
					.scrollable {
 | 
				
			||||||
  overflow-y: scroll;
 | 
					  overflow-y: scroll;
 | 
				
			||||||
  overflow-x: hidden;
 | 
					  overflow-x: hidden;
 | 
				
			||||||
| 
						 | 
					@ -1386,15 +1530,6 @@
 | 
				
			||||||
  height: 1em;
 | 
					  height: 1em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.navigational-toggle {
 | 
					 | 
				
			||||||
  padding: 10px;
 | 
					 | 
				
			||||||
  display: flex;
 | 
					 | 
				
			||||||
  align-items: center;
 | 
					 | 
				
			||||||
  justify-content: space-between;
 | 
					 | 
				
			||||||
  font-size: 14px;
 | 
					 | 
				
			||||||
  color: $dark-text-color;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.layout-toggle {
 | 
					.layout-toggle {
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  padding: 5px;
 | 
					  padding: 5px;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,3 +149,7 @@ export function GettingStartedMisc () {
 | 
				
			||||||
export function ListAdder () {
 | 
					export function ListAdder () {
 | 
				
			||||||
  return import(/* webpackChunkName: "features/glitch/async/list_adder" */'flavours/glitch/features/list_adder');
 | 
					  return import(/* webpackChunkName: "features/glitch/async/list_adder" */'flavours/glitch/features/list_adder');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function Search () {
 | 
				
			||||||
 | 
					  return import(/*webpackChunkName: "features/glitch/async/search" */'flavours/glitch/features/search');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,5 +28,6 @@ export const version = getMeta('version');
 | 
				
			||||||
export const mascot = getMeta('mascot');
 | 
					export const mascot = getMeta('mascot');
 | 
				
			||||||
export const isStaff = getMeta('is_staff');
 | 
					export const isStaff = getMeta('is_staff');
 | 
				
			||||||
export const defaultContentType = getMeta('default_content_type');
 | 
					export const defaultContentType = getMeta('default_content_type');
 | 
				
			||||||
 | 
					export const forceSingleColumn = !getMeta('advanced_layout');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default initialState;
 | 
					export default initialState;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue