diff options
Diffstat (limited to 'app/javascript/flavours/glitch/features/drawer')
6 files changed, 0 insertions, 756 deletions
diff --git a/app/javascript/flavours/glitch/features/drawer/account/index.js b/app/javascript/flavours/glitch/features/drawer/account/index.js deleted file mode 100644 index 552848641..000000000 --- a/app/javascript/flavours/glitch/features/drawer/account/index.js +++ /dev/null @@ -1,76 +0,0 @@ -// Package imports. -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { - FormattedMessage, - defineMessages, -} from 'react-intl'; - -// Components. -import Avatar from 'flavours/glitch/components/avatar'; -import Permalink from 'flavours/glitch/components/permalink'; - -// Utils. -import { hiddenComponent } from 'flavours/glitch/util/react_helpers'; -import { profileLink } from 'flavours/glitch/util/backend_links'; - -// Messages. -const messages = defineMessages({ - edit: { - defaultMessage: 'Edit profile', - id: 'navigation_bar.edit_profile', - }, -}); - -// The component. -export default function DrawerAccount ({ account }) { - - // We need an account to render. - if (!account) { - return ( - <div className='drawer--account'> - { profileLink !== undefined && ( - <a - className='edit' - href={ profileLink } - > - <FormattedMessage {...messages.edit} /> - </a> - )} - </div> - ); - } - - // The result. - return ( - <div className='drawer--account'> - <Permalink - className='avatar' - href={account.get('url')} - to={`/accounts/${account.get('id')}`} - > - <span {...hiddenComponent}>{account.get('acct')}</span> - <Avatar - account={account} - size={40} - /> - </Permalink> - <Permalink - className='acct' - href={account.get('url')} - to={`/accounts/${account.get('id')}`} - > - <strong>@{account.get('acct')}</strong> - </Permalink> - { profileLink !== undefined && ( - <a - className='edit' - href={ profileLink } - ><FormattedMessage {...messages.edit} /></a> - )} - </div> - ); -} - -// Props. -DrawerAccount.propTypes = { account: ImmutablePropTypes.map }; diff --git a/app/javascript/flavours/glitch/features/drawer/header/index.js b/app/javascript/flavours/glitch/features/drawer/header/index.js deleted file mode 100644 index da5599732..000000000 --- a/app/javascript/flavours/glitch/features/drawer/header/index.js +++ /dev/null @@ -1,127 +0,0 @@ -// Package imports. -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { defineMessages } from 'react-intl'; -import { Link } from 'react-router-dom'; - -// Components. -import Icon from 'flavours/glitch/components/icon'; - -// Utils. -import { conditionalRender } from 'flavours/glitch/util/react_helpers'; -import { signOutLink } from 'flavours/glitch/util/backend_links'; - -// Messages. -const messages = defineMessages({ - community: { - defaultMessage: 'Local timeline', - id: 'navigation_bar.community_timeline', - }, - home_timeline: { - defaultMessage: 'Home', - id: 'tabs_bar.home', - }, - logout: { - defaultMessage: 'Logout', - id: 'navigation_bar.logout', - }, - notifications: { - defaultMessage: 'Notifications', - id: 'tabs_bar.notifications', - }, - public: { - defaultMessage: 'Federated timeline', - id: 'navigation_bar.public_timeline', - }, - settings: { - defaultMessage: 'App settings', - id: 'navigation_bar.app_settings', - }, - start: { - defaultMessage: 'Getting started', - id: 'getting_started.heading', - }, -}); - -// The component. -export default function DrawerHeader ({ - columns, - unreadNotifications, - showNotificationsBadge, - intl, - onSettingsClick, -}) { - - // Only renders the component if the column isn't being shown. - const renderForColumn = conditionalRender.bind(null, - columnId => !columns || !columns.some( - column => column.get('id') === columnId - ) - ); - - // The result. - return ( - <nav className='drawer--header'> - <Link - aria-label={intl.formatMessage(messages.start)} - title={intl.formatMessage(messages.start)} - to='/getting-started' - ><Icon icon='asterisk' /></Link> - {renderForColumn('HOME', ( - <Link - aria-label={intl.formatMessage(messages.home_timeline)} - title={intl.formatMessage(messages.home_timeline)} - to='/timelines/home' - ><Icon icon='home' /></Link> - ))} - {renderForColumn('NOTIFICATIONS', ( - <Link - aria-label={intl.formatMessage(messages.notifications)} - title={intl.formatMessage(messages.notifications)} - to='/notifications' - > - <span className='icon-badge-wrapper'> - <Icon icon='bell' /> - { showNotificationsBadge && unreadNotifications > 0 && <div className='icon-badge' />} - </span> - </Link> - ))} - {renderForColumn('COMMUNITY', ( - <Link - aria-label={intl.formatMessage(messages.community)} - title={intl.formatMessage(messages.community)} - to='/timelines/public/local' - ><Icon icon='users' /></Link> - ))} - {renderForColumn('PUBLIC', ( - <Link - aria-label={intl.formatMessage(messages.public)} - title={intl.formatMessage(messages.public)} - to='/timelines/public' - ><Icon icon='globe' /></Link> - ))} - <a - aria-label={intl.formatMessage(messages.settings)} - onClick={onSettingsClick} - href='#' - title={intl.formatMessage(messages.settings)} - ><Icon icon='cogs' /></a> - <a - aria-label={intl.formatMessage(messages.logout)} - data-method='delete' - href={ signOutLink } - title={intl.formatMessage(messages.logout)} - ><Icon icon='sign-out' /></a> - </nav> - ); -} - -// Props. -DrawerHeader.propTypes = { - columns: ImmutablePropTypes.list, - unreadNotifications: PropTypes.number, - showNotificationsBadge: PropTypes.bool, - intl: PropTypes.object, - onSettingsClick: PropTypes.func, -}; diff --git a/app/javascript/flavours/glitch/features/drawer/index.js b/app/javascript/flavours/glitch/features/drawer/index.js deleted file mode 100644 index c8121b8e5..000000000 --- a/app/javascript/flavours/glitch/features/drawer/index.js +++ /dev/null @@ -1,175 +0,0 @@ -// Package imports. -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { defineMessages } from 'react-intl'; -import classNames from 'classnames'; - -// Actions. -import { openModal } from 'flavours/glitch/actions/modal'; -import { - changeSearch, - clearSearch, - showSearch, - submitSearch, -} from 'flavours/glitch/actions/search'; -import { cycleElefriendCompose } from 'flavours/glitch/actions/compose'; - -// Components. -import Composer from 'flavours/glitch/features/composer'; -import DrawerAccount from './account'; -import DrawerHeader from './header'; -import DrawerResults from './results'; -import DrawerSearch from './search'; - -// Utils. -import { me, mascot } from 'flavours/glitch/util/initial_state'; -import { wrap } from 'flavours/glitch/util/redux_helpers'; - -// Messages. -const messages = defineMessages({ - compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new toot' }, -}); - -// State mapping. -const mapStateToProps = state => ({ - account: state.getIn(['accounts', me]), - columns: state.getIn(['settings', 'columns']), - elefriend: state.getIn(['compose', 'elefriend']), - results: state.getIn(['search', 'results']), - searchHidden: state.getIn(['search', 'hidden']), - searchValue: state.getIn(['search', 'value']), - submitted: state.getIn(['search', 'submitted']), - unreadNotifications: state.getIn(['notifications', 'unread']), - showNotificationsBadge: state.getIn(['local_settings', 'notifications', 'tab_badge']), -}); - -// Dispatch mapping. -const mapDispatchToProps = (dispatch, { intl }) => ({ - onChange (value) { - dispatch(changeSearch(value)); - }, - onClear () { - dispatch(clearSearch()); - }, - onClickElefriend () { - dispatch(cycleElefriendCompose()); - }, - onShow () { - dispatch(showSearch()); - }, - onSubmit () { - dispatch(submitSearch()); - }, - onOpenSettings (e) { - e.preventDefault(); - e.stopPropagation(); - dispatch(openModal('SETTINGS', {})); - }, -}); - -// The component. -class Drawer extends React.Component { - - // Constructor. - constructor (props) { - super(props); - } - - // Rendering. - render () { - const { - account, - columns, - elefriend, - intl, - multiColumn, - onChange, - onClear, - onClickElefriend, - onOpenSettings, - onShow, - onSubmit, - results, - searchHidden, - searchValue, - submitted, - isSearchPage, - unreadNotifications, - showNotificationsBadge, - } = this.props; - const computedClass = classNames('drawer', `mbstobon-${elefriend}`); - - // The result. - return ( - <div className={computedClass} role='region' aria-label={intl.formatMessage(messages.compose)}> - {multiColumn ? ( - <DrawerHeader - columns={columns} - unreadNotifications={unreadNotifications} - showNotificationsBadge={showNotificationsBadge} - intl={intl} - onSettingsClick={onOpenSettings} - /> - ) : null} - {(multiColumn || isSearchPage) && <DrawerSearch - intl={intl} - onChange={onChange} - onClear={onClear} - onShow={onShow} - onSubmit={onSubmit} - submitted={submitted} - value={searchValue} - /> } - <div className='drawer__pager'> - {!isSearchPage && <div className='drawer__inner'> - <DrawerAccount account={account} /> - <Composer /> - {multiColumn && ( - <div className='drawer__inner__mastodon'> - {mascot ? <img alt='' draggable='false' src={mascot} /> : <button className='mastodon' onClick={onClickElefriend} />} - </div> - )} - </div>} - - {(multiColumn || isSearchPage) && - <DrawerResults - results={results} - visible={submitted && !searchHidden} - />} - </div> - </div> - ); - } - -} - -// Props. -Drawer.propTypes = { - intl: PropTypes.object.isRequired, - isSearchPage: PropTypes.bool, - multiColumn: PropTypes.bool, - - // State props. - account: ImmutablePropTypes.map, - columns: ImmutablePropTypes.list, - results: ImmutablePropTypes.map, - elefriend: PropTypes.number, - searchHidden: PropTypes.bool, - searchValue: PropTypes.string, - submitted: PropTypes.bool, - unreadNotifications: PropTypes.number, - showNotificationsBadge: PropTypes.bool, - - // Dispatch props. - onChange: PropTypes.func, - onClear: PropTypes.func, - onClickElefriend: PropTypes.func, - onShow: PropTypes.func, - onSubmit: PropTypes.func, - onOpenSettings: PropTypes.func, -}; - -// Connecting and export. -export { Drawer as WrappedComponent }; -export default wrap(Drawer, mapStateToProps, mapDispatchToProps, true); diff --git a/app/javascript/flavours/glitch/features/drawer/results/index.js b/app/javascript/flavours/glitch/features/drawer/results/index.js deleted file mode 100644 index 4574c0e1e..000000000 --- a/app/javascript/flavours/glitch/features/drawer/results/index.js +++ /dev/null @@ -1,117 +0,0 @@ -// Package imports. -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { - FormattedMessage, - defineMessages, -} from 'react-intl'; -import spring from 'react-motion/lib/spring'; -import { Link } from 'react-router-dom'; - -// Components. -import Icon from 'flavours/glitch/components/icon'; -import AccountContainer from 'flavours/glitch/containers/account_container'; -import StatusContainer from 'flavours/glitch/containers/status_container'; -import Hashtag from 'flavours/glitch/components/hashtag'; - -// Utils. -import Motion from 'flavours/glitch/util/optional_motion'; - -// Messages. -const messages = defineMessages({ - total: { - defaultMessage: '{count, number} {count, plural, one {result} other {results}}', - id: 'search_results.total', - }, -}); - -// The component. -export default function DrawerResults ({ - results, - visible, -}) { - const accounts = results ? results.get('accounts') : null; - const statuses = results ? results.get('statuses') : null; - const hashtags = results ? results.get('hashtags') : null; - - // This gets the total number of items. - const count = [accounts, statuses, hashtags].reduce(function (size, item) { - if (item && item.size) { - return size + item.size; - } - return size; - }, 0); - - // The result. - return ( - <Motion - defaultStyle={{ x: -100 }} - style={{ - x: spring(visible ? 0 : -100, { - stiffness: 210, - damping: 20, - }), - }} - > - {({ x }) => ( - <div - className='drawer--results' - style={{ - transform: `translateX(${x}%)`, - visibility: x === -100 ? 'hidden' : 'visible', - }} - > - <header> - <Icon icon='search' fixedWidth /> - <FormattedMessage - {...messages.total} - values={{ count }} - /> - </header> - {accounts && accounts.size ? ( - <section> - <h5><Icon icon='users' fixedWidth /><FormattedMessage id='search_results.accounts' defaultMessage='People' /></h5> - - {accounts.map( - accountId => ( - <AccountContainer - id={accountId} - key={accountId} - /> - ) - )} - </section> - ) : null} - {statuses && statuses.size ? ( - <section> - <h5><Icon icon='quote-right' fixedWidth /><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5> - - {statuses.map( - statusId => ( - <StatusContainer - id={statusId} - key={statusId} - /> - ) - )} - </section> - ) : null} - {hashtags && hashtags.size ? ( - <section> - <h5><Icon icon='hashtag' fixedWidth /><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></h5> - - {hashtags.map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)} - </section> - ) : null} - </div> - )} - </Motion> - ); -} - -// Props. -DrawerResults.propTypes = { - results: ImmutablePropTypes.map, - visible: PropTypes.bool, -}; diff --git a/app/javascript/flavours/glitch/features/drawer/search/index.js b/app/javascript/flavours/glitch/features/drawer/search/index.js deleted file mode 100644 index 8cbb0906c..000000000 --- a/app/javascript/flavours/glitch/features/drawer/search/index.js +++ /dev/null @@ -1,152 +0,0 @@ -// Package imports. -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React from 'react'; -import { - FormattedMessage, - defineMessages, -} from 'react-intl'; -import Overlay from 'react-overlays/lib/Overlay'; - -// Components. -import Icon from 'flavours/glitch/components/icon'; -import DrawerSearchPopout from './popout'; - -// Utils. -import { focusRoot } from 'flavours/glitch/util/dom_helpers'; -import { - assignHandlers, - hiddenComponent, -} from 'flavours/glitch/util/react_helpers'; - -// Messages. -const messages = defineMessages({ - placeholder: { - defaultMessage: 'Search', - id: 'search.placeholder', - }, -}); - -// Handlers. -const handlers = { - - handleBlur () { - this.setState({ expanded: false }); - }, - - handleChange ({ target: { value } }) { - const { onChange } = this.props; - if (onChange) { - onChange(value); - } - }, - - handleClear (e) { - const { - onClear, - submitted, - value, - } = this.props; - e.preventDefault(); // Prevents focus change ?? - if (onClear && (submitted || value && value.length)) { - onClear(); - } - }, - - handleFocus () { - const { onShow } = this.props; - this.setState({ expanded: true }); - if (onShow) { - onShow(); - } - }, - - handleKeyUp (e) { - const { onSubmit } = this.props; - switch (e.key) { - case 'Enter': - if (onSubmit) { - onSubmit(); - } - break; - case 'Escape': - focusRoot(); - } - }, -}; - -// The component. -export default class DrawerSearch extends React.PureComponent { - - // Constructor. - constructor (props) { - super(props); - assignHandlers(this, handlers); - this.state = { expanded: false }; - } - - // Rendering. - render () { - const { - handleBlur, - handleChange, - handleClear, - handleFocus, - handleKeyUp, - } = this.handlers; - const { - intl, - submitted, - value, - } = this.props; - const { expanded } = this.state; - const active = value && value.length || submitted; - const computedClass = classNames('drawer--search', { active }); - - return ( - <div className={computedClass}> - <label> - <span {...hiddenComponent}> - <FormattedMessage {...messages.placeholder} /> - </span> - <input - type='text' - placeholder={intl.formatMessage(messages.placeholder)} - value={value || ''} - onChange={handleChange} - onKeyUp={handleKeyUp} - onFocus={handleFocus} - onBlur={handleBlur} - /> - </label> - <div - aria-label={intl.formatMessage(messages.placeholder)} - className='icon' - onClick={handleClear} - role='button' - tabIndex='0' - > - <Icon icon='search' /> - <Icon icon='times-circle' /> - </div> - <Overlay - placement='bottom' - show={expanded && !active} - target={this} - ><DrawerSearchPopout /></Overlay> - </div> - ); - } - -} - -// Props. -DrawerSearch.propTypes = { - value: PropTypes.string, - submitted: PropTypes.bool, - onChange: PropTypes.func, - onSubmit: PropTypes.func, - onClear: PropTypes.func, - onShow: PropTypes.func, - intl: PropTypes.object, -}; diff --git a/app/javascript/flavours/glitch/features/drawer/search/popout/index.js b/app/javascript/flavours/glitch/features/drawer/search/popout/index.js deleted file mode 100644 index fec090b64..000000000 --- a/app/javascript/flavours/glitch/features/drawer/search/popout/index.js +++ /dev/null @@ -1,109 +0,0 @@ -// Package imports. -import PropTypes from 'prop-types'; -import React from 'react'; -import { - FormattedMessage, - defineMessages, -} from 'react-intl'; -import spring from 'react-motion/lib/spring'; - -// Utils. -import Motion from 'flavours/glitch/util/optional_motion'; -import { searchEnabled } from 'flavours/glitch/util/initial_state'; - -// Messages. -const messages = defineMessages({ - format: { - defaultMessage: 'Advanced search format', - id: 'search_popout.search_format', - }, - hashtag: { - defaultMessage: 'hashtag', - id: 'search_popout.tips.hashtag', - }, - status: { - defaultMessage: 'status', - id: 'search_popout.tips.status', - }, - text: { - defaultMessage: 'Simple text returns matching display names, usernames and hashtags', - id: 'search_popout.tips.text', - }, - full_text: { - defaultMessage: 'Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.', - id: 'search_popout.tips.full_text', - }, - user: { - defaultMessage: 'user', - id: 'search_popout.tips.user', - }, -}); - -// The spring used by our motion. -const motionSpring = spring(1, { damping: 35, stiffness: 400 }); - -// The component. -export default function DrawerSearchPopout ({ style }) { - - // The result. - return ( - <div - className='drawer--search--popout' - style={{ - ...style, - position: 'absolute', - width: 285, - }} - > - <Motion - defaultStyle={{ - opacity: 0, - scaleX: 0.85, - scaleY: 0.75, - }} - style={{ - opacity: motionSpring, - scaleX: motionSpring, - scaleY: motionSpring, - }} - > - {({ opacity, scaleX, scaleY }) => ( - <div - style={{ - opacity: opacity, - transform: `scale(${scaleX}, ${scaleY})`, - }} - > - <h4><FormattedMessage {...messages.format} /></h4> - <ul> - <li> - <em>#example</em> - {' '} - <FormattedMessage {...messages.hashtag} /> - </li> - <li> - <em>@username@domain</em> - {' '} - <FormattedMessage {...messages.user} /> - </li> - <li> - <em>URL</em> - {' '} - <FormattedMessage {...messages.user} /> - </li> - <li> - <em>URL</em> - {' '} - <FormattedMessage {...messages.status} /> - </li> - </ul> - { searchEnabled ? <FormattedMessage {...messages.full_text} /> : <FormattedMessage {...messages.text} /> } - </div> - )} - </Motion> - </div> - ); -} - -// Props. -DrawerSearchPopout.propTypes = { style: PropTypes.object }; |