diff options
49 files changed, 479 insertions, 111 deletions
diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb index db6cd8568..bbbcf7f90 100644 --- a/app/controllers/api/v1/timelines/home_controller.rb +++ b/app/controllers/api/v1/timelines/home_controller.rb @@ -9,7 +9,11 @@ class Api::V1::Timelines::HomeController < Api::BaseController def show @statuses = load_statuses - render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) + + render json: @statuses, + each_serializer: REST::StatusSerializer, + relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id), + status: regeneration_in_progress? ? 206 : 200 end private @@ -57,4 +61,8 @@ class Api::V1::Timelines::HomeController < Api::BaseController def pagination_since_id @statuses.first.id end + + def regeneration_in_progress? + Redis.current.exists("account:#{current_account.id}:regeneration") + end end diff --git a/app/javascript/flavours/glitch/actions/timelines.js b/app/javascript/flavours/glitch/actions/timelines.js index 9a5b2e6da..3a9d64084 100644 --- a/app/javascript/flavours/glitch/actions/timelines.js +++ b/app/javascript/flavours/glitch/actions/timelines.js @@ -19,13 +19,14 @@ export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT'; export const TIMELINE_CONTEXT_UPDATE = 'CONTEXT_UPDATE'; -export function refreshTimelineSuccess(timeline, statuses, skipLoading, next) { +export function refreshTimelineSuccess(timeline, statuses, skipLoading, next, partial) { return { type: TIMELINE_REFRESH_SUCCESS, timeline, statuses, skipLoading, next, + partial, }; }; @@ -88,7 +89,7 @@ export function refreshTimeline(timelineId, path, params = {}) { return function (dispatch, getState) { const timeline = getState().getIn(['timelines', timelineId], ImmutableMap()); - if (timeline.get('isLoading') || timeline.get('online')) { + if (timeline.get('isLoading') || (timeline.get('online') && !timeline.get('isPartial'))) { return; } @@ -104,8 +105,12 @@ export function refreshTimeline(timelineId, path, params = {}) { dispatch(refreshTimelineRequest(timelineId, skipLoading)); api(getState).get(path, { params }).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null)); + if (response.status === 206) { + dispatch(refreshTimelineSuccess(timelineId, [], skipLoading, null, true)); + } else { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null, false)); + } }).catch(error => { dispatch(refreshTimelineFail(timelineId, error, skipLoading)); }); diff --git a/app/javascript/flavours/glitch/components/account.js b/app/javascript/flavours/glitch/components/account.js index 265ee94f6..df17f1897 100644 --- a/app/javascript/flavours/glitch/components/account.js +++ b/app/javascript/flavours/glitch/components/account.js @@ -132,7 +132,7 @@ export default class Account extends ImmutablePureComponent { <div className='account__relationship'> {buttons} </div> - : null} + : null} </div> </div> ); diff --git a/app/javascript/flavours/glitch/components/attachment_list.js b/app/javascript/flavours/glitch/components/attachment_list.js index b3d00b335..3a28c70f3 100644 --- a/app/javascript/flavours/glitch/components/attachment_list.js +++ b/app/javascript/flavours/glitch/components/attachment_list.js @@ -21,9 +21,9 @@ export default class AttachmentList extends ImmutablePureComponent { <ul className='attachment-list__list'> {media.map(attachment => - <li key={attachment.get('id')}> + (<li key={attachment.get('id')}> <a href={attachment.get('remote_url')} target='_blank' rel='noopener'>{filename(attachment.get('remote_url'))}</a> - </li> + </li>) )} </ul> </div> diff --git a/app/javascript/flavours/glitch/components/collapsable.js b/app/javascript/flavours/glitch/components/collapsable.js index fe125a729..0e8b04033 100644 --- a/app/javascript/flavours/glitch/components/collapsable.js +++ b/app/javascript/flavours/glitch/components/collapsable.js @@ -6,9 +6,9 @@ import PropTypes from 'prop-types'; const Collapsable = ({ fullHeight, isVisible, children }) => ( <Motion defaultStyle={{ opacity: !isVisible ? 0 : 100, height: isVisible ? fullHeight : 0 }} style={{ opacity: spring(!isVisible ? 0 : 100), height: spring(!isVisible ? 0 : fullHeight) }}> {({ opacity, height }) => - <div style={{ height: `${height}px`, overflow: 'hidden', opacity: opacity / 100, display: Math.floor(opacity) === 0 ? 'none' : 'block' }}> + (<div style={{ height: `${height}px`, overflow: 'hidden', opacity: opacity / 100, display: Math.floor(opacity) === 0 ? 'none' : 'block' }}> {children} - </div> + </div>) } </Motion> ); diff --git a/app/javascript/flavours/glitch/components/icon_button.js b/app/javascript/flavours/glitch/components/icon_button.js index 13b91e8a1..dfbe75110 100644 --- a/app/javascript/flavours/glitch/components/icon_button.js +++ b/app/javascript/flavours/glitch/components/icon_button.js @@ -116,7 +116,7 @@ export default class IconButton extends React.PureComponent { return ( <Motion defaultStyle={motionDefaultStyle} style={motionStyle}> {({ rotate }) => - <button + (<button aria-label={title} aria-pressed={pressed} aria-expanded={expanded} @@ -128,7 +128,7 @@ export default class IconButton extends React.PureComponent { > <i style={{ transform: `rotate(${rotate}deg)` }} className={`fa fa-fw fa-${icon}`} aria-hidden='true' /> {this.props.label} - </button> + </button>) } </Motion> ); diff --git a/app/javascript/flavours/glitch/components/missing_indicator.js b/app/javascript/flavours/glitch/components/missing_indicator.js index 87df7f61c..70d8c3b98 100644 --- a/app/javascript/flavours/glitch/components/missing_indicator.js +++ b/app/javascript/flavours/glitch/components/missing_indicator.js @@ -2,9 +2,14 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; const MissingIndicator = () => ( - <div className='missing-indicator'> + <div className='regeneration-indicator missing-indicator'> <div> - <FormattedMessage id='missing_indicator.label' defaultMessage='Not found' /> + <div className='regeneration-indicator__figure' /> + + <div className='regeneration-indicator__label'> + <FormattedMessage id='missing_indicator.label' tagName='strong' defaultMessage='Not found' /> + <FormattedMessage id='missing_indicator.sublabel' defaultMessage='This resource could not be found' /> + </div> </div> </div> ); diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 4feb9180b..feffc2d59 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -318,14 +318,14 @@ export default class Status extends ImmutablePureComponent { media = ( <Bundle fetchComponent={Video} loading={this.renderLoadingVideoPlayer} > - {Component => <Component + {Component => (<Component preview={video.get('preview_url')} src={video.get('url')} sensitive={status.get('sensitive')} letterbox={settings.getIn(['media', 'letterbox'])} fullwidth={settings.getIn(['media', 'fullwidth'])} onOpenVideo={this.handleOpenVideo} - />} + />)} </Bundle> ); mediaIcon = 'video-camera'; diff --git a/app/javascript/flavours/glitch/components/status_header.js b/app/javascript/flavours/glitch/components/status_header.js index bfa996cd5..e8c7a771e 100644 --- a/app/javascript/flavours/glitch/components/status_header.js +++ b/app/javascript/flavours/glitch/components/status_header.js @@ -104,8 +104,8 @@ export default class StatusHeader extends React.PureComponent { active={collapsed} title={ collapsed ? - intl.formatMessage(messages.uncollapse) : - intl.formatMessage(messages.collapse) + intl.formatMessage(messages.uncollapse) : + intl.formatMessage(messages.collapse) } icon='angle-double-up' onClick={this.handleCollapsedClick} diff --git a/app/javascript/flavours/glitch/components/status_list.js b/app/javascript/flavours/glitch/components/status_list.js index f190ba6ab..f253f0fdc 100644 --- a/app/javascript/flavours/glitch/components/status_list.js +++ b/app/javascript/flavours/glitch/components/status_list.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import StatusContainer from 'flavours/glitch/containers/status_container'; import ImmutablePureComponent from 'react-immutable-pure-component'; import ScrollableList from './scrollable_list'; +import { FormattedMessage } from 'react-intl'; export default class StatusList extends ImmutablePureComponent { @@ -16,6 +17,7 @@ export default class StatusList extends ImmutablePureComponent { trackScroll: PropTypes.bool, shouldUpdateScroll: PropTypes.func, isLoading: PropTypes.bool, + isPartial: PropTypes.bool, hasMore: PropTypes.bool, prepend: PropTypes.node, emptyMessage: PropTypes.node, @@ -48,8 +50,23 @@ export default class StatusList extends ImmutablePureComponent { } render () { - const { statusIds, ...other } = this.props; - const { isLoading } = other; + const { statusIds, ...other } = this.props; + const { isLoading, isPartial } = other; + + if (isPartial) { + return ( + <div className='regeneration-indicator'> + <div> + <div className='regeneration-indicator__figure' /> + + <div className='regeneration-indicator__label'> + <FormattedMessage id='regeneration_indicator.label' tagName='strong' defaultMessage='Loading…' /> + <FormattedMessage id='regeneration_indicator.sublabel' defaultMessage='Your home feed is being prepared!' /> + </div> + </div> + </div> + ); + } const scrollableContent = (isLoading || statusIds.size > 0) ? ( statusIds.map((statusId) => ( diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index 1a258c7e4..767e4da47 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -64,11 +64,11 @@ export default class Header extends ImmutablePureComponent { <div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}> <div> <a - href={account.get('url')} - className='account__header__avatar' - role='presentation' - target='_blank' - rel='noopener' + href={account.get('url')} + className='account__header__avatar' + role='presentation' + target='_blank' + rel='noopener' > <Avatar account={account} size={90} /> </a> diff --git a/app/javascript/flavours/glitch/features/account_gallery/index.js b/app/javascript/flavours/glitch/features/account_gallery/index.js index 951e019e3..df66b3b21 100644 --- a/app/javascript/flavours/glitch/features/account_gallery/index.js +++ b/app/javascript/flavours/glitch/features/account_gallery/index.js @@ -95,10 +95,10 @@ export default class AccountGallery extends ImmutablePureComponent { <div className='account-gallery__container'> {medias.map(media => - <MediaItem + (<MediaItem key={media.get('id')} media={media} - /> + />) )} {loadMore} </div> diff --git a/app/javascript/flavours/glitch/features/composer/upload_form/progress/index.js b/app/javascript/flavours/glitch/features/composer/upload_form/progress/index.js index 9dac6acf9..8c4b0eea6 100644 --- a/app/javascript/flavours/glitch/features/composer/upload_form/progress/index.js +++ b/app/javascript/flavours/glitch/features/composer/upload_form/progress/index.js @@ -36,10 +36,10 @@ export default function ComposerUploadFormProgress ({ progress }) { style={{ width: spring(progress) }} > {({ width }) => - <div + (<div className='tracker' style={{ width: `${width}%` }} - /> + />) } </Motion> </div> diff --git a/app/javascript/flavours/glitch/features/home_timeline/index.js b/app/javascript/flavours/glitch/features/home_timeline/index.js index 2dfec6bbe..c20c0244a 100644 --- a/app/javascript/flavours/glitch/features/home_timeline/index.js +++ b/app/javascript/flavours/glitch/features/home_timeline/index.js @@ -1,6 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; -import { expandHomeTimeline } from 'flavours/glitch/actions/timelines'; +import { expandHomeTimeline, refreshHomeTimeline } from 'flavours/glitch/actions/timelines'; import PropTypes from 'prop-types'; import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container'; import Column from 'flavours/glitch/components/column'; @@ -16,6 +16,7 @@ const messages = defineMessages({ const mapStateToProps = state => ({ hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0, + isPartial: state.getIn(['timelines', 'home', 'isPartial'], false), }); @connect(mapStateToProps) @@ -26,6 +27,7 @@ export default class HomeTimeline extends React.PureComponent { dispatch: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, hasUnread: PropTypes.bool, + isPartial: PropTypes.bool, columnId: PropTypes.string, multiColumn: PropTypes.bool, }; @@ -57,6 +59,39 @@ export default class HomeTimeline extends React.PureComponent { this.props.dispatch(expandHomeTimeline()); } + componentDidMount () { + this._checkIfReloadNeeded(false, this.props.isPartial); + } + + componentDidUpdate (prevProps) { + this._checkIfReloadNeeded(prevProps.isPartial, this.props.isPartial); + } + + componentWillUnmount () { + this._stopPolling(); + } + + _checkIfReloadNeeded (wasPartial, isPartial) { + const { dispatch } = this.props; + + if (wasPartial === isPartial) { + return; + } else if (!wasPartial && isPartial) { + this.polling = setInterval(() => { + dispatch(refreshHomeTimeline()); + }, 3000); + } else if (wasPartial && !isPartial) { + this._stopPolling(); + } + } + + _stopPolling () { + if (this.polling) { + clearInterval(this.polling); + this.polling = null; + } + } + render () { const { intl, hasUnread, columnId, multiColumn } = this.props; const pinned = !!columnId; diff --git a/app/javascript/flavours/glitch/features/list_editor/index.js b/app/javascript/flavours/glitch/features/list_editor/index.js index 7f9c6b0e9..e6df4755a 100644 --- a/app/javascript/flavours/glitch/features/list_editor/index.js +++ b/app/javascript/flavours/glitch/features/list_editor/index.js @@ -67,9 +67,9 @@ export default class ListEditor extends ImmutablePureComponent { <Motion defaultStyle={{ x: -100 }} style={{ x: spring(showSearch ? 0 : -100, { stiffness: 210, damping: 20 }) }}> {({ x }) => - <div className='drawer__inner backdrop' style={{ transform: x === 0 ? null : `translateX(${x}%)`, visibility: x === -100 ? 'hidden' : 'visible' }}> + (<div className='drawer__inner backdrop' style={{ transform: x === 0 ? null : `translateX(${x}%)`, visibility: x === -100 ? 'hidden' : 'visible' }}> {searchAccountIds.map(accountId => <Account key={accountId} accountId={accountId} />)} - </div> + </div>) } </Motion> </div> diff --git a/app/javascript/flavours/glitch/features/list_timeline/index.js b/app/javascript/flavours/glitch/features/list_timeline/index.js index c6a89a920..f9476d92d 100644 --- a/app/javascript/flavours/glitch/features/list_timeline/index.js +++ b/app/javascript/flavours/glitch/features/list_timeline/index.js @@ -120,13 +120,17 @@ export default class ListTimeline extends React.PureComponent { if (typeof list === 'undefined') { return ( <Column> - <LoadingIndicator /> + <div className='scrollable'> + <LoadingIndicator /> + </div> </Column> ); } else if (list === false) { return ( <Column> - <MissingIndicator /> + <div className='scrollable'> + <MissingIndicator /> + </div> </Column> ); } diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.js b/app/javascript/flavours/glitch/features/ui/components/modal_root.js index a3e734867..e12ee1761 100644 --- a/app/javascript/flavours/glitch/features/ui/components/modal_root.js +++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.js @@ -124,7 +124,7 @@ export default class ModalRoot extends React.PureComponent { (<BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}> {(SpecificComponent) => <SpecificComponent {...props} onClose={onClose} />} </BundleContainer>) : - null + null } </div> </div> diff --git a/app/javascript/flavours/glitch/features/ui/components/upload_area.js b/app/javascript/flavours/glitch/features/ui/components/upload_area.js index cc6b6d171..11a10baf1 100644 --- a/app/javascript/flavours/glitch/features/ui/components/upload_area.js +++ b/app/javascript/flavours/glitch/features/ui/components/upload_area.js @@ -38,12 +38,12 @@ export default class UploadArea extends React.PureComponent { return ( <Motion defaultStyle={{ backgroundOpacity: 0, backgroundScale: 0.95 }} style={{ backgroundOpacity: spring(active ? 1 : 0, { stiffness: 150, damping: 15 }), backgroundScale: spring(active ? 1 : 0.95, { stiffness: 200, damping: 3 }) }}> {({ backgroundOpacity, backgroundScale }) => - <div className='upload-area' style={{ visibility: active ? 'visible' : 'hidden', opacity: backgroundOpacity }}> + (<div className='upload-area' style={{ visibility: active ? 'visible' : 'hidden', opacity: backgroundOpacity }}> <div className='upload-area__drop'> <div className='upload-area__background' style={{ transform: `scale(${backgroundScale})` }} /> <div className='upload-area__content'><FormattedMessage id='upload_area.title' defaultMessage='Drag & drop to upload' /></div> </div> - </div> + </div>) } </Motion> ); diff --git a/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js b/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js index eca85b8e6..f85a2eeb8 100644 --- a/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js +++ b/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js @@ -51,6 +51,7 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, { timelineId }) => ({ statusIds: getStatusIds(state, { type: timelineId }), isLoading: state.getIn(['timelines', timelineId, 'isLoading'], true), + isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false), hasMore: !!state.getIn(['timelines', timelineId, 'next']), }); diff --git a/app/javascript/flavours/glitch/images/elephant_ui_disappointed.svg b/app/javascript/flavours/glitch/images/elephant_ui_disappointed.svg new file mode 100644 index 000000000..580c15a13 --- /dev/null +++ b/app/javascript/flavours/glitch/images/elephant_ui_disappointed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="134.11569" width="134.61565" viewBox="0 0 134.61565 134.11569"><path d="M82.69963 103.86569c6.8 1.5 11 2.4 11.3-6.200005.3-8.6-1.8-17.3-1.8-17.3l-13.6 1.1 4.1 22.400005z" class="st32" fill="#3a434e" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M65.39963 112.96569c-.2 10.3-.6 17.5 6.5 17.4 7.1-.1 12.6 1.1 13.6-5.3 1.1-6.3 1.9-20.6.7-28.000005" class="st32" fill="#3a434e" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M86.39963 97.66569c-1.4-7.5-4.1-23.2-4.1-23.2s13.2-1.5 10.4-13c-2.7-11.4-7.5-22.6-11-31.1s-14.5-16.9-28.6-15.7c-19.2 1.6-25.6 7-31.6 23.1-5.4 14.4-10.4 47.2-8.9 63.3.8 8.7 5 13.7 14.4 13.5 9.4-.2 39.8-.8 49.8-2.8.3-.1.6-.1.9-.2" class="st33" fill="#56606b"/><path d="M85.89963 97.76569l-4.1-23.2c0-.3.1-.5.4-.6 2.6-.4 5.3-1.4 7.3-3.1 1-.8 1.9-1.9 2.4-3.1.5-1.2.7-2.5.6-3.9 0-1.3-.4-2.6-.7-4-.3-1.3-.7-2.7-1.1-4-.8-2.7-1.7-5.3-2.6-7.9-1.9-5.2-4-10.4-6.1-15.5-.5-1.3-1-2.6-1.7-3.8-.6-1.2-1.4-2.3-2.3-3.4-1.7-2.1-3.8-4-6-5.5-4.6-3-10-4.7-15.4-4.9-2.7-.1-5.5.3-8.2.6-2.7.4-5.5.9-8.1 1.7-2.6.8-5.1 1.9-7.3 3.5s-4.1 3.6-5.6 5.8c-1.5 2.3-2.8 4.7-3.9 7.3-.6 1.3-1.1 2.5-1.6 3.8-.4 1.3-.9 2.6-1.3 3.9-1.6 5.3-2.8 10.7-3.9 16.1-1 5.4-1.9 10.9-2.6 16.4-.7 5.5-1.2 11-1.3 16.6-.1 2.8-.1 5.5.1 8.3.1 2.8.5 5.5 1.6 8 1 2.5 2.9 4.6 5.4 5.7 2.4 1.1 5.2 1.3 8 1.3 5.6-.1 11.1-.2 16.7-.4 11.1-.4 22.2-.8 33.2-2.3.1 0 .2.1.2.2s0 .2-.1.2c-2.7.9-5.5 1.2-8.3 1.4-2.8.2-5.6.5-8.3.6-5.6.3-11.1.6-16.7.7-5.6.2-11.1.3-16.7.4-2.8.1-5.7-.1-8.4-1.3s-4.7-3.5-5.8-6.2c-1.1-2.6-1.5-5.5-1.6-8.3-.2-2.8-.2-5.6-.1-8.4.2-5.6.7-11.1 1.3-16.7.7-5.5 1.5-11 2.6-16.5s2.3-10.9 3.9-16.3c.4-1.3.9-2.7 1.3-4 .5-1.3 1-2.6 1.6-3.9 1.1-2.6 2.4-5.1 4-7.4 1.6-2.3 3.6-4.4 5.9-6.1 2.3-1.7 4.9-2.8 7.6-3.7 2.7-.8 5.5-1.4 8.2-1.7 2.8-.3 5.5-.7 8.4-.6 5.6.2 11.2 1.9 15.9 5 2.4 1.6 4.5 3.5 6.3 5.7.9 1.1 1.7 2.3 2.4 3.5.7 1.3 1.2 2.6 1.7 3.9 2.1 5.1 4.2 10.3 6.1 15.5.9 2.6 1.8 5.3 2.6 7.9.4 1.3.8 2.7 1.1 4 .3 1.3.7 2.7.8 4.2.1 1.4-.1 2.9-.7 4.3s-1.5 2.5-2.6 3.5c-2.3 1.9-5 2.8-7.9 3.3l.4-.6 4.1 23.2c0 .3-.1.5-.4.6-.3.1-.7.5-.7.2z"/><path d="M26.49963 114.06569c-4.7 0-7.4-2.1-10-4.4-2.3-2-3.2-4.6-3.4-8.6-.1-2.700005-.6-10.000005.4-18.800005 3.8.9 9.7 3.8 13.4 7.6 5.6 5.7 17.7 6.3 22.7 6.3h1.8l.1-.4s.5-2.6 1.8-5.2l.3-.6-.7-.1c-.4-.1-10.9-1.9-9.7-10.8.7-4.9 13.3-7.9 33.9-7.9 2.2 0 3.8 0 4.2.1l3.5 2.2c-1.5.5-2.6.6-2.6.6l-.5.1.1.5c0 .2 2.8 16.4 4.1 24 0 0-7.9 13.100005-8 13.000005-.1-.1-.3-.1-.3-.1-.3 0-.7.1-.9.1-9.9 1.7-39.6 2.4-49.3 2.6l-.9-.2z" class="st34" fill="#3a434e"/><path d="M45.89963 51.36569c-.7 0-1.4-.6-1.4-1.4v-5.1c0-.7.6-1.4 1.4-1.4.7 0 1.4.6 1.4 1.4v5.1c-.1.8-.7 1.4-1.4 1.4z"/><path d="M72.89963 30.365685c-3.5.4-2.7 2.9-1.2 3.5 1.5.6 3.7.1 4.3-1.6.4-1.6-1.3-2.1-3.1-1.9z" class="st35" fill="#4f5862"/><path d="M44.29963 53.965685c-.4.7-1.5.2-2.7-.6-1.2-.8-2.1-1.5-1.6-2.2.4-.7 1.6-.4 2.8.4 1.2.8 2 1.7 1.5 2.4z" class="st34" fill="#4f5862"/><path d="M27.29963 36.165685c0-5.6-3.7-9.4-7.9-9.8-4.2-.4-9-.3-14.0000002 11.3-5.00000001 11.6-6.7 15.7-2.6 17.9 4.1 2.2 9.5000002 1.5 11.3000002-1.4 0 0 5.3 3.8 9.7-3.8" class="st36" fill="#56606b" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M11.19963 40.565685c-2.7000002 5.1-2.7000002 7.7-.5 8.5 2.2.8 4.1.7 6.4-3 0 0 2 .7 4.9-4.1.9-1.5-.7-2.6-.7-2.6s-4.8 1.3-7.1-5l-3 6.2z" class="st34" fill="#3a434e" fill-opacity="0"/><path d="M9.7996298 43.365685l4.4000002-9s1.8 6.3 7.8 4.9" class="st7" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M27.89963 67.365685c-4.9.8-9.7 4.5-9.3 15.7.4 11.2.5 18.700005 6.1 20.000005 5.5 1.3 13.8.3 14.1-7.100005.3-7.4.3-16.1.3-16.1" class="st36" fill="#53606c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M28.69963 102.96569c-1.4 0-2.8-.2-4.1-.5-1.2-.3-2.2-.9-3-2 .5.2 1.1.3 1.7.3 1.2 0 5.2-.5 5.8-7.200005.7-7.4 2.8-10.9 6.6-10.9.8 0 1.6.1 2.6.4 0 3.4-.1 8.3-.2 12.7-.2 6.700005-7.2 7.200005-9.4 7.200005z" class="st34" fill="#3a434e"/><path d="M50.69963 18.965685c-5.2 2.9-14.6 4.7-18.1-1.5-3-5.4 2.1-9.6999996 7.8-9.9999996 5.7-.3 7.6 1.2 7.6 1.2s1.9-5.9 9.3-7.69999998c3.9-1 6-.1 6.2 1.19999998 0 0 3.6-.9 4 3.5 0 0 3.9-.4 3.1 5.1999996-.8 5.6-10.6 10.1-17.7 6.4 0 0-1.1 1.2-2.2 1.7z" class="st33" fill="#56606b"/><path d="M40.79963 21.665685c-2.7 0-4.8-.9-6.3-2.3-.7-1.1-.8-2.9-.3-4.3.8-1.9 2.6-3.3 4.6-3.7 1.2-.2 2.6-.4 3.9-.4 3.3 0 6.2.8 7.3 1.9l.6.6.3-.7s.7-2 2.2-2c.2 0 .5.1.8.2 2.2.9 3.5 1.2 4.6 1.2.5 0 .9-.1 1.3-.2.1-.1.4-.1.6-.1.6 0 1.5.3 1.8.8.2.3.2.6.1 1l-.2.6h.7c.4 0 1.4.2 1.8.9.2.4.2 1-.2 1.7-1.8.8-3.8 1.2-5.7 1.2-2 0-4 0-5.6-.8 0 0-1.2 1.3-2.2 1.8-3.1 1.6-7 2.6-10.1 2.6z" class="st34" fill="#3a434e" fill-opacity=".94117647"/><path d="M61.79963 18.66569c-3.1.5-6.3.1-8.9-1.5.7.2 1.5.4 2.2.5.7.2 1.4.2 2.2.3.7.1 1.4 0 2.2 0 .7-.1 1.4-.1 2.2-.2h.1c.3 0 .5.1.6.4-.1.2-.3.5-.6.5z"/><path d="M37.59963 21.26569c-2.4-.4-4.8-2.1-5.7-4.5-.5-1.2-.7-2.6-.3-3.9.3-1.3 1.1-2.4 2.1-3.3 2-1.7 4.6-2.5 7.1-2.6 1.3-.1 2.5 0 3.8.1.6.1 1.3.2 1.9.4.6.2 1.2.4 1.9.8l-.8.2c.6-1.6 1.6-3 2.8-4.2 1.2-1.2 2.6-2.2 4.1-2.9 1.5-.7 3.2-1.1 4.8-1.3.8-.1 1.7-.1 2.6.1.4.1.9.3 1.3.6s.7.8.8 1.3l-.6-.4c.6-.1 1.2-.1 1.7 0 .6.1 1.1.4 1.6.8.4.4.7.9.9 1.5.1.3.2.5.2.8l.1.8-.5-.4c1 0 1.9.3 2.6.9.7.7 1 1.6 1.1 2.5.1.9 0 1.7-.1 2.5-.2.9-.5 1.7-1 2.4-.9 1.4-2.2 2.5-3.7 3.4-1.4.9-3 1.4-4.6 1.8-.3.1-.5-.1-.6-.4-.1-.3.1-.5.4-.6 1.5-.3 3-.9 4.3-1.7 1.3-.8 2.5-1.8 3.3-3.1.4-.6.7-1.3.8-2 .1-.7.2-1.5.1-2.2-.1-.7-.3-1.4-.8-1.9-.5-.4-1.2-.7-1.8-.7-.3 0-.5-.2-.5-.4l-.1-.7c-.1-.2-.1-.4-.2-.7-.2-.4-.4-.8-.7-1.1-.3-.3-.7-.5-1.1-.6-.4-.1-.9-.1-1.3 0-.3.1-.5-.1-.6-.4-.1-.5-.7-.9-1.4-1.1-.7-.2-1.5-.2-2.2-.1-1.5.2-3.1.6-4.5 1.2-1.4.7-2.7 1.6-3.8 2.7-1.1 1.1-2 2.5-2.5 3.8-.1.3-.4.4-.6.3h-.1c-.4-.2-1-.5-1.5-.6-.6-.1-1.2-.2-1.7-.3-1.2-.1-2.4-.2-3.6-.1-2.4.1-4.7.8-6.5 2.3-.9.7-1.6 1.7-1.9 2.8-.3 1.1-.2 2.3.2 3.4s1.1 2.1 1.9 2.9c.6.9 1.7 1.5 2.9 1.9z"/><path d="M63.49963 2.1656854c0 3.5-2.6 5.5-4.3 6.1m8.3-2.6c.2 3.4-3.3 5.1999996-3.3 5.1999996" class="st7" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M90.29963 84.765685c2.6 2.3 3 4.3-2.4 4.8-5.3.5-25.7 2.4-28.2 2.6-2.4.3-3.4 1.7-3.4 2.8 0 1.1.5 3.2 4 3.1 3.4-.1 23.8-1.5 30.4-2.4 6.6-.8 14.4-2.4 13.4-9s-5.4-8.7-5.4-8.7l-8.4 6.8z" class="st37" fill="#737039" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M90.29963 84.765685c2.6 2.3 3 4.3-2.4 4.8-5.3.5-25.7 2.4-28.2 2.6-2.4.3-3.4 1.7-3.4 2.8 0 1.1.5 3.2 4 3.1 3.4-.1 23.8-1.5 30.4-2.4 6.6-.8 13.8-2.3 13.4-9-.3-5.5-3.1-7-4.4-8.1-.5-.1-1-.1-1.6-.2l-7.8 6.4z" fill="#625d28" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M102.69963 64.665685c5.4-.1 10.3-1.9 12.2-6.5 1.9-4.6 8.7-10.1 14.2-2.1 5.4 8.1 6.6 17.3 2.8 23.7-3.8 6.5-12.1 3.5-14.9-.5-2.7-4-8.6-2.9-14.5-2.7-5.9.2.2-11.9.2-11.9z" class="st37" fill="#737039" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M65.89963 54.865685s10.2 21.3 13.5 26.8c3.2 5.5 12.9 6.2 17.4 3.5 4.5-2.7 7.3-7.3 8-15.1.7-7.9-2.4-14.9-10-15.2-7.6-.3-11.9 7.6-12.1 13.7" class="st36" fill="#53606c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M65.89963 54.865685s10.2 21.3 13.5 26.8c3.2 5.5 12.9 6.2 17.4 3.5 4.5-2.7 7.3-7.3 8-15.1.7-7.9-2.4-14.9-10-15.2-7.6-.3-11.9 7.6-12.1 13.7" class="st36" fill="#56606b" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M90.19963 86.165685c-3.7 0-8.3-1.3-10.4-4.8-.9-1.5-2.4-4.3-4.4-8.4l5.9-.1c4 7.4 5.9 9.8 8 9.8 3.9 0 6-3.4 6.9-9.5.2-1.2.3-2.3.4-3.4.5-4.6.9-7.2 3.4-7.5.3 0 .6-.1.9-.1 2.1 0 2.5 1.2 3.1 2.8.1.2.2.5.2.7.1 1.3.1 2.7 0 4.2-.7 7.3-3.1 11.9-7.7 14.7-1.6 1-3.9 1.6-6.3 1.6z" class="st34" fill="#3a434e"/><path d="M89.19963 63.86569l-.3 6.6c-.1 1.1-.2 2.2-.4 3.3-.1.6-.3 1.1-.5 1.7-.3.5-.6 1.1-1.2 1.5-.2.1-.5.1-.7-.2-.1-.2-.1-.5.2-.7.7-.4 1.1-1.5 1.3-2.5.2-1 .4-2.1.5-3.2.2-2.2.3-4.4.5-6.6 0-.2.2-.3.3-.3.2.1.3.3.3.4z"/><path d="M52.29963 68.665685c-6.3.6-11.1 3.9-10 10.7 1.1 6.8 7.6 8.1 16 7.7 8.4-.4 26.4-1.3 26.4-1.3s-3.3-1.7-4.8-3.3c-.5-.6-1-1.4-1.6-2.5-1.6.1-15.5.8-22.7 1-3.4.1-3.8-1.2-3.9-1.8-.3-1.2.5-2.7 2.8-2.8 3.1-.2 10.8-.7 21.4-.7h11.5s.9-.3 1-9.1c0-.1-29.8 1.5-36.1 2.1z" class="st37" fill="#737039" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M56.19963 86.665685c-8.8 0-12.6-2.3-13.5-7.4 0-.1 0-.2-.1-.4 1.2 1.5 3.5 2.7 5.6 2.7 1.4 0 2.6-.5 3.6-1.5.5.7 1.4 1.4 3.7 1.4h.4c6.9-.2 19.5-.8 22.1-.9.6 1.1 1.2 1.9 1.6 2.4.9 1 2.4 1.9 3.6 2.5-5 .3-18.1.9-24.7 1.2h-2.3z" class="st39" fill="#625d28"/><path d="M44.09963 57.865685c-2.2-.6-5.8-8.3-8.7-8.7-2.9-.3-6.6 1.6-3.2 8.5 3.4 6.9 8 10 14.3 8.2 6.3-1.8 12.7-5.1 14.5-8.3 1.8-3.2-.6-6.2-4.8-4.3-4.1 1.7-9.9 5.2-12.1 4.6z" fill="#b3bfcd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M43.09963 65.865685c-4.3 0-7.7-2.7-10.4-8.4-1.4-2.8-1.7-5.1-.8-6.4.8-1.3 2.3-1.4 2.9-1.4h.6c.4 0 .8.2 1.2.6-.7.1-1.3.5-1.6 1.2-.6 1.2-.3 2.9.9 4.7l.4.6c2.1 3.1 4.1 6 7.8 6 .9 0 1.9-.2 2.9-.6 5.6-2 9.4-3.6 11.1-5.4 1.2-1.3 1.9-2.6 1.7-3.6.5.2.9.5 1.1.9.5.8.4 1.9-.2 3-1.6 2.8-7.4 6.2-14.2 8.1-1.2.5-2.3.7-3.4.7z" class="st35" fill="#93a1b5"/><path d="M13.89963 107.66569c-.1 5.1 1.3 10.2 2.3 14.8 1.3 5.5 1.3 10.1 5.2 10.7 3.9.6 10.1.9 14.4 0 4.3-.9 4.1-5.2 4.5-8.2.4-3.1 0-10.7 0-10.7s-1.1-1.4-3-1.9" class="st34" fill="#3a434e"/><path d="M14.39963 107.66569c-.1 5.2 1.3 10.3 2.5 15.4l.8 3.9c.3 1.3.6 2.5 1.1 3.6.3.5.6 1 1.1 1.4.5.3 1 .5 1.6.6 1.3.2 2.6.3 3.9.4 2.6.2 5.2.2 7.8 0 1.3-.1 2.6-.3 3.7-.7 1.1-.4 1.9-1.4 2.3-2.6.4-1.2.5-2.4.7-3.7.1-.7.2-1.3.2-1.9.1-.6.1-1.3.1-1.9 0-2.6 0-5.2-.2-7.8l.1.3c-.1-.2-.3-.4-.5-.6l-.6-.6c-.4-.4-.9-.7-1.5-.9-.1 0-.1-.1-.1-.2s.1-.1.2-.1c.6.1 1.2.3 1.7.6.3.1.5.3.8.5.3.2.5.4.8.6.1.1.1.2.1.2.1 2.6.2 5.3.2 7.9 0 .7 0 1.3-.1 2s-.2 1.3-.2 2c-.1 1.3-.3 2.7-.7 4-.5 1.3-1.5 2.6-2.8 3.1-1.4.6-2.7.7-4 .8-2.7.2-5.3.2-8 0-1.3-.1-2.6-.2-4-.4-.7-.1-1.4-.4-2-.8-.6-.5-1-1.1-1.4-1.7-.6-1.3-.9-2.6-1.2-3.9l-.8-3.9c-1.1-5.1-2.6-10.3-2.5-15.6 0-.3.2-.5.5-.5.2 0 .4.2.4.5z"/><path d="M68.19963 86.665685l.4 4.6s.3 1.5 2.4 1.5c2.1-.1 2.2-2 2.2-2l-.1-4.5-4.9.4z" class="st37" fill="#737039" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M110.49963 71.465685c-.5 1.8.5 2.9 3.8 4.6 3.3 1.8 4 5.1 8.2 6 4.3.9 8.2-4.5 3.8-10.1-4.5-5.6-14.1-6.5-15.8-.5z" class="st39" fill="#625d28"/><circle r="1.7" cy="57.765686" cx="126.09963" fill="#99988c"/><path d="M17.39963 115.26569s.8 3.9 1.1 6.3c.3 2.4.9 3.8 5.9 3.2 5-.6 4.9-1.5 5.1-6.4.2-4.9-.1-7.4-3.7-7.6-3.6-.2-9.1.7-8.4 4.5z" class="st33" fill="#56606b"/><path fill="#3a434e" class="st34" d="M11.19963 40.565685c-2.7000002 5.1-2.7000002 7.7-.5 8.5 2.2.8 4.1.7 6.4-3 0 0 2 .7 4.9-4.1.9-1.5-.7-2.6-.7-2.6s-4.8 1.3-7.1-5l-3 6.2z"/></svg> \ No newline at end of file diff --git a/app/javascript/flavours/glitch/images/elephant_ui_working.svg b/app/javascript/flavours/glitch/images/elephant_ui_working.svg new file mode 100644 index 000000000..8ba475db0 --- /dev/null +++ b/app/javascript/flavours/glitch/images/elephant_ui_working.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 124.12477 127.91685" width="124.12476" height="127.91685"><path d="M72.584191 46.815676c-2.3-2.2-4.2-2.5-6.6-.6-2.4 1.9-2.1 4.8.9 7.6 3.1 2.9 4.7 4.1 6.7 5 2.1.9 5.4 2.5 10.5-2s10.2-11.1 9.4-14.7c-.8-3.6-4.1-1.8-6.8 1.2s-3.7 4-5.4 5.2c-1.5 1.3-3.8 3-8.7-1.7z" class="st0" style="fill:#93a1b5;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M116.384191 75.015676c0 6.3-3.9 9.8-9.1 9.8-5.3 0-9.9-3.5-9.9-9.8 0-6.3 4.3-10.3 9.5-10.3s9.5 4 9.5 10.3z" style="fill:#3a434e;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M54.184191 16.615676c-23 1.2-30.5 14.1-32.8 27.8-3 18.2-8.2 44.2-9.2 53.2s-1 16 6 22 11 5 23 7 19 0 20-8l16.8-1.1s14.5 5.5 18.8 6.9c4.3 1.4 10.6.5 12.1-7.1s.2-12.5-6.6-14.4c-6.8-1.9-10.6-2.9-10.6-2.9l4.4-30.1s17.4 1.6 22.6-20c0 0 3.9 1.1 4.8-2.8.9-3.9-2.6-6.2-5.6-4.8l-2.5-1s-.2-3.8-3.5-4.2c-2.1-.2-6 3.4-3 7.4 0 0-3.4 8.9-12 7.8-8.6-1.1-12.5-11.2-15-18.2s-10.7-18.3-27.7-17.5z" class="st2" style="fill:#56606b;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M95.484191 69.915676c-.6 0-1.2 0-1.8-.1-4.2-.2-10.9-2.4-17-7.8-.7-1-.4-2-.2-2.5.5-1.1 1.7-1.8 3-1.8.8 0 1.5.3 2.2.8 3 2.2 7.8 5.1 13.8 5.1.9 0 1.8-.1 2.7-.2 7.2-1 12.1-5.8 14.3-9.9.6-1.2 1.3-2.5 1.8-3.5.2-.5.3-.7.6-.9.3-.2 1 .2 1 .2l2.1.8c-4.5 17.8-17.4 19.2-21.2 19.2h-1.3v.6z" class="st3" style="fill:#3a434e;opacity:.98;fill-opacity:1"/><path d="M48.884191 126.915676c-2.2 0-4.7-.2-7.6-.7-2.8-.5-5.1-.8-7.1-1-6.9-.9-10.3-1.3-15.6-5.9-7-6-6.8-13-5.8-21.6.3-2.3.8-5.9 1.7-11.2 3.1 1.4 6.1 2.2 8.7 2.2 3.1 0 5.4-1.2 6.6-3.4 1.6 1.9 6.9 7.3 13.3 7.3 1 0 1.9-.1 2.8-.4 3.5-1 19.8-2.1 46.9-3.4l-1.7 11.7.4.1s3.8 1 10.6 2.9c6.1 1.7 7.9 5.6 6.3 13.8-1.3 6.6-6.2 7.3-8.2 7.3-1.1 0-2.2-.2-3.3-.5-4.2-1.4-18.6-6.8-18.7-6.9h-.1l-17.3 1.2-.1.4c-.7 5.4-4.5 8.1-11.8 8.1z" class="st3" style="fill:#3a434e;fill-opacity:1"/><path d="M41.184191 103.415676c-3.8-1.4-6-1.4-7.7-1.4-1.8 0-4.6 3.3 1.4 5.4 6 2.1 10.3 3.4 10.3 3.4s1.8-2.1 3.5-2.9c1.6-.8 2.3-.9 2.3-.9l-9.8-3.6z" style="fill:#56606b;fill-opacity:1"/><path d="M27.584191 38.615676c1.2-5-2.1-8.2-5.7-9.2-3.5-1-8.4-1.7-13.9 6.9s-9.5 16.5-6.4 20.6c3.1 4.1 9.3 3.4 11.8-.8 0 0 5.7 3.8 9.5-4.2" class="st2" style="fill:#56606b;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M10.884191 45.115676c-1.6 2.5-.8 5 2 5.9 2.7 1 5-1.5 6.5-3.8 1.6-2.3 3.6-5.9 3.6-5.9s-3.7 1.2-5.6-.2c-2-1.4-1.5-3.8-1.5-3.8l-5 7.8z" class="st3" style="fill:#3a434e;fill-opacity:1"/><path d="M22.684191 41.415676c-2.6 1.1-6.8.6-6.9-4.1 0 0-5.1 7.6-5.9 9.6" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M67.584191 5.215676c0-3.4-3.9-2.6-3.9-2.6 0-1.2-2-3.5-8.5-.6-6.4 2.9-7.3 6-7.3 6-3.8-1.7-9.6-2.6-13.5.8-3.9 3.4-4.3 10 2.3 13.5 0 0 2.9.9 7.7-.4 4.8-1.3 7.7-3.3 7.7-3.3s3.7 2.3 9 .6c5.3-1.7 9.9-4.5 10.3-10.1.5-5.7-3.8-3.9-3.8-3.9z" style="fill:#56606b;fill-opacity:1"/><path d="M67.084191 16.315676c-1-5.5-7-3-7-3 .5-2.1-3-4.1-5.5-2.7-2.5 1.4-6.6-.1-6.6-.1-6.4-4.4-14.3-2.1-16.1 2-1.1 3.3.2 7.3 4.8 9.7 0 0 2.9.9 7.7-.4 4.8-1.3 7.7-3.3 7.7-3.3s3.7 2.3 9 .6c2.3-.6 4.3-1.5 6-2.8 0 .1 0 0 0 0z" style="fill:#3a434e;fill-opacity:1"/><path d="M36.684191 22.715676c-.1 0-.2 0-.2-.1-3.1-1.6-5-4.1-5.4-7-.3-2.7.8-5.4 3-7.3 3.9-3.3 9.5-2.8 13.6-1.1.5-1.1 2.2-3.5 7.3-5.8 4.5-2 6.9-1.5 8-.8.6.4.9.9 1.1 1.3.7-.1 2-.1 3 .7.5.4.9 1 1 1.8.7-.1 1.8-.2 2.7.4 1 .7 1.4 2.1 1.2 4.1-.4 5-3.9 8.5-10.7 10.6-5.5 1.7-9.3-.6-9.4-.7-.2-.1-.3-.5-.2-.7.1-.2.5-.3.7-.2 0 0 3.6 2.2 8.6.6 6.3-2 9.6-5.1 10-9.7.1-1.6-.2-2.8-.8-3.3-.9-.7-2.3-.1-2.3-.1-.2.1-.3 0-.5 0-.1-.1-.2-.2-.2-.4 0-.8-.2-1.3-.6-1.7-.9-.8-2.6-.4-2.7-.4-.1 0-.3 0-.4-.1-.1-.1-.2-.2-.2-.4 0-.3-.2-.7-.7-1-.6-.4-2.6-1.1-7.1.8-6.1 2.7-7 5.6-7 5.7 0 .1-.1.3-.3.3-.1.1-.3.1-.4 0-3.9-1.7-9.3-2.4-13 .8-1.9 1.7-2.9 4.1-2.6 6.4.3 2.5 2 4.7 4.8 6.2.2.1.3.4.2.7-.1.3-.3.4-.5.4z"/><path d="M40.584191 84.115676s6.3 16.8 7.1 19.3c.8 2.5 1.8 3.4 7.3 3 5.5-.4 6.7-21.5 6.7-21.5l-21.1-.8z" style="fill:#191b22;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M51.084191 103.415676c-1.7-2.1-1.9-4.2-1.9-4.2l2-10.9 3-1.4-3.1 16.5zm33.9-35.3l-23.9 1.9 1.2 8 25.2 1.1 4.6-9c-2.3-.3-4.7-.9-7.1-2z" class="st9" style="fill:#191b22;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M28.484191 82.915676c7.2 9.4 12.7 11.4 21.8 7.7 8.5-3.4 15.4-9 15.1-15-.3-6-2.1-10.3-9.1-9.8-2.3.2-6.8 2.8-9.6 4.4-1.8 1-4.2 2.2-6 .4-1.8-1.8-4.3-4.4-4.3-4.4" class="st2" style="fill:#56606b;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M49.284191 80.515676c-.3-.2-.5-.4-.7-.6-1.2.7-2.3 1.3-2.8 1.6-2 1.2-3.8.5-4.7-.3-.9-.9-2.3-2.4-5.5-1.5-3.7 1-4.5 5.7-2.5 8.4 6.5 6.1 12.8 4.1 15.2 3.3 2.4-.8 6.3-2.7 6.3-2.7l.6-6c-2-.8-4.1-.9-5.9-2.2z" class="st3" style="fill:#3a434e;fill-opacity:1"/><path d="M28.484191 82.915676c7.2 9.4 12.7 11.4 21.8 7.7 8.5-3.4 15.4-9 15.1-15-.3-6-2.1-10.3-9.1-9.8-2.3.2-6.8 2.8-9.6 4.4-1.8 1-4.2 2.2-6 .4-1.8-1.8-4.3-4.4-4.3-4.4m35.4-8.6c6.5 8.3 15.5 12.5 21.8 12.7" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M53.184191 104.415676c-1.6.1-2.7-1.1-2.4-2.7l4.9-25.9c.3-1.6 1.9-3 3.6-3.1l26.9-1.7c1.6-.1 3.6-1.4 4.4-2.9l.7-1.3c.7-1.5 2.7-2.8 4.4-2.9l4.5-.3c1.6-.1 3.1 1.1 3.3 2.8v.2c.2 1.6.5 3.7.7 4.6.2.9.3 3 .1 4.6l-2.2 21.3c-.2 1.6-1.7 3.1-3.3 3.3l-45.6 4z" style="fill:#191b22;fill-opacity:1"/><path d="M53.184191 104.415676c-1.6.1-2.7-1.1-2.4-2.7l4.9-25.9c.3-1.6 1.9-3 3.6-3.1l26.9-1.7c1.6-.1 3.6-1.4 4.4-2.9l.7-1.3c.7-1.5 2.7-2.8 4.4-2.9l4.5-.3c1.6-.1 3.1 1.1 3.3 2.8v.2c.2 1.6.5 3.7.7 4.6.2.9.3 3 .1 4.6l-2.2 21.3c-.2 1.6-1.7 3.1-3.3 3.3l-45.6 4z" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M55.684191 105.915676c-1.6.1-2.3-.4-2-2l4.4-25.6c.3-1.6 1.9-3 3.6-3.1l26.9-1.7c1.6-.1 3.6-1.4 4.4-2.9l.7-1.3c.7-1.5 2.7-2.8 4.4-2.9l4.5-.3c1.6-.1 3.1 1.1 3.3 2.8v.2c.2 1.6 1.3 2.9 2.5 2.8 1.2-.1 1.9 1.2 1.6 2.8l-5.2 24.9c-.3 1.6-2 3.1-3.6 3.2l-45.5 3.1z" style="fill:#191b22;fill-opacity:1"/><path d="M53.184191 104.315676l4.9-26c.3-1.6 1.9-3 3.6-3.1l26.9-1.7c1.6-.1 3.6-1.4 4.4-2.9l.7-1.3c.7-1.5 2.7-2.8 4.4-2.9l4.5-.3c1.6-.1 3.1 1.1 3.3 2.8v.2c.2 1.6 1.3 2.9 2.5 2.8 1.2-.1 1.9 1.2 1.6 2.8l-5.2 24.9c-.3 1.6-2 3.1-3.6 3.2l-46.7 3.7m9.2-103.9c-.3 2.9-2.9 4.9-4.1 5.8m8-3.2c-.7 3.5-4 6-4 6" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M39.884191 53.615676c-2.3-2.2-4.2-2.5-6.6-.6-2.4 1.9-2.1 4.8.9 7.6 3.1 2.9 4.7 4.1 6.7 5 2 .9 5.4 2.5 10.5-2s10.2-11.1 9.4-14.7c-.8-3.6-4.1-1.8-6.8 1.2s-3.7 4-5.4 5.2c-1.7 1.2-3.8 3-8.7-1.7z" class="st0" style="fill:#93a1b5;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M44.384191 61.315676c-2.3 0-4.7-1.2-6.6-3.1-.9-.9-1.1-2-.7-2.9.3-.8 1.1-1.3 1.8-1.3.2 0 .5 0 .7.1 2.3 2.1 4.2 3.2 5.9 3.2 1.6 0 2.7-.8 3.5-1.4 1.7-1.3 2.8-2.3 5.5-5.3.9-1.1 1.9-1.9 2.7-2.4.3.2.6.4.7.8.2.8-.2 2-.7 2.7-.9 1.3-4.9 5.4-9 8.4-1.1.7-2.4 1.2-3.8 1.2z" style="fill:#b3bfcd;fill-opacity:1"/><path d="M45.784191 50.115676c-.7 0-1.4-.6-1.4-1.4v-6.1c0-.7.6-1.4 1.4-1.4.7 0 1.4.6 1.4 1.4v6.1c0 .8-.6 1.4-1.4 1.4z"/><path d="M61.184191 118.215676c.7-7.1-3.5-10.6-9.2-11.1-5.7-.5-10.2 6.8-9.1 13.1 1.1 6.3 6.7 7.2 6.7 7.2" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M52.084191 107.515676c-2.2-.7-4.3-1.4-6.5-2.2-2.1-.8-4.3-1.5-6.4-2.3-.1 0-.2-.2-.1-.3 0-.1.2-.2.3-.2 2.2.6 4.4 1.3 6.5 1.9 2.2.7 4.3 1.3 6.5 2 .3.1.4.4.3.6-.1.4-.4.6-.6.5zm25.4 10.1c-.2-1.4-.2-2.9.1-4.2.2-1.4.6-2.7 1.1-4-.3 1.3-.5 2.7-.6 4.1 0 1.4.1 2.7.4 4 .1.3-.1.5-.3.6-.2.1-.6-.1-.7-.5 0 .1 0 .1 0 0z"/><path d="M104.284191 103.615676c-3.6-.7-8.5 2.1-9.5 9.7s2.1 10.7 5.3 11.6m15.1-83.5l-.39999 1.4m-1.90001-1.2c2.4 1.7 6.4 3.4 6.4 3.4m-1.6-2.6l-.60001 1.59999" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M47.484191 79.215676c3.2 2.7 7 3.3 7 3.3" style="fill:none;stroke:#000;stroke-miterlimit:10"/><path d="M69.284191 24.315676c-3.5.4-2.7 2.9-1.2 3.5 1.5.6 3.7.1 4.3-1.6.4-1.6-1.3-2.1-3.1-1.9z" style="fill:#4f5862;fill-opacity:1"/></svg> \ No newline at end of file diff --git a/app/javascript/flavours/glitch/reducers/timelines.js b/app/javascript/flavours/glitch/reducers/timelines.js index 679e1601e..4c62d8df3 100644 --- a/app/javascript/flavours/glitch/reducers/timelines.js +++ b/app/javascript/flavours/glitch/reducers/timelines.js @@ -30,7 +30,7 @@ const initialTimeline = ImmutableMap({ items: ImmutableList(), }); -const normalizeTimeline = (state, timeline, statuses, next) => { +const normalizeTimeline = (state, timeline, statuses, next, isPartial) => { const oldIds = state.getIn([timeline, 'items'], ImmutableList()); const ids = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId)); const wasLoaded = state.getIn([timeline, 'loaded']); @@ -41,6 +41,7 @@ const normalizeTimeline = (state, timeline, statuses, next) => { mMap.set('isLoading', false); if (!hadNext) mMap.set('next', next); mMap.set('items', wasLoaded ? ids.concat(oldIds) : ids); + mMap.set('isPartial', isPartial); })); }; @@ -125,7 +126,7 @@ export default function timelines(state = initialState, action) { case TIMELINE_EXPAND_FAIL: return state.update(action.timeline, initialTimeline, map => map.set('isLoading', false)); case TIMELINE_REFRESH_SUCCESS: - return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next); + return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial); case TIMELINE_EXPAND_SUCCESS: return appendNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next); case TIMELINE_UPDATE: diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index 8f051f7a0..8f06209c6 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -838,21 +838,10 @@ } .missing-indicator { - text-align: center; - font-size: 16px; - font-weight: 500; - color: lighten($ui-base-color, 16%); - background: $ui-base-color; - cursor: default; - display: flex; - flex: 1 1 auto; - align-items: center; - justify-content: center; + padding-top: 20px + 48px; - & > div { - background: url('~images/mastodon-not-found.png') no-repeat center -50px; - padding-top: 210px; - width: 100%; + .regeneration-indicator__figure { + background-image: url('~flavours/glitch/images/elephant_ui_disappointed.svg'); } } @@ -1162,6 +1151,7 @@ noscript { @import 'metadata'; @import 'composer'; @import 'columns'; +@import 'regeneration_indicator'; @import 'search'; @import 'emoji'; @import 'doodle'; diff --git a/app/javascript/flavours/glitch/styles/components/regeneration_indicator.scss b/app/javascript/flavours/glitch/styles/components/regeneration_indicator.scss new file mode 100644 index 000000000..9c1873cdf --- /dev/null +++ b/app/javascript/flavours/glitch/styles/components/regeneration_indicator.scss @@ -0,0 +1,53 @@ +.regeneration-indicator { + text-align: center; + font-size: 16px; + font-weight: 500; + color: lighten($ui-base-color, 16%); + background: $ui-base-color; + cursor: default; + display: flex; + flex: 1 1 auto; + align-items: center; + justify-content: center; + padding: 20px; + + & > div { + width: 100%; + background: transparent; + padding-top: 0; + } + + &__figure { + background: url('~flavours/glitch/images/elephant_ui_working.svg') no-repeat center 0; + width: 100%; + height: 160px; + background-size: contain; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + + &.missing-indicator { + padding-top: 20px + 48px; + + .regeneration-indicator__figure { + background-image: url('~flavours/glitch/images/elephant_ui_disappointed.svg'); + } + } + + &__label { + margin-top: 200px; + + strong { + display: block; + margin-bottom: 10px; + color: lighten($ui-base-color, 34%); + } + + span { + font-size: 15px; + font-weight: 400; + } + } +} diff --git a/app/javascript/flavours/glitch/util/bio_metadata.js b/app/javascript/flavours/glitch/util/bio_metadata.js index 599ec20e2..3c9c2b8b1 100644 --- a/app/javascript/flavours/glitch/util/bio_metadata.js +++ b/app/javascript/flavours/glitch/util/bio_metadata.js @@ -97,8 +97,8 @@ const rexstr = exp => '(?:' + exp.source + ')'; const DOCUMENT_START = /^/; const DOCUMENT_END = /$/; const ALLOWED_CHAR = unirex( // `c-printable` in the YAML 1.2 spec. - compat_mode ? '[\t\n\r\x20-\x7e\x85\xa0-\ufffd]' : '[\t\n\r\x20-\x7e\x85\xa0-\ud7ff\ue000-\ufffd\u{10000}-\u{10FFFF}]' - ); + compat_mode ? '[\t\n\r\x20-\x7e\x85\xa0-\ufffd]' : '[\t\n\r\x20-\x7e\x85\xa0-\ud7ff\ue000-\ufffd\u{10000}-\u{10FFFF}]' +); const WHITE_SPACE = /[ \t]/; const LINE_BREAK = /\r?\n|\r|<br\s*\/?>/; const INDICATOR = /[-?:,[\]{}&#*!|>'"%@`]/; diff --git a/app/javascript/flavours/glitch/util/url_regex.js b/app/javascript/flavours/glitch/util/url_regex.js index e676d1879..faed22169 100644 --- a/app/javascript/flavours/glitch/util/url_regex.js +++ b/app/javascript/flavours/glitch/util/url_regex.js @@ -40,7 +40,7 @@ export const urlRegex = (function() { regexen.validSubdomain = regexSupplant(/(?:(?:#{validDomainChars}(?:[_-]|#{validDomainChars})*)?#{validDomainChars}\.)/); regexen.validDomainName = regexSupplant(/(?:(?:#{validDomainChars}(?:-|#{validDomainChars})*)?#{validDomainChars}\.)/); regexen.validGTLD = regexSupplant(RegExp( - '(?:(?:' + + '(?:(?:' + '삼성|닷컴|닷넷|香格里拉|餐厅|食品|飞利浦|電訊盈科|集团|通販|购物|谷歌|诺基亚|联通|网络|网站|网店|网址|组织机构|移动|珠宝|点看|游戏|淡马锡|机构|書籍|时尚|新闻|政府|' + '政务|手表|手机|我爱你|慈善|微博|广东|工行|家電|娱乐|天主教|大拿|大众汽车|在线|嘉里大酒店|嘉里|商标|商店|商城|公益|公司|八卦|健康|信息|佛山|企业|中文网|中信|世界|' + 'ポイント|ファッション|セール|ストア|コム|グーグル|クラウド|みんな|คอม|संगठन|नेट|कॉम|همراه|موقع|موبايلي|كوم|كاثوليك|عرب|شبكة|' + @@ -131,7 +131,7 @@ export const urlRegex = (function() { 'academy|abudhabi|abogado|able|abc|abbvie|abbott|abb|abarth|aarp|aaa|onion' + ')(?=[^0-9a-zA-Z@]|$))')); regexen.validCCTLD = regexSupplant(RegExp( - '(?:(?:' + + '(?:(?:' + '한국|香港|澳門|新加坡|台灣|台湾|中國|中国|გე|ไทย|ලංකා|ഭാരതം|ಭಾರತ|భారత్|சிங்கப்பூர்|இலங்கை|இந்தியா|ଭାରତ|ભારત|ਭਾਰਤ|' + 'ভাৰত|ভারত|বাংলা|भारोत|भारतम्|भारत|ڀارت|پاکستان|مليسيا|مصر|قطر|فلسطين|عمان|عراق|سورية|سودان|تونس|' + 'بھارت|بارت|ایران|امارات|المغرب|السعودية|الجزائر|الاردن|հայ|қаз|укр|срб|рф|мон|мкд|ею|бел|бг|ελ|' + @@ -169,7 +169,7 @@ export const urlRegex = (function() { ')' + ')' + '\\)' - , 'i'); + , 'i'); // Valid end-of-path chracters (so /foo. does not gobble the period). // 1. Allow =&# for empty URL parameters and other URL-join artifacts regexen.validUrlPathEndingChars = regexSupplant(/[^#{spaces_group}\(\)\?!\*';:=\,\.\$%\[\]#{pd}~&\|@]|(?:#{validUrlBalancedParens})/i); @@ -191,6 +191,6 @@ export const urlRegex = (function() { '(\\/#{validUrlPath}*)?' + // $5 URL Path '(\\?#{validUrlQueryChars}*#{validUrlQueryEndingChars})?' + // $6 Query String ')' - , 'gi'); + , 'gi'); return regexen.validUrl; }()); diff --git a/app/javascript/images/clippy_frame.png b/app/javascript/images/clippy_frame.png new file mode 100644 index 000000000..7f2cd6a59 --- /dev/null +++ b/app/javascript/images/clippy_frame.png Binary files differdiff --git a/app/javascript/images/clippy_wave.gif b/app/javascript/images/clippy_wave.gif new file mode 100644 index 000000000..4d2e38a3d --- /dev/null +++ b/app/javascript/images/clippy_wave.gif Binary files differdiff --git a/app/javascript/images/elephant-friend.png b/app/javascript/images/elephant-friend.png deleted file mode 100644 index 3c5145ba9..000000000 --- a/app/javascript/images/elephant-friend.png +++ /dev/null Binary files differdiff --git a/app/javascript/images/elephant_ui_disappointed.svg b/app/javascript/images/elephant_ui_disappointed.svg new file mode 100644 index 000000000..580c15a13 --- /dev/null +++ b/app/javascript/images/elephant_ui_disappointed.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="134.11569" width="134.61565" viewBox="0 0 134.61565 134.11569"><path d="M82.69963 103.86569c6.8 1.5 11 2.4 11.3-6.200005.3-8.6-1.8-17.3-1.8-17.3l-13.6 1.1 4.1 22.400005z" class="st32" fill="#3a434e" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M65.39963 112.96569c-.2 10.3-.6 17.5 6.5 17.4 7.1-.1 12.6 1.1 13.6-5.3 1.1-6.3 1.9-20.6.7-28.000005" class="st32" fill="#3a434e" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M86.39963 97.66569c-1.4-7.5-4.1-23.2-4.1-23.2s13.2-1.5 10.4-13c-2.7-11.4-7.5-22.6-11-31.1s-14.5-16.9-28.6-15.7c-19.2 1.6-25.6 7-31.6 23.1-5.4 14.4-10.4 47.2-8.9 63.3.8 8.7 5 13.7 14.4 13.5 9.4-.2 39.8-.8 49.8-2.8.3-.1.6-.1.9-.2" class="st33" fill="#56606b"/><path d="M85.89963 97.76569l-4.1-23.2c0-.3.1-.5.4-.6 2.6-.4 5.3-1.4 7.3-3.1 1-.8 1.9-1.9 2.4-3.1.5-1.2.7-2.5.6-3.9 0-1.3-.4-2.6-.7-4-.3-1.3-.7-2.7-1.1-4-.8-2.7-1.7-5.3-2.6-7.9-1.9-5.2-4-10.4-6.1-15.5-.5-1.3-1-2.6-1.7-3.8-.6-1.2-1.4-2.3-2.3-3.4-1.7-2.1-3.8-4-6-5.5-4.6-3-10-4.7-15.4-4.9-2.7-.1-5.5.3-8.2.6-2.7.4-5.5.9-8.1 1.7-2.6.8-5.1 1.9-7.3 3.5s-4.1 3.6-5.6 5.8c-1.5 2.3-2.8 4.7-3.9 7.3-.6 1.3-1.1 2.5-1.6 3.8-.4 1.3-.9 2.6-1.3 3.9-1.6 5.3-2.8 10.7-3.9 16.1-1 5.4-1.9 10.9-2.6 16.4-.7 5.5-1.2 11-1.3 16.6-.1 2.8-.1 5.5.1 8.3.1 2.8.5 5.5 1.6 8 1 2.5 2.9 4.6 5.4 5.7 2.4 1.1 5.2 1.3 8 1.3 5.6-.1 11.1-.2 16.7-.4 11.1-.4 22.2-.8 33.2-2.3.1 0 .2.1.2.2s0 .2-.1.2c-2.7.9-5.5 1.2-8.3 1.4-2.8.2-5.6.5-8.3.6-5.6.3-11.1.6-16.7.7-5.6.2-11.1.3-16.7.4-2.8.1-5.7-.1-8.4-1.3s-4.7-3.5-5.8-6.2c-1.1-2.6-1.5-5.5-1.6-8.3-.2-2.8-.2-5.6-.1-8.4.2-5.6.7-11.1 1.3-16.7.7-5.5 1.5-11 2.6-16.5s2.3-10.9 3.9-16.3c.4-1.3.9-2.7 1.3-4 .5-1.3 1-2.6 1.6-3.9 1.1-2.6 2.4-5.1 4-7.4 1.6-2.3 3.6-4.4 5.9-6.1 2.3-1.7 4.9-2.8 7.6-3.7 2.7-.8 5.5-1.4 8.2-1.7 2.8-.3 5.5-.7 8.4-.6 5.6.2 11.2 1.9 15.9 5 2.4 1.6 4.5 3.5 6.3 5.7.9 1.1 1.7 2.3 2.4 3.5.7 1.3 1.2 2.6 1.7 3.9 2.1 5.1 4.2 10.3 6.1 15.5.9 2.6 1.8 5.3 2.6 7.9.4 1.3.8 2.7 1.1 4 .3 1.3.7 2.7.8 4.2.1 1.4-.1 2.9-.7 4.3s-1.5 2.5-2.6 3.5c-2.3 1.9-5 2.8-7.9 3.3l.4-.6 4.1 23.2c0 .3-.1.5-.4.6-.3.1-.7.5-.7.2z"/><path d="M26.49963 114.06569c-4.7 0-7.4-2.1-10-4.4-2.3-2-3.2-4.6-3.4-8.6-.1-2.700005-.6-10.000005.4-18.800005 3.8.9 9.7 3.8 13.4 7.6 5.6 5.7 17.7 6.3 22.7 6.3h1.8l.1-.4s.5-2.6 1.8-5.2l.3-.6-.7-.1c-.4-.1-10.9-1.9-9.7-10.8.7-4.9 13.3-7.9 33.9-7.9 2.2 0 3.8 0 4.2.1l3.5 2.2c-1.5.5-2.6.6-2.6.6l-.5.1.1.5c0 .2 2.8 16.4 4.1 24 0 0-7.9 13.100005-8 13.000005-.1-.1-.3-.1-.3-.1-.3 0-.7.1-.9.1-9.9 1.7-39.6 2.4-49.3 2.6l-.9-.2z" class="st34" fill="#3a434e"/><path d="M45.89963 51.36569c-.7 0-1.4-.6-1.4-1.4v-5.1c0-.7.6-1.4 1.4-1.4.7 0 1.4.6 1.4 1.4v5.1c-.1.8-.7 1.4-1.4 1.4z"/><path d="M72.89963 30.365685c-3.5.4-2.7 2.9-1.2 3.5 1.5.6 3.7.1 4.3-1.6.4-1.6-1.3-2.1-3.1-1.9z" class="st35" fill="#4f5862"/><path d="M44.29963 53.965685c-.4.7-1.5.2-2.7-.6-1.2-.8-2.1-1.5-1.6-2.2.4-.7 1.6-.4 2.8.4 1.2.8 2 1.7 1.5 2.4z" class="st34" fill="#4f5862"/><path d="M27.29963 36.165685c0-5.6-3.7-9.4-7.9-9.8-4.2-.4-9-.3-14.0000002 11.3-5.00000001 11.6-6.7 15.7-2.6 17.9 4.1 2.2 9.5000002 1.5 11.3000002-1.4 0 0 5.3 3.8 9.7-3.8" class="st36" fill="#56606b" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M11.19963 40.565685c-2.7000002 5.1-2.7000002 7.7-.5 8.5 2.2.8 4.1.7 6.4-3 0 0 2 .7 4.9-4.1.9-1.5-.7-2.6-.7-2.6s-4.8 1.3-7.1-5l-3 6.2z" class="st34" fill="#3a434e" fill-opacity="0"/><path d="M9.7996298 43.365685l4.4000002-9s1.8 6.3 7.8 4.9" class="st7" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M27.89963 67.365685c-4.9.8-9.7 4.5-9.3 15.7.4 11.2.5 18.700005 6.1 20.000005 5.5 1.3 13.8.3 14.1-7.100005.3-7.4.3-16.1.3-16.1" class="st36" fill="#53606c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M28.69963 102.96569c-1.4 0-2.8-.2-4.1-.5-1.2-.3-2.2-.9-3-2 .5.2 1.1.3 1.7.3 1.2 0 5.2-.5 5.8-7.200005.7-7.4 2.8-10.9 6.6-10.9.8 0 1.6.1 2.6.4 0 3.4-.1 8.3-.2 12.7-.2 6.700005-7.2 7.200005-9.4 7.200005z" class="st34" fill="#3a434e"/><path d="M50.69963 18.965685c-5.2 2.9-14.6 4.7-18.1-1.5-3-5.4 2.1-9.6999996 7.8-9.9999996 5.7-.3 7.6 1.2 7.6 1.2s1.9-5.9 9.3-7.69999998c3.9-1 6-.1 6.2 1.19999998 0 0 3.6-.9 4 3.5 0 0 3.9-.4 3.1 5.1999996-.8 5.6-10.6 10.1-17.7 6.4 0 0-1.1 1.2-2.2 1.7z" class="st33" fill="#56606b"/><path d="M40.79963 21.665685c-2.7 0-4.8-.9-6.3-2.3-.7-1.1-.8-2.9-.3-4.3.8-1.9 2.6-3.3 4.6-3.7 1.2-.2 2.6-.4 3.9-.4 3.3 0 6.2.8 7.3 1.9l.6.6.3-.7s.7-2 2.2-2c.2 0 .5.1.8.2 2.2.9 3.5 1.2 4.6 1.2.5 0 .9-.1 1.3-.2.1-.1.4-.1.6-.1.6 0 1.5.3 1.8.8.2.3.2.6.1 1l-.2.6h.7c.4 0 1.4.2 1.8.9.2.4.2 1-.2 1.7-1.8.8-3.8 1.2-5.7 1.2-2 0-4 0-5.6-.8 0 0-1.2 1.3-2.2 1.8-3.1 1.6-7 2.6-10.1 2.6z" class="st34" fill="#3a434e" fill-opacity=".94117647"/><path d="M61.79963 18.66569c-3.1.5-6.3.1-8.9-1.5.7.2 1.5.4 2.2.5.7.2 1.4.2 2.2.3.7.1 1.4 0 2.2 0 .7-.1 1.4-.1 2.2-.2h.1c.3 0 .5.1.6.4-.1.2-.3.5-.6.5z"/><path d="M37.59963 21.26569c-2.4-.4-4.8-2.1-5.7-4.5-.5-1.2-.7-2.6-.3-3.9.3-1.3 1.1-2.4 2.1-3.3 2-1.7 4.6-2.5 7.1-2.6 1.3-.1 2.5 0 3.8.1.6.1 1.3.2 1.9.4.6.2 1.2.4 1.9.8l-.8.2c.6-1.6 1.6-3 2.8-4.2 1.2-1.2 2.6-2.2 4.1-2.9 1.5-.7 3.2-1.1 4.8-1.3.8-.1 1.7-.1 2.6.1.4.1.9.3 1.3.6s.7.8.8 1.3l-.6-.4c.6-.1 1.2-.1 1.7 0 .6.1 1.1.4 1.6.8.4.4.7.9.9 1.5.1.3.2.5.2.8l.1.8-.5-.4c1 0 1.9.3 2.6.9.7.7 1 1.6 1.1 2.5.1.9 0 1.7-.1 2.5-.2.9-.5 1.7-1 2.4-.9 1.4-2.2 2.5-3.7 3.4-1.4.9-3 1.4-4.6 1.8-.3.1-.5-.1-.6-.4-.1-.3.1-.5.4-.6 1.5-.3 3-.9 4.3-1.7 1.3-.8 2.5-1.8 3.3-3.1.4-.6.7-1.3.8-2 .1-.7.2-1.5.1-2.2-.1-.7-.3-1.4-.8-1.9-.5-.4-1.2-.7-1.8-.7-.3 0-.5-.2-.5-.4l-.1-.7c-.1-.2-.1-.4-.2-.7-.2-.4-.4-.8-.7-1.1-.3-.3-.7-.5-1.1-.6-.4-.1-.9-.1-1.3 0-.3.1-.5-.1-.6-.4-.1-.5-.7-.9-1.4-1.1-.7-.2-1.5-.2-2.2-.1-1.5.2-3.1.6-4.5 1.2-1.4.7-2.7 1.6-3.8 2.7-1.1 1.1-2 2.5-2.5 3.8-.1.3-.4.4-.6.3h-.1c-.4-.2-1-.5-1.5-.6-.6-.1-1.2-.2-1.7-.3-1.2-.1-2.4-.2-3.6-.1-2.4.1-4.7.8-6.5 2.3-.9.7-1.6 1.7-1.9 2.8-.3 1.1-.2 2.3.2 3.4s1.1 2.1 1.9 2.9c.6.9 1.7 1.5 2.9 1.9z"/><path d="M63.49963 2.1656854c0 3.5-2.6 5.5-4.3 6.1m8.3-2.6c.2 3.4-3.3 5.1999996-3.3 5.1999996" class="st7" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M90.29963 84.765685c2.6 2.3 3 4.3-2.4 4.8-5.3.5-25.7 2.4-28.2 2.6-2.4.3-3.4 1.7-3.4 2.8 0 1.1.5 3.2 4 3.1 3.4-.1 23.8-1.5 30.4-2.4 6.6-.8 14.4-2.4 13.4-9s-5.4-8.7-5.4-8.7l-8.4 6.8z" class="st37" fill="#737039" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M90.29963 84.765685c2.6 2.3 3 4.3-2.4 4.8-5.3.5-25.7 2.4-28.2 2.6-2.4.3-3.4 1.7-3.4 2.8 0 1.1.5 3.2 4 3.1 3.4-.1 23.8-1.5 30.4-2.4 6.6-.8 13.8-2.3 13.4-9-.3-5.5-3.1-7-4.4-8.1-.5-.1-1-.1-1.6-.2l-7.8 6.4z" fill="#625d28" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M102.69963 64.665685c5.4-.1 10.3-1.9 12.2-6.5 1.9-4.6 8.7-10.1 14.2-2.1 5.4 8.1 6.6 17.3 2.8 23.7-3.8 6.5-12.1 3.5-14.9-.5-2.7-4-8.6-2.9-14.5-2.7-5.9.2.2-11.9.2-11.9z" class="st37" fill="#737039" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M65.89963 54.865685s10.2 21.3 13.5 26.8c3.2 5.5 12.9 6.2 17.4 3.5 4.5-2.7 7.3-7.3 8-15.1.7-7.9-2.4-14.9-10-15.2-7.6-.3-11.9 7.6-12.1 13.7" class="st36" fill="#53606c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M65.89963 54.865685s10.2 21.3 13.5 26.8c3.2 5.5 12.9 6.2 17.4 3.5 4.5-2.7 7.3-7.3 8-15.1.7-7.9-2.4-14.9-10-15.2-7.6-.3-11.9 7.6-12.1 13.7" class="st36" fill="#56606b" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M90.19963 86.165685c-3.7 0-8.3-1.3-10.4-4.8-.9-1.5-2.4-4.3-4.4-8.4l5.9-.1c4 7.4 5.9 9.8 8 9.8 3.9 0 6-3.4 6.9-9.5.2-1.2.3-2.3.4-3.4.5-4.6.9-7.2 3.4-7.5.3 0 .6-.1.9-.1 2.1 0 2.5 1.2 3.1 2.8.1.2.2.5.2.7.1 1.3.1 2.7 0 4.2-.7 7.3-3.1 11.9-7.7 14.7-1.6 1-3.9 1.6-6.3 1.6z" class="st34" fill="#3a434e"/><path d="M89.19963 63.86569l-.3 6.6c-.1 1.1-.2 2.2-.4 3.3-.1.6-.3 1.1-.5 1.7-.3.5-.6 1.1-1.2 1.5-.2.1-.5.1-.7-.2-.1-.2-.1-.5.2-.7.7-.4 1.1-1.5 1.3-2.5.2-1 .4-2.1.5-3.2.2-2.2.3-4.4.5-6.6 0-.2.2-.3.3-.3.2.1.3.3.3.4z"/><path d="M52.29963 68.665685c-6.3.6-11.1 3.9-10 10.7 1.1 6.8 7.6 8.1 16 7.7 8.4-.4 26.4-1.3 26.4-1.3s-3.3-1.7-4.8-3.3c-.5-.6-1-1.4-1.6-2.5-1.6.1-15.5.8-22.7 1-3.4.1-3.8-1.2-3.9-1.8-.3-1.2.5-2.7 2.8-2.8 3.1-.2 10.8-.7 21.4-.7h11.5s.9-.3 1-9.1c0-.1-29.8 1.5-36.1 2.1z" class="st37" fill="#737039" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M56.19963 86.665685c-8.8 0-12.6-2.3-13.5-7.4 0-.1 0-.2-.1-.4 1.2 1.5 3.5 2.7 5.6 2.7 1.4 0 2.6-.5 3.6-1.5.5.7 1.4 1.4 3.7 1.4h.4c6.9-.2 19.5-.8 22.1-.9.6 1.1 1.2 1.9 1.6 2.4.9 1 2.4 1.9 3.6 2.5-5 .3-18.1.9-24.7 1.2h-2.3z" class="st39" fill="#625d28"/><path d="M44.09963 57.865685c-2.2-.6-5.8-8.3-8.7-8.7-2.9-.3-6.6 1.6-3.2 8.5 3.4 6.9 8 10 14.3 8.2 6.3-1.8 12.7-5.1 14.5-8.3 1.8-3.2-.6-6.2-4.8-4.3-4.1 1.7-9.9 5.2-12.1 4.6z" fill="#b3bfcd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M43.09963 65.865685c-4.3 0-7.7-2.7-10.4-8.4-1.4-2.8-1.7-5.1-.8-6.4.8-1.3 2.3-1.4 2.9-1.4h.6c.4 0 .8.2 1.2.6-.7.1-1.3.5-1.6 1.2-.6 1.2-.3 2.9.9 4.7l.4.6c2.1 3.1 4.1 6 7.8 6 .9 0 1.9-.2 2.9-.6 5.6-2 9.4-3.6 11.1-5.4 1.2-1.3 1.9-2.6 1.7-3.6.5.2.9.5 1.1.9.5.8.4 1.9-.2 3-1.6 2.8-7.4 6.2-14.2 8.1-1.2.5-2.3.7-3.4.7z" class="st35" fill="#93a1b5"/><path d="M13.89963 107.66569c-.1 5.1 1.3 10.2 2.3 14.8 1.3 5.5 1.3 10.1 5.2 10.7 3.9.6 10.1.9 14.4 0 4.3-.9 4.1-5.2 4.5-8.2.4-3.1 0-10.7 0-10.7s-1.1-1.4-3-1.9" class="st34" fill="#3a434e"/><path d="M14.39963 107.66569c-.1 5.2 1.3 10.3 2.5 15.4l.8 3.9c.3 1.3.6 2.5 1.1 3.6.3.5.6 1 1.1 1.4.5.3 1 .5 1.6.6 1.3.2 2.6.3 3.9.4 2.6.2 5.2.2 7.8 0 1.3-.1 2.6-.3 3.7-.7 1.1-.4 1.9-1.4 2.3-2.6.4-1.2.5-2.4.7-3.7.1-.7.2-1.3.2-1.9.1-.6.1-1.3.1-1.9 0-2.6 0-5.2-.2-7.8l.1.3c-.1-.2-.3-.4-.5-.6l-.6-.6c-.4-.4-.9-.7-1.5-.9-.1 0-.1-.1-.1-.2s.1-.1.2-.1c.6.1 1.2.3 1.7.6.3.1.5.3.8.5.3.2.5.4.8.6.1.1.1.2.1.2.1 2.6.2 5.3.2 7.9 0 .7 0 1.3-.1 2s-.2 1.3-.2 2c-.1 1.3-.3 2.7-.7 4-.5 1.3-1.5 2.6-2.8 3.1-1.4.6-2.7.7-4 .8-2.7.2-5.3.2-8 0-1.3-.1-2.6-.2-4-.4-.7-.1-1.4-.4-2-.8-.6-.5-1-1.1-1.4-1.7-.6-1.3-.9-2.6-1.2-3.9l-.8-3.9c-1.1-5.1-2.6-10.3-2.5-15.6 0-.3.2-.5.5-.5.2 0 .4.2.4.5z"/><path d="M68.19963 86.665685l.4 4.6s.3 1.5 2.4 1.5c2.1-.1 2.2-2 2.2-2l-.1-4.5-4.9.4z" class="st37" fill="#737039" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="M110.49963 71.465685c-.5 1.8.5 2.9 3.8 4.6 3.3 1.8 4 5.1 8.2 6 4.3.9 8.2-4.5 3.8-10.1-4.5-5.6-14.1-6.5-15.8-.5z" class="st39" fill="#625d28"/><circle r="1.7" cy="57.765686" cx="126.09963" fill="#99988c"/><path d="M17.39963 115.26569s.8 3.9 1.1 6.3c.3 2.4.9 3.8 5.9 3.2 5-.6 4.9-1.5 5.1-6.4.2-4.9-.1-7.4-3.7-7.6-3.6-.2-9.1.7-8.4 4.5z" class="st33" fill="#56606b"/><path fill="#3a434e" class="st34" d="M11.19963 40.565685c-2.7000002 5.1-2.7000002 7.7-.5 8.5 2.2.8 4.1.7 6.4-3 0 0 2 .7 4.9-4.1.9-1.5-.7-2.6-.7-2.6s-4.8 1.3-7.1-5l-3 6.2z"/></svg> \ No newline at end of file diff --git a/app/javascript/images/elephant_ui_working.svg b/app/javascript/images/elephant_ui_working.svg new file mode 100644 index 000000000..8ba475db0 --- /dev/null +++ b/app/javascript/images/elephant_ui_working.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 124.12477 127.91685" width="124.12476" height="127.91685"><path d="M72.584191 46.815676c-2.3-2.2-4.2-2.5-6.6-.6-2.4 1.9-2.1 4.8.9 7.6 3.1 2.9 4.7 4.1 6.7 5 2.1.9 5.4 2.5 10.5-2s10.2-11.1 9.4-14.7c-.8-3.6-4.1-1.8-6.8 1.2s-3.7 4-5.4 5.2c-1.5 1.3-3.8 3-8.7-1.7z" class="st0" style="fill:#93a1b5;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M116.384191 75.015676c0 6.3-3.9 9.8-9.1 9.8-5.3 0-9.9-3.5-9.9-9.8 0-6.3 4.3-10.3 9.5-10.3s9.5 4 9.5 10.3z" style="fill:#3a434e;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M54.184191 16.615676c-23 1.2-30.5 14.1-32.8 27.8-3 18.2-8.2 44.2-9.2 53.2s-1 16 6 22 11 5 23 7 19 0 20-8l16.8-1.1s14.5 5.5 18.8 6.9c4.3 1.4 10.6.5 12.1-7.1s.2-12.5-6.6-14.4c-6.8-1.9-10.6-2.9-10.6-2.9l4.4-30.1s17.4 1.6 22.6-20c0 0 3.9 1.1 4.8-2.8.9-3.9-2.6-6.2-5.6-4.8l-2.5-1s-.2-3.8-3.5-4.2c-2.1-.2-6 3.4-3 7.4 0 0-3.4 8.9-12 7.8-8.6-1.1-12.5-11.2-15-18.2s-10.7-18.3-27.7-17.5z" class="st2" style="fill:#56606b;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M95.484191 69.915676c-.6 0-1.2 0-1.8-.1-4.2-.2-10.9-2.4-17-7.8-.7-1-.4-2-.2-2.5.5-1.1 1.7-1.8 3-1.8.8 0 1.5.3 2.2.8 3 2.2 7.8 5.1 13.8 5.1.9 0 1.8-.1 2.7-.2 7.2-1 12.1-5.8 14.3-9.9.6-1.2 1.3-2.5 1.8-3.5.2-.5.3-.7.6-.9.3-.2 1 .2 1 .2l2.1.8c-4.5 17.8-17.4 19.2-21.2 19.2h-1.3v.6z" class="st3" style="fill:#3a434e;opacity:.98;fill-opacity:1"/><path d="M48.884191 126.915676c-2.2 0-4.7-.2-7.6-.7-2.8-.5-5.1-.8-7.1-1-6.9-.9-10.3-1.3-15.6-5.9-7-6-6.8-13-5.8-21.6.3-2.3.8-5.9 1.7-11.2 3.1 1.4 6.1 2.2 8.7 2.2 3.1 0 5.4-1.2 6.6-3.4 1.6 1.9 6.9 7.3 13.3 7.3 1 0 1.9-.1 2.8-.4 3.5-1 19.8-2.1 46.9-3.4l-1.7 11.7.4.1s3.8 1 10.6 2.9c6.1 1.7 7.9 5.6 6.3 13.8-1.3 6.6-6.2 7.3-8.2 7.3-1.1 0-2.2-.2-3.3-.5-4.2-1.4-18.6-6.8-18.7-6.9h-.1l-17.3 1.2-.1.4c-.7 5.4-4.5 8.1-11.8 8.1z" class="st3" style="fill:#3a434e;fill-opacity:1"/><path d="M41.184191 103.415676c-3.8-1.4-6-1.4-7.7-1.4-1.8 0-4.6 3.3 1.4 5.4 6 2.1 10.3 3.4 10.3 3.4s1.8-2.1 3.5-2.9c1.6-.8 2.3-.9 2.3-.9l-9.8-3.6z" style="fill:#56606b;fill-opacity:1"/><path d="M27.584191 38.615676c1.2-5-2.1-8.2-5.7-9.2-3.5-1-8.4-1.7-13.9 6.9s-9.5 16.5-6.4 20.6c3.1 4.1 9.3 3.4 11.8-.8 0 0 5.7 3.8 9.5-4.2" class="st2" style="fill:#56606b;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M10.884191 45.115676c-1.6 2.5-.8 5 2 5.9 2.7 1 5-1.5 6.5-3.8 1.6-2.3 3.6-5.9 3.6-5.9s-3.7 1.2-5.6-.2c-2-1.4-1.5-3.8-1.5-3.8l-5 7.8z" class="st3" style="fill:#3a434e;fill-opacity:1"/><path d="M22.684191 41.415676c-2.6 1.1-6.8.6-6.9-4.1 0 0-5.1 7.6-5.9 9.6" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M67.584191 5.215676c0-3.4-3.9-2.6-3.9-2.6 0-1.2-2-3.5-8.5-.6-6.4 2.9-7.3 6-7.3 6-3.8-1.7-9.6-2.6-13.5.8-3.9 3.4-4.3 10 2.3 13.5 0 0 2.9.9 7.7-.4 4.8-1.3 7.7-3.3 7.7-3.3s3.7 2.3 9 .6c5.3-1.7 9.9-4.5 10.3-10.1.5-5.7-3.8-3.9-3.8-3.9z" style="fill:#56606b;fill-opacity:1"/><path d="M67.084191 16.315676c-1-5.5-7-3-7-3 .5-2.1-3-4.1-5.5-2.7-2.5 1.4-6.6-.1-6.6-.1-6.4-4.4-14.3-2.1-16.1 2-1.1 3.3.2 7.3 4.8 9.7 0 0 2.9.9 7.7-.4 4.8-1.3 7.7-3.3 7.7-3.3s3.7 2.3 9 .6c2.3-.6 4.3-1.5 6-2.8 0 .1 0 0 0 0z" style="fill:#3a434e;fill-opacity:1"/><path d="M36.684191 22.715676c-.1 0-.2 0-.2-.1-3.1-1.6-5-4.1-5.4-7-.3-2.7.8-5.4 3-7.3 3.9-3.3 9.5-2.8 13.6-1.1.5-1.1 2.2-3.5 7.3-5.8 4.5-2 6.9-1.5 8-.8.6.4.9.9 1.1 1.3.7-.1 2-.1 3 .7.5.4.9 1 1 1.8.7-.1 1.8-.2 2.7.4 1 .7 1.4 2.1 1.2 4.1-.4 5-3.9 8.5-10.7 10.6-5.5 1.7-9.3-.6-9.4-.7-.2-.1-.3-.5-.2-.7.1-.2.5-.3.7-.2 0 0 3.6 2.2 8.6.6 6.3-2 9.6-5.1 10-9.7.1-1.6-.2-2.8-.8-3.3-.9-.7-2.3-.1-2.3-.1-.2.1-.3 0-.5 0-.1-.1-.2-.2-.2-.4 0-.8-.2-1.3-.6-1.7-.9-.8-2.6-.4-2.7-.4-.1 0-.3 0-.4-.1-.1-.1-.2-.2-.2-.4 0-.3-.2-.7-.7-1-.6-.4-2.6-1.1-7.1.8-6.1 2.7-7 5.6-7 5.7 0 .1-.1.3-.3.3-.1.1-.3.1-.4 0-3.9-1.7-9.3-2.4-13 .8-1.9 1.7-2.9 4.1-2.6 6.4.3 2.5 2 4.7 4.8 6.2.2.1.3.4.2.7-.1.3-.3.4-.5.4z"/><path d="M40.584191 84.115676s6.3 16.8 7.1 19.3c.8 2.5 1.8 3.4 7.3 3 5.5-.4 6.7-21.5 6.7-21.5l-21.1-.8z" style="fill:#191b22;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M51.084191 103.415676c-1.7-2.1-1.9-4.2-1.9-4.2l2-10.9 3-1.4-3.1 16.5zm33.9-35.3l-23.9 1.9 1.2 8 25.2 1.1 4.6-9c-2.3-.3-4.7-.9-7.1-2z" class="st9" style="fill:#191b22;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M28.484191 82.915676c7.2 9.4 12.7 11.4 21.8 7.7 8.5-3.4 15.4-9 15.1-15-.3-6-2.1-10.3-9.1-9.8-2.3.2-6.8 2.8-9.6 4.4-1.8 1-4.2 2.2-6 .4-1.8-1.8-4.3-4.4-4.3-4.4" class="st2" style="fill:#56606b;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M49.284191 80.515676c-.3-.2-.5-.4-.7-.6-1.2.7-2.3 1.3-2.8 1.6-2 1.2-3.8.5-4.7-.3-.9-.9-2.3-2.4-5.5-1.5-3.7 1-4.5 5.7-2.5 8.4 6.5 6.1 12.8 4.1 15.2 3.3 2.4-.8 6.3-2.7 6.3-2.7l.6-6c-2-.8-4.1-.9-5.9-2.2z" class="st3" style="fill:#3a434e;fill-opacity:1"/><path d="M28.484191 82.915676c7.2 9.4 12.7 11.4 21.8 7.7 8.5-3.4 15.4-9 15.1-15-.3-6-2.1-10.3-9.1-9.8-2.3.2-6.8 2.8-9.6 4.4-1.8 1-4.2 2.2-6 .4-1.8-1.8-4.3-4.4-4.3-4.4m35.4-8.6c6.5 8.3 15.5 12.5 21.8 12.7" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M53.184191 104.415676c-1.6.1-2.7-1.1-2.4-2.7l4.9-25.9c.3-1.6 1.9-3 3.6-3.1l26.9-1.7c1.6-.1 3.6-1.4 4.4-2.9l.7-1.3c.7-1.5 2.7-2.8 4.4-2.9l4.5-.3c1.6-.1 3.1 1.1 3.3 2.8v.2c.2 1.6.5 3.7.7 4.6.2.9.3 3 .1 4.6l-2.2 21.3c-.2 1.6-1.7 3.1-3.3 3.3l-45.6 4z" style="fill:#191b22;fill-opacity:1"/><path d="M53.184191 104.415676c-1.6.1-2.7-1.1-2.4-2.7l4.9-25.9c.3-1.6 1.9-3 3.6-3.1l26.9-1.7c1.6-.1 3.6-1.4 4.4-2.9l.7-1.3c.7-1.5 2.7-2.8 4.4-2.9l4.5-.3c1.6-.1 3.1 1.1 3.3 2.8v.2c.2 1.6.5 3.7.7 4.6.2.9.3 3 .1 4.6l-2.2 21.3c-.2 1.6-1.7 3.1-3.3 3.3l-45.6 4z" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M55.684191 105.915676c-1.6.1-2.3-.4-2-2l4.4-25.6c.3-1.6 1.9-3 3.6-3.1l26.9-1.7c1.6-.1 3.6-1.4 4.4-2.9l.7-1.3c.7-1.5 2.7-2.8 4.4-2.9l4.5-.3c1.6-.1 3.1 1.1 3.3 2.8v.2c.2 1.6 1.3 2.9 2.5 2.8 1.2-.1 1.9 1.2 1.6 2.8l-5.2 24.9c-.3 1.6-2 3.1-3.6 3.2l-45.5 3.1z" style="fill:#191b22;fill-opacity:1"/><path d="M53.184191 104.315676l4.9-26c.3-1.6 1.9-3 3.6-3.1l26.9-1.7c1.6-.1 3.6-1.4 4.4-2.9l.7-1.3c.7-1.5 2.7-2.8 4.4-2.9l4.5-.3c1.6-.1 3.1 1.1 3.3 2.8v.2c.2 1.6 1.3 2.9 2.5 2.8 1.2-.1 1.9 1.2 1.6 2.8l-5.2 24.9c-.3 1.6-2 3.1-3.6 3.2l-46.7 3.7m9.2-103.9c-.3 2.9-2.9 4.9-4.1 5.8m8-3.2c-.7 3.5-4 6-4 6" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M39.884191 53.615676c-2.3-2.2-4.2-2.5-6.6-.6-2.4 1.9-2.1 4.8.9 7.6 3.1 2.9 4.7 4.1 6.7 5 2 .9 5.4 2.5 10.5-2s10.2-11.1 9.4-14.7c-.8-3.6-4.1-1.8-6.8 1.2s-3.7 4-5.4 5.2c-1.7 1.2-3.8 3-8.7-1.7z" class="st0" style="fill:#93a1b5;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill-opacity:1"/><path d="M44.384191 61.315676c-2.3 0-4.7-1.2-6.6-3.1-.9-.9-1.1-2-.7-2.9.3-.8 1.1-1.3 1.8-1.3.2 0 .5 0 .7.1 2.3 2.1 4.2 3.2 5.9 3.2 1.6 0 2.7-.8 3.5-1.4 1.7-1.3 2.8-2.3 5.5-5.3.9-1.1 1.9-1.9 2.7-2.4.3.2.6.4.7.8.2.8-.2 2-.7 2.7-.9 1.3-4.9 5.4-9 8.4-1.1.7-2.4 1.2-3.8 1.2z" style="fill:#b3bfcd;fill-opacity:1"/><path d="M45.784191 50.115676c-.7 0-1.4-.6-1.4-1.4v-6.1c0-.7.6-1.4 1.4-1.4.7 0 1.4.6 1.4 1.4v6.1c0 .8-.6 1.4-1.4 1.4z"/><path d="M61.184191 118.215676c.7-7.1-3.5-10.6-9.2-11.1-5.7-.5-10.2 6.8-9.1 13.1 1.1 6.3 6.7 7.2 6.7 7.2" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M52.084191 107.515676c-2.2-.7-4.3-1.4-6.5-2.2-2.1-.8-4.3-1.5-6.4-2.3-.1 0-.2-.2-.1-.3 0-.1.2-.2.3-.2 2.2.6 4.4 1.3 6.5 1.9 2.2.7 4.3 1.3 6.5 2 .3.1.4.4.3.6-.1.4-.4.6-.6.5zm25.4 10.1c-.2-1.4-.2-2.9.1-4.2.2-1.4.6-2.7 1.1-4-.3 1.3-.5 2.7-.6 4.1 0 1.4.1 2.7.4 4 .1.3-.1.5-.3.6-.2.1-.6-.1-.7-.5 0 .1 0 .1 0 0z"/><path d="M104.284191 103.615676c-3.6-.7-8.5 2.1-9.5 9.7s2.1 10.7 5.3 11.6m15.1-83.5l-.39999 1.4m-1.90001-1.2c2.4 1.7 6.4 3.4 6.4 3.4m-1.6-2.6l-.60001 1.59999" class="st5" style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M47.484191 79.215676c3.2 2.7 7 3.3 7 3.3" style="fill:none;stroke:#000;stroke-miterlimit:10"/><path d="M69.284191 24.315676c-3.5.4-2.7 2.9-1.2 3.5 1.5.6 3.7.1 4.3-1.6.4-1.6-1.3-2.1-3.1-1.9z" style="fill:#4f5862;fill-opacity:1"/></svg> \ No newline at end of file diff --git a/app/javascript/images/icon_follow_requests.png b/app/javascript/images/icon_follow_requests.png new file mode 100644 index 000000000..4123e2a69 --- /dev/null +++ b/app/javascript/images/icon_follow_requests.png Binary files differdiff --git a/app/javascript/images/icon_keyboard_shortcuts.png b/app/javascript/images/icon_keyboard_shortcuts.png new file mode 100644 index 000000000..d66f3939e --- /dev/null +++ b/app/javascript/images/icon_keyboard_shortcuts.png Binary files differdiff --git a/app/javascript/images/icon_lists.png b/app/javascript/images/icon_lists.png new file mode 100644 index 000000000..3828946e8 --- /dev/null +++ b/app/javascript/images/icon_lists.png Binary files differdiff --git a/app/javascript/images/mastodon-not-found.png b/app/javascript/images/mastodon-not-found.png deleted file mode 100644 index 76108d41f..000000000 --- a/app/javascript/images/mastodon-not-found.png +++ /dev/null Binary files differdiff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js index f8843d1d9..df6a36379 100644 --- a/app/javascript/mastodon/actions/timelines.js +++ b/app/javascript/mastodon/actions/timelines.js @@ -19,13 +19,14 @@ export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT'; export const TIMELINE_CONTEXT_UPDATE = 'CONTEXT_UPDATE'; -export function refreshTimelineSuccess(timeline, statuses, skipLoading, next) { +export function refreshTimelineSuccess(timeline, statuses, skipLoading, next, partial) { return { type: TIMELINE_REFRESH_SUCCESS, timeline, statuses, skipLoading, next, + partial, }; }; @@ -88,7 +89,7 @@ export function refreshTimeline(timelineId, path, params = {}) { return function (dispatch, getState) { const timeline = getState().getIn(['timelines', timelineId], ImmutableMap()); - if (timeline.get('isLoading') || timeline.get('online')) { + if (timeline.get('isLoading') || (timeline.get('online') && !timeline.get('isPartial'))) { return; } @@ -104,8 +105,12 @@ export function refreshTimeline(timelineId, path, params = {}) { dispatch(refreshTimelineRequest(timelineId, skipLoading)); api(getState).get(path, { params }).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null)); + if (response.status === 206) { + dispatch(refreshTimelineSuccess(timelineId, [], skipLoading, null, true)); + } else { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null, false)); + } }).catch(error => { dispatch(refreshTimelineFail(timelineId, error, skipLoading)); }); diff --git a/app/javascript/mastodon/components/missing_indicator.js b/app/javascript/mastodon/components/missing_indicator.js index 87df7f61c..70d8c3b98 100644 --- a/app/javascript/mastodon/components/missing_indicator.js +++ b/app/javascript/mastodon/components/missing_indicator.js @@ -2,9 +2,14 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; const MissingIndicator = () => ( - <div className='missing-indicator'> + <div className='regeneration-indicator missing-indicator'> <div> - <FormattedMessage id='missing_indicator.label' defaultMessage='Not found' /> + <div className='regeneration-indicator__figure' /> + + <div className='regeneration-indicator__label'> + <FormattedMessage id='missing_indicator.label' tagName='strong' defaultMessage='Not found' /> + <FormattedMessage id='missing_indicator.sublabel' defaultMessage='This resource could not be found' /> + </div> </div> </div> ); diff --git a/app/javascript/mastodon/components/status_list.js b/app/javascript/mastodon/components/status_list.js index 58a7b228a..5acaf714e 100644 --- a/app/javascript/mastodon/components/status_list.js +++ b/app/javascript/mastodon/components/status_list.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import StatusContainer from '../containers/status_container'; import ImmutablePureComponent from 'react-immutable-pure-component'; import ScrollableList from './scrollable_list'; +import { FormattedMessage } from 'react-intl'; export default class StatusList extends ImmutablePureComponent { @@ -16,6 +17,7 @@ export default class StatusList extends ImmutablePureComponent { trackScroll: PropTypes.bool, shouldUpdateScroll: PropTypes.func, isLoading: PropTypes.bool, + isPartial: PropTypes.bool, hasMore: PropTypes.bool, prepend: PropTypes.node, emptyMessage: PropTypes.node, @@ -48,8 +50,23 @@ export default class StatusList extends ImmutablePureComponent { } render () { - const { statusIds, ...other } = this.props; - const { isLoading } = other; + const { statusIds, ...other } = this.props; + const { isLoading, isPartial } = other; + + if (isPartial) { + return ( + <div className='regeneration-indicator'> + <div> + <div className='regeneration-indicator__figure' /> + + <div className='regeneration-indicator__label'> + <FormattedMessage id='regeneration_indicator.label' tagName='strong' defaultMessage='Loading…' /> + <FormattedMessage id='regeneration_indicator.sublabel' defaultMessage='Your home feed is being prepared!' /> + </div> + </div> + </div> + ); + } const scrollableContent = (isLoading || statusIds.size > 0) ? ( statusIds.map((statusId) => ( diff --git a/app/javascript/mastodon/features/home_timeline/index.js b/app/javascript/mastodon/features/home_timeline/index.js index a4bc60fac..31f5a3c8b 100644 --- a/app/javascript/mastodon/features/home_timeline/index.js +++ b/app/javascript/mastodon/features/home_timeline/index.js @@ -1,6 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; -import { expandHomeTimeline } from '../../actions/timelines'; +import { expandHomeTimeline, refreshHomeTimeline } from '../../actions/timelines'; import PropTypes from 'prop-types'; import StatusListContainer from '../ui/containers/status_list_container'; import Column from '../../components/column'; @@ -16,6 +16,7 @@ const messages = defineMessages({ const mapStateToProps = state => ({ hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0, + isPartial: state.getIn(['timelines', 'home', 'isPartial'], false), }); @connect(mapStateToProps) @@ -26,6 +27,7 @@ export default class HomeTimeline extends React.PureComponent { dispatch: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, hasUnread: PropTypes.bool, + isPartial: PropTypes.bool, columnId: PropTypes.string, multiColumn: PropTypes.bool, }; @@ -57,6 +59,39 @@ export default class HomeTimeline extends React.PureComponent { this.props.dispatch(expandHomeTimeline()); } + componentDidMount () { + this._checkIfReloadNeeded(false, this.props.isPartial); + } + + componentDidUpdate (prevProps) { + this._checkIfReloadNeeded(prevProps.isPartial, this.props.isPartial); + } + + componentWillUnmount () { + this._stopPolling(); + } + + _checkIfReloadNeeded (wasPartial, isPartial) { + const { dispatch } = this.props; + + if (wasPartial === isPartial) { + return; + } else if (!wasPartial && isPartial) { + this.polling = setInterval(() => { + dispatch(refreshHomeTimeline()); + }, 3000); + } else if (wasPartial && !isPartial) { + this._stopPolling(); + } + } + + _stopPolling () { + if (this.polling) { + clearInterval(this.polling); + this.polling = null; + } + } + render () { const { intl, hasUnread, columnId, multiColumn } = this.props; const pinned = !!columnId; diff --git a/app/javascript/mastodon/features/list_timeline/index.js b/app/javascript/mastodon/features/list_timeline/index.js index ae136e48f..3b97ac62a 100644 --- a/app/javascript/mastodon/features/list_timeline/index.js +++ b/app/javascript/mastodon/features/list_timeline/index.js @@ -120,13 +120,17 @@ export default class ListTimeline extends React.PureComponent { if (typeof list === 'undefined') { return ( <Column> - <LoadingIndicator /> + <div className='scrollable'> + <LoadingIndicator /> + </div> </Column> ); } else if (list === false) { return ( <Column> - <MissingIndicator /> + <div className='scrollable'> + <MissingIndicator /> + </div> </Column> ); } diff --git a/app/javascript/mastodon/features/ui/containers/status_list_container.js b/app/javascript/mastodon/features/ui/containers/status_list_container.js index a0aec4403..59b53d823 100644 --- a/app/javascript/mastodon/features/ui/containers/status_list_container.js +++ b/app/javascript/mastodon/features/ui/containers/status_list_container.js @@ -47,6 +47,7 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, { timelineId }) => ({ statusIds: getStatusIds(state, { type: timelineId }), isLoading: state.getIn(['timelines', timelineId, 'isLoading'], true), + isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false), hasMore: !!state.getIn(['timelines', timelineId, 'next']), }); diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js index 9984c3b5d..7b7b5470f 100644 --- a/app/javascript/mastodon/reducers/timelines.js +++ b/app/javascript/mastodon/reducers/timelines.js @@ -30,7 +30,7 @@ const initialTimeline = ImmutableMap({ items: ImmutableList(), }); -const normalizeTimeline = (state, timeline, statuses, next) => { +const normalizeTimeline = (state, timeline, statuses, next, isPartial) => { const oldIds = state.getIn([timeline, 'items'], ImmutableList()); const ids = ImmutableList(statuses.map(status => status.get('id'))).filter(newId => !oldIds.includes(newId)); const wasLoaded = state.getIn([timeline, 'loaded']); @@ -41,6 +41,7 @@ const normalizeTimeline = (state, timeline, statuses, next) => { mMap.set('isLoading', false); if (!hadNext) mMap.set('next', next); mMap.set('items', wasLoaded ? ids.concat(oldIds) : ids); + mMap.set('isPartial', isPartial); })); }; @@ -124,7 +125,7 @@ export default function timelines(state = initialState, action) { case TIMELINE_EXPAND_FAIL: return state.update(action.timeline, initialTimeline, map => map.set('isLoading', false)); case TIMELINE_REFRESH_SUCCESS: - return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next); + return normalizeTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial); case TIMELINE_EXPAND_SUCCESS: return appendNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next); case TIMELINE_UPDATE: diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 71bffdaa6..d13a18ad7 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2303,7 +2303,7 @@ } } -.missing-indicator { +.regeneration-indicator { text-align: center; font-size: 16px; font-weight: 500; @@ -2314,11 +2314,46 @@ flex: 1 1 auto; align-items: center; justify-content: center; + padding: 20px; & > div { - background: url('~images/mastodon-not-found.png') no-repeat center -50px; - padding-top: 210px; width: 100%; + background: transparent; + padding-top: 0; + } + + &__figure { + background: url('~images/elephant_ui_working.svg') no-repeat center 0; + width: 100%; + height: 160px; + background-size: contain; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + + &.missing-indicator { + padding-top: 20px + 48px; + + .regeneration-indicator__figure { + background-image: url('~images/elephant_ui_disappointed.svg'); + } + } + + &__label { + margin-top: 200px; + + strong { + display: block; + margin-bottom: 10px; + color: lighten($ui-base-color, 34%); + } + + span { + font-size: 15px; + font-weight: 400; + } } } @@ -2749,7 +2784,6 @@ @keyframes heartbeat { from { transform: scale(1); - transform-origin: center center; animation-timing-function: ease-out; } @@ -2775,6 +2809,7 @@ } .pulse-loading { + transform-origin: center center; animation: heartbeat 1.5s ease-in-out infinite both; } diff --git a/app/javascript/styles/win95.scss b/app/javascript/styles/win95.scss index d683218b0..c1058af29 100644 --- a/app/javascript/styles/win95.scss +++ b/app/javascript/styles/win95.scss @@ -54,7 +54,6 @@ $ui-highlight-color: $win95-window-header; border-radius:0px; } - @mixin win95-tab() { box-shadow: inset -1px 0px 0px #000000, inset 1px 0px 0px #ffffff, @@ -122,7 +121,6 @@ $ui-highlight-color: $win95-window-header; vertical-align: middle; } - /* main win95 style */ body { @@ -189,10 +187,31 @@ body.admin { .drawer .drawer__inner { overflow: visible; height:inherit; + background:$win95-bg; +} + +.drawer:after { + display:block; + content: " "; + + position:absolute; + bottom:15px; + left:15px; + width:132px; + height:117px; + background-image:url("~images/clippy_wave.gif"), url("~images/clippy_frame.png"); + background-repeat:no-repeat; + background-position: 4px 20px, 0px 0px; + z-index:0; } .drawer__pager { overflow-y:auto; + z-index:1; +} + +.privacy-dropdown__dropdown { + z-index:2; } .column { @@ -219,6 +238,7 @@ body.admin { border-bottom-width:0px; color:white; font-weight:bold; + align-items:baseline; } .column-header__wrapper.active { @@ -237,6 +257,11 @@ body.admin { color:white; } +.column-header__buttons { + max-height: 20px; + margin-right:0px; +} + .column-header__button { background: $win95-bg; color: black; @@ -246,6 +271,10 @@ body.admin { padding:0px 2px; margin-top:2px; @include win95-outset() + + &:hover { + color: black; + } } .column-header__button.active, .column-header__button.active:hover { @@ -308,6 +337,13 @@ body.admin { padding:4px; } +.column-inline-form { + background-color: $win95-bg; + @include win95-border-outset(); + border-bottom-width:0px; + border-top-width:0px; +} + .column-settings__section { color:black; font-weight:bold; @@ -679,7 +715,6 @@ body.admin { font-weight:bold; } - .drawer__header { background: $win95-bg; @include win95-border-outset() @@ -820,12 +855,13 @@ body.admin { font-weight:bold; } -.autosuggest-textarea__textarea, .spoiler-input__input { +.compose-form .autosuggest-textarea__textarea, +.compose-form .spoiler-input__input { border-radius:0px; @include win95-border-slight-inset(); } -.autosuggest-textarea__textarea { +.compose-form .autosuggest-textarea__textarea { border-bottom:0px; } @@ -840,13 +876,30 @@ body.admin { border-right:1px inset $win95-bg; } +.compose-form .compose-form__buttons-wrapper { + background-color: $win95-bg; + border:2px groove $win95-bg; + margin-top:4px; + padding:4px 8px; +} + .compose-form__buttons { background-color:$win95-bg; border-radius:0px; box-shadow:unset; - border:2px groove $win95-bg; - margin-top:4px; - padding:4px 8px; +} + +.compose-form__buttons-separator { + border-left: 2px groove $win95-bg; +} + +.privacy-dropdown.active .privacy-dropdown__value.active, +.advanced-options-dropdown.open .advanced-options-dropdown__value { + background: $win95-bg; +} + +.privacy-dropdown.active .privacy-dropdown__value.active .icon-button { + color: $win95-dark-grey; } .privacy-dropdown.active @@ -860,7 +913,11 @@ body.admin { background:$win95-window-header; } -.privacy-dropdown.active .privacy-dropdown__dropdown { +.privacy-dropdown__dropdown, +.privacy-dropdown.active .privacy-dropdown__dropdown, +.advanced-options-dropdown__dropdown, +.advanced-options-dropdown.open .advanced-options-dropdown__dropdown +{ box-shadow:unset; color:black; @include win95-outset() @@ -934,6 +991,10 @@ body.admin { display:none; } +.emoji-picker-dropdown__menu { + z-index:2; +} + .emoji-dialog.with-search { box-shadow:unset; border-radius:0px; @@ -1026,31 +1087,43 @@ body.admin { .column-subheading { background-color:$win95-bg; color:black; - font-size:0px; border-bottom: 2px groove $win95-bg; - padding:0px; - margin:0px; + text-transform: none; + font-size: 16px; } .column-link { background-color:transparent; - background-size:32px 32px; - background-repeat:no-repeat; - background-position: 36px 50%; color:black; - padding-left:40px; - &:hover { background-color: $win95-window-header; + color:white; + } +} + +.getting-started__wrapper { + .column-subheading { + font-size:0px; + margin:0px; + padding:0px; + } + + .column-link { background-size:32px 32px; background-repeat:no-repeat; background-position: 36px 50%; - color:white; - } + padding-left:40px; + + &:hover { + background-size:32px 32px; + background-repeat:no-repeat; + background-position: 36px 50%; + } - i { - font-size: 0px; - width:32px; + i { + font-size: 0px; + width:32px; + } } } @@ -1070,6 +1143,18 @@ body.admin { background-image: url("~images/icon_likes.png"); &:hover { background-image: url("~images/icon_likes.png"); } } +.column-link[href="/web/lists"] { + background-image: url("~images/icon_lists.png"); + &:hover { background-image: url("~images/icon_lists.png"); } +} +.column-link[href="/web/follow_requests"] { + background-image: url("~images/icon_follow_requests.png"); + &:hover { background-image: url("~images/icon_follow_requests.png"); } +} +.column-link[href="/web/keyboard-shortcuts"] { + background-image: url("~images/icon_keyboard_shortcuts.png"); + &:hover { background-image: url("~images/icon_keyboard_shortcuts.png"); } +} .column-link[href="/web/blocks"] { background-image: url("~images/icon_blocks.png"); &:hover { background-image: url("~images/icon_blocks.png"); } @@ -1124,6 +1209,14 @@ body.admin { background-color:$win95-bg; } +.column .static-content.getting-started { + display:none; +} + +.keyboard-shortcuts kbd { + background-color: $win95-bg; +} + .account__header { background-color:#7f7f7f; } @@ -1132,6 +1225,23 @@ body.admin { color:white; } +.account-authorize__wrapper { + border: 2px groove $win95-bg; + margin: 2px; + padding:2px; +} + +.account--panel { + background-color: $win95-bg; + border:0px; + border-top: 2px groove $win95-bg; +} + +.account-authorize .account__header__content { + color:black; + margin:10px; +} + .account__action-bar__tab > span { color:black; font-weight:bold; @@ -1307,7 +1417,6 @@ body.admin { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAFnpUWHRUaXRsZQAACJnLzU9JzElKBwALgwLXaCRlPwAAABd6VFh0QXV0aG9yAAAImUvOKMrPS8wBAAuaAugOwWPyAAAAEUlEQVQImWNgYGD4z4AE/gMADwMB/414xEUAAAAASUVORK5CYII='); } - .admin-wrapper::before { position:absolute; top:0px; @@ -1652,4 +1761,3 @@ a.table-action-link:hover, color:black; border-bottom: 0px solid transparent; } - diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index d5960c3ad..ba086449c 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -54,7 +54,7 @@ class NotifyService < BaseService end def response_to_recipient? - @notification.target_status.in_reply_to_account_id == @recipient.id + @notification.target_status.in_reply_to_account_id == @recipient.id && @notification.target_status.thread&.direct_visibility? end def optional_non_following_and_direct? diff --git a/app/services/precompute_feed_service.rb b/app/services/precompute_feed_service.rb index 36aabaa00..4f771ff72 100644 --- a/app/services/precompute_feed_service.rb +++ b/app/services/precompute_feed_service.rb @@ -3,5 +3,6 @@ class PrecomputeFeedService < BaseService def call(account) FeedManager.instance.populate_feed(account) + Redis.current.del("account:#{account.id}:regeneration") end end diff --git a/app/workers/regeneration_worker.rb b/app/workers/regeneration_worker.rb index 8cee21ae1..5c6a040bd 100644 --- a/app/workers/regeneration_worker.rb +++ b/app/workers/regeneration_worker.rb @@ -3,7 +3,7 @@ class RegenerationWorker include Sidekiq::Worker - sidekiq_options queue: 'pull', backtrace: true, unique: :until_executed + sidekiq_options unique: :until_executed def perform(account_id, _ = :home) account = Account.find(account_id) diff --git a/spec/controllers/concerns/user_tracking_concern_spec.rb b/spec/controllers/concerns/user_tracking_concern_spec.rb index 168d44ba6..d08095ef8 100644 --- a/spec/controllers/concerns/user_tracking_concern_spec.rb +++ b/spec/controllers/concerns/user_tracking_concern_spec.rb @@ -43,15 +43,39 @@ describe ApplicationController, type: :controller do expect_updated_sign_in_at(user) end - it 'regenerates feed when sign in is older than two weeks' do - allow(RegenerationWorker).to receive(:perform_async) - user.update(current_sign_in_at: 3.weeks.ago) - sign_in user, scope: :user - get :show + describe 'feed regeneration' do + before do + alice = Fabricate(:account) + bob = Fabricate(:account) - expect_updated_sign_in_at(user) - expect(Redis.current.get("account:#{user.account_id}:regeneration")).to eq 'true' - expect(RegenerationWorker).to have_received(:perform_async) + user.account.follow!(alice) + user.account.follow!(bob) + + Fabricate(:status, account: alice, text: 'hello world') + Fabricate(:status, account: bob, text: 'yes hello') + Fabricate(:status, account: user.account, text: 'test') + + user.update(last_sign_in_at: 'Tue, 04 Jul 2017 14:45:56 UTC +00:00', current_sign_in_at: 'Wed, 05 Jul 2017 22:10:52 UTC +00:00') + + sign_in user, scope: :user + end + + it 'sets a regeneration marker while regenerating' do + allow(RegenerationWorker).to receive(:perform_async) + get :show + + expect_updated_sign_in_at(user) + expect(Redis.current.get("account:#{user.account_id}:regeneration")).to eq 'true' + expect(RegenerationWorker).to have_received(:perform_async) + end + + it 'regenerates feed when sign in is older than two weeks' do + get :show + + expect_updated_sign_in_at(user) + expect(Redis.current.zcard(FeedManager.instance.key(:home, user.account_id))).to eq 3 + expect(Redis.current.get("account:#{user.account_id}:regeneration")).to be_nil + end end def expect_updated_sign_in_at(user) diff --git a/spec/services/notify_service_spec.rb b/spec/services/notify_service_spec.rb index bb7601e76..1435ec917 100644 --- a/spec/services/notify_service_spec.rb +++ b/spec/services/notify_service_spec.rb @@ -82,10 +82,19 @@ RSpec.describe NotifyService do is_expected.to_not change(Notification, :count) end - context 'if the message chain initiated by recipient' do + context 'if the message chain initiated by recipient, but is not direct message' do let(:reply_to) { Fabricate(:status, account: recipient) } let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, visibility: :direct, thread: reply_to)) } + it 'does not notify' do + is_expected.to_not change(Notification, :count) + end + end + + context 'if the message chain initiated by recipient and is direct message' do + let(:reply_to) { Fabricate(:status, account: recipient, visibility: :direct) } + let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, visibility: :direct, thread: reply_to)) } + it 'does notify' do is_expected.to change(Notification, :count) end |