From 1544ac4e2798e969cb9d6d14a361f90517726cfc Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Wed, 29 Aug 2018 15:26:24 +0200 Subject: Add confirmation dialog when posting media without description Fixes #211 --- .../flavours/glitch/features/composer/index.js | 38 +++++++++++++++++++--- .../glitch/features/local_settings/page/index.js | 8 +++++ .../flavours/glitch/reducers/local_settings.js | 1 + 3 files changed, 42 insertions(+), 5 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js index cf6f45b34..b823f966f 100644 --- a/app/javascript/flavours/glitch/features/composer/index.js +++ b/app/javascript/flavours/glitch/features/composer/index.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import { defineMessages } from 'react-intl'; const APPROX_HASHTAG_RE = /(?:^|[^\/\)\w])#(\S+)/i; @@ -49,6 +50,13 @@ import { assignHandlers } from 'flavours/glitch/util/react_helpers'; import { wrap } from 'flavours/glitch/util/redux_helpers'; import { privacyPreference } from 'flavours/glitch/util/privacy_preference'; +const messages = defineMessages({ + missingDescriptionMessage: { id: 'confirmations.missing_media_description.message', + defaultMessage: 'At least one media attachment is lacking a description. Consider describing all media attachments for the visually impaired before sending your toot.' }, + missingDescriptionConfirm: { id: 'confirmations.missing_media_description.confirm', + defaultMessage: 'Send anyway' }, +}); + // State mapping. function mapStateToProps (state) { const spoilersAlwaysOn = state.getIn(['local_settings', 'always_show_spoilers_field']); @@ -93,11 +101,12 @@ function mapStateToProps (state) { text: state.getIn(['compose', 'text']), anyMedia: state.getIn(['compose', 'media_attachments']).size > 0, spoilersAlwaysOn: spoilersAlwaysOn, + mediaDescriptionConfirmation: state.getIn(['local_settings', 'confirm_missing_media_description']), }; }; // Dispatch mapping. -const mapDispatchToProps = (dispatch) => ({ +const mapDispatchToProps = (dispatch, { intl }) => ({ onCancelReply() { dispatch(cancelReplyCompose()); }, @@ -149,6 +158,13 @@ const mapDispatchToProps = (dispatch) => ({ onSelectSuggestion(position, token, suggestion) { dispatch(selectComposeSuggestion(position, token, suggestion)); }, + onMediaDescriptionConfirm() { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.missingDescriptionMessage), + confirm: intl.formatMessage(messages.missingDescriptionConfirm), + onConfirm: () => dispatch(submitCompose()), + })); + }, onSubmit() { dispatch(submitCompose()); }, @@ -212,8 +228,11 @@ const handlers = { onSubmit, isSubmitting, isUploading, + media, anyMedia, text, + mediaDescriptionConfirmation, + onMediaDescriptionConfirm, } = this.props; // If something changes inside the textarea, then we update the @@ -227,8 +246,15 @@ const handlers = { return; } - // Submits the status. - if (onSubmit) { + // Submit unless there are media with missing descriptions + if (mediaDescriptionConfirmation && onMediaDescriptionConfirm && media && media.some(item => !item.get('description'))) { + const firstWithoutDescription = media.findIndex(item => !item.get('description')); + const inputs = document.querySelectorAll('.composer--upload_form--item input'); + if (inputs.length == media.size && firstWithoutDescription !== -1) { + inputs[firstWithoutDescription].focus(); + } + onMediaDescriptionConfirm(); + } else if (onSubmit) { onSubmit(); } }, @@ -495,6 +521,9 @@ Composer.propTypes = { suggestionToken: PropTypes.string, suggestions: ImmutablePropTypes.list, text: PropTypes.string, + anyMedia: PropTypes.bool, + spoilersAlwaysOn: PropTypes.bool, + mediaDescriptionConfirmation: PropTypes.bool, // Dispatch props. onCancelReply: PropTypes.func, @@ -517,8 +546,7 @@ Composer.propTypes = { onUndoUpload: PropTypes.func, onUnmount: PropTypes.func, onUpload: PropTypes.func, - anyMedia: PropTypes.bool, - spoilersAlwaysOn: PropTypes.bool, + onMediaDescriptionConfirm: PropTypes.func, }; // Connecting and export. diff --git a/app/javascript/flavours/glitch/features/local_settings/page/index.js b/app/javascript/flavours/glitch/features/local_settings/page/index.js index ad5c11979..1e61c67c0 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js @@ -83,6 +83,14 @@ export default class LocalSettingsPage extends React.PureComponent { > + + + Date: Thu, 30 Aug 2018 11:46:45 +0200 Subject: Restrict querySelectorAll to the upload form component --- .../flavours/glitch/features/composer/index.js | 17 +++++++++++++---- .../glitch/features/composer/upload_form/index.js | 4 +++- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js index b823f966f..bc409f0a3 100644 --- a/app/javascript/flavours/glitch/features/composer/index.js +++ b/app/javascript/flavours/glitch/features/composer/index.js @@ -222,7 +222,7 @@ const handlers = { // Submits the status. handleSubmit () { - const { textarea: { value } } = this; + const { textarea: { value }, uploadForm } = this; const { onChangeText, onSubmit, @@ -249,9 +249,11 @@ const handlers = { // Submit unless there are media with missing descriptions if (mediaDescriptionConfirmation && onMediaDescriptionConfirm && media && media.some(item => !item.get('description'))) { const firstWithoutDescription = media.findIndex(item => !item.get('description')); - const inputs = document.querySelectorAll('.composer--upload_form--item input'); - if (inputs.length == media.size && firstWithoutDescription !== -1) { - inputs[firstWithoutDescription].focus(); + if (uploadForm) { + const inputs = uploadForm.querySelectorAll('.composer--upload_form--item input'); + if (inputs.length == media.size && firstWithoutDescription !== -1) { + inputs[firstWithoutDescription].focus(); + } } onMediaDescriptionConfirm(); } else if (onSubmit) { @@ -259,6 +261,11 @@ const handlers = { } }, + // Sets a reference to the upload form. + handleRefUploadForm (uploadFormComponent) { + this.uploadForm = uploadFormComponent; + }, + // Sets a reference to the textarea. handleRefTextarea (textareaComponent) { if (textareaComponent) { @@ -365,6 +372,7 @@ class Composer extends React.Component { handleSecondarySubmit, handleSelect, handleSubmit, + handleRefUploadForm, handleRefTextarea, handleRefSpoilerText, } = this.handlers; @@ -455,6 +463,7 @@ class Composer extends React.Component { onRemove={onUndoUpload} progress={progress} uploading={isUploading} + handleRef={handleRefUploadForm} /> ) : null} +
{uploading ? : null} {media ? (
@@ -55,4 +56,5 @@ ComposerUploadForm.propTypes = { onRemove: PropTypes.func.isRequired, progress: PropTypes.number, uploading: PropTypes.bool, + handleRef: PropTypes.func, }; -- cgit From 70c308c4aa97acaaf6354420bee7d843ddf97d13 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 31 Aug 2018 13:31:45 +0200 Subject: [Glitch] When search enabled, display hint in search popout Port 7901f9f63e156732ab10154c34f3c2d188471a9d to glitch-soc --- .../flavours/glitch/features/drawer/search/popout/index.js | 7 ++++++- app/javascript/flavours/glitch/features/ui/components/tabs_bar.js | 2 +- app/javascript/flavours/glitch/util/initial_state.js | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/drawer/search/popout/index.js b/app/javascript/flavours/glitch/features/drawer/search/popout/index.js index 6219f46ca..fec090b64 100644 --- a/app/javascript/flavours/glitch/features/drawer/search/popout/index.js +++ b/app/javascript/flavours/glitch/features/drawer/search/popout/index.js @@ -9,6 +9,7 @@ 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({ @@ -28,6 +29,10 @@ const messages = defineMessages({ 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', @@ -92,7 +97,7 @@ export default function DrawerSearchPopout ({ style }) { - + { searchEnabled ? : }
)} diff --git a/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js b/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js index 89b455dd8..257178439 100644 --- a/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js +++ b/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js @@ -13,7 +13,7 @@ export const links = [ , , - , + , ]; export function getIndex (path) { diff --git a/app/javascript/flavours/glitch/util/initial_state.js b/app/javascript/flavours/glitch/util/initial_state.js index 2c4ab9091..236ea1c3a 100644 --- a/app/javascript/flavours/glitch/util/initial_state.js +++ b/app/javascript/flavours/glitch/util/initial_state.js @@ -19,6 +19,7 @@ export const boostModal = getMeta('boost_modal'); export const favouriteModal = getMeta('favourite_modal'); export const deleteModal = getMeta('delete_modal'); export const me = getMeta('me'); +export const searchEnabled = getMeta('search_enabled'); export const maxChars = (initialState && initialState.max_toot_chars) || 500; export default initialState; -- cgit From 5f035a2a1acbd6072b556837b5dd647a0fdbf263 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 31 Aug 2018 13:34:11 +0200 Subject: [Glitch] Move "compose" on mobile to floating action button Port e72db6d9dd53a9d44f641bdf6bce7e64548e7d94 to glitch-soc --- .../glitch/features/ui/components/columns_area.js | 17 +++++++++++---- .../glitch/features/ui/components/tabs_bar.js | 1 - .../flavours/glitch/styles/components/columns.scss | 24 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/ui/components/columns_area.js b/app/javascript/flavours/glitch/features/ui/components/columns_area.js index ee71e514a..8fde279c7 100644 --- a/app/javascript/flavours/glitch/features/ui/components/columns_area.js +++ b/app/javascript/flavours/glitch/features/ui/components/columns_area.js @@ -6,6 +6,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import ReactSwipeableViews from 'react-swipeable-views'; import { links, getIndex, getLink } from './tabs_bar'; +import { Link } from 'react-router-dom'; import BundleContainer from '../containers/bundle_container'; import ColumnLoading from './column_loading'; @@ -153,11 +154,19 @@ export default class ColumnsArea extends ImmutablePureComponent { this.pendingIndex = null; if (singleColumn) { - return columnIndex !== -1 ? ( - + const floatingActionButton = this.context.router.history.location.pathname === '/statuses/new' ? null : ; + + return columnIndex !== -1 ? [ + {links.map(this.renderView)} - - ) :
{children}
; +
, + + floatingActionButton, + ] : [ +
{children}
, + + floatingActionButton, + ]; } return ( diff --git a/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js b/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js index 257178439..81d5f5a7d 100644 --- a/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js +++ b/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js @@ -6,7 +6,6 @@ import { debounce } from 'lodash'; import { isUserTouching } from 'flavours/glitch/util/is_mobile'; export const links = [ - , , , diff --git a/app/javascript/flavours/glitch/styles/components/columns.scss b/app/javascript/flavours/glitch/styles/components/columns.scss index c61cd038f..86c77f980 100644 --- a/app/javascript/flavours/glitch/styles/components/columns.scss +++ b/app/javascript/flavours/glitch/styles/components/columns.scss @@ -503,3 +503,27 @@ margin-left: 5px; } } + +.floating-action-button { + position: fixed; + display: flex; + justify-content: center; + align-items: center; + width: 3.9375rem; + height: 3.9375rem; + bottom: 1.3125rem; + right: 1.3125rem; + background: darken($ui-highlight-color, 3%); + color: $white; + border-radius: 50%; + font-size: 21px; + line-height: 21px; + text-decoration: none; + box-shadow: 2px 3px 9px rgba($base-shadow-color, 0.4); + + &:hover, + &:focus, + &:active { + background: lighten($ui-highlight-color, 7%); + } +} -- cgit From 76a3f373e3bfa94df13272aed9b92a50ed912928 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 31 Aug 2018 13:34:58 +0200 Subject: [Glitch] Use withRouter for TabsBar Port 61e62757816cd8cfe38944d509f8ec13d7d86912 to glitch-soc --- .../flavours/glitch/features/ui/components/tabs_bar.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js b/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js index 81d5f5a7d..93a74faae 100644 --- a/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js +++ b/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { NavLink } from 'react-router-dom'; +import { NavLink, withRouter } from 'react-router-dom'; import { FormattedMessage, injectIntl } from 'react-intl'; import { debounce } from 'lodash'; import { isUserTouching } from 'flavours/glitch/util/is_mobile'; @@ -24,14 +24,12 @@ export function getLink (index) { } @injectIntl -export default class TabsBar extends React.Component { - - static contextTypes = { - router: PropTypes.object.isRequired, - } +@withRouter +export default class TabsBar extends React.PureComponent { static propTypes = { intl: PropTypes.object.isRequired, + history: PropTypes.object.isRequired, } setRef = ref => { @@ -59,7 +57,7 @@ export default class TabsBar extends React.Component { const listener = debounce(() => { nextTab.removeEventListener('transitionend', listener); - this.context.router.history.push(to); + this.props.history.push(to); }, 50); nextTab.addEventListener('transitionend', listener); -- cgit From 37a00d4c1dd3aa1b66f60d296fa71fa3201a32da Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 31 Aug 2018 13:54:25 +0200 Subject: [Glitch] Add search item to tab bar for mobile devices Port c9cbb8de703e321c0d152813a2e22471ffe5eef7 to glitch-soc --- app/javascript/flavours/glitch/features/drawer/index.js | 4 +++- app/javascript/flavours/glitch/features/ui/components/tabs_bar.js | 1 + app/javascript/flavours/glitch/features/ui/index.js | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/drawer/index.js b/app/javascript/flavours/glitch/features/drawer/index.js index 1679e9a4b..eb051ba42 100644 --- a/app/javascript/flavours/glitch/features/drawer/index.js +++ b/app/javascript/flavours/glitch/features/drawer/index.js @@ -86,6 +86,7 @@ class Drawer extends React.Component { searchHidden, searchValue, submitted, + isSearchPage, } = this.props; const computedClass = classNames('drawer', `mbstobon-${elefriend}`); @@ -110,7 +111,7 @@ class Drawer extends React.Component { />
- + {!isSearchPage && } {multiColumn &&
); -- cgit From 130bdb5ee8c0689a44b353be9bc0ca78b75bdf2e Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 31 Aug 2018 16:41:58 +0200 Subject: [Glitch] Show compose form on delete & redraft when in mobile layout Port 025fbb8285cdedf495d9e4d015db611b0c622cbb to glitch-soc --- app/javascript/flavours/glitch/actions/statuses.js | 6 +++++- app/javascript/flavours/glitch/components/status_action_bar.js | 4 ++-- app/javascript/flavours/glitch/containers/status_container.js | 6 +++--- .../flavours/glitch/features/status/components/action_bar.js | 4 ++-- app/javascript/flavours/glitch/features/status/index.js | 6 +++--- 5 files changed, 15 insertions(+), 11 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/actions/statuses.js b/app/javascript/flavours/glitch/actions/statuses.js index c6d8486f9..fa8845002 100644 --- a/app/javascript/flavours/glitch/actions/statuses.js +++ b/app/javascript/flavours/glitch/actions/statuses.js @@ -79,7 +79,7 @@ export function redraft(status) { }; }; -export function deleteStatus(id, withRedraft = false) { +export function deleteStatus(id, router, withRedraft = false) { return (dispatch, getState) => { const status = getState().getIn(['statuses', id]); @@ -91,6 +91,10 @@ export function deleteStatus(id, withRedraft = false) { if (withRedraft) { dispatch(redraft(status)); + + if (!getState().getIn(['compose', 'mounted'])) { + router.push('/statuses/new'); + } } }).catch(error => { dispatch(deleteStatusFail(id, error)); diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js index 8a840030a..e26bdb717 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.js @@ -102,11 +102,11 @@ export default class StatusActionBar extends ImmutablePureComponent { } handleDeleteClick = () => { - this.props.onDelete(this.props.status); + this.props.onDelete(this.props.status, this.context.router.history); } handleRedraftClick = () => { - this.props.onDelete(this.props.status, true); + this.props.onDelete(this.props.status, this.context.router.history, true); } handlePinClick = () => { diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index 48cb76f86..5ac92ea39 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -122,14 +122,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(openModal('EMBED', { url: status.get('url') })); }, - onDelete (status, withRedraft = false) { + onDelete (status, history, withRedraft = false) { if (!deleteModal) { - dispatch(deleteStatus(status.get('id'), withRedraft)); + dispatch(deleteStatus(status.get('id'), history, withRedraft)); } else { dispatch(openModal('CONFIRM', { message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)), + onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), })); } }, diff --git a/app/javascript/flavours/glitch/features/status/components/action_bar.js b/app/javascript/flavours/glitch/features/status/components/action_bar.js index 99e2c594b..413833a79 100644 --- a/app/javascript/flavours/glitch/features/status/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/status/components/action_bar.js @@ -70,11 +70,11 @@ export default class ActionBar extends React.PureComponent { } handleDeleteClick = () => { - this.props.onDelete(this.props.status); + this.props.onDelete(this.props.status, this.context.router.history); } handleRedraftClick = () => { - this.props.onDelete(this.props.status, true); + this.props.onDelete(this.props.status, this.context.router.history, true); } handleDirectClick = () => { diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index ddc2f820a..1fceaa5ea 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -159,16 +159,16 @@ export default class Status extends ImmutablePureComponent { } } - handleDeleteClick = (status, withRedraft = false) => { + handleDeleteClick = (status, history, withRedraft = false) => { const { dispatch, intl } = this.props; if (!deleteModal) { - dispatch(deleteStatus(status.get('id'), withRedraft)); + dispatch(deleteStatus(status.get('id'), history, withRedraft)); } else { dispatch(openModal('CONFIRM', { message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)), + onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), })); } } -- cgit From 9d2739d74da26b725f03eb5a19a93c6041714be7 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 28 Aug 2018 14:10:26 +0200 Subject: Add a setting to automatically unfold all content warnings --- app/javascript/flavours/glitch/components/status.js | 1 + .../glitch/features/local_settings/navigation/index.js | 17 ++++++++++++----- .../glitch/features/local_settings/page/index.js | 13 +++++++++++++ app/javascript/flavours/glitch/features/status/index.js | 4 ++-- .../flavours/glitch/reducers/local_settings.js | 3 +++ 5 files changed, 31 insertions(+), 7 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 1ac5a4b3e..e0d591ff6 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -56,6 +56,7 @@ export default class Status extends ImmutablePureComponent { state = { isCollapsed: false, autoCollapsed: false, + isExpanded: this.props.settings.getIn(['content_warnings', 'auto_unfold']), } // Avoid checking props that are functions (and whose equality will always diff --git a/app/javascript/flavours/glitch/features/local_settings/navigation/index.js b/app/javascript/flavours/glitch/features/local_settings/navigation/index.js index fc2167c0c..0c1040290 100644 --- a/app/javascript/flavours/glitch/features/local_settings/navigation/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/navigation/index.js @@ -10,6 +10,7 @@ import LocalSettingsNavigationItem from './item'; const messages = defineMessages({ general: { id: 'settings.general', defaultMessage: 'General' }, + content_warnings: { id: 'settings.content_warnings', defaultMessage: 'Content Warnings' }, collapsed: { id: 'settings.collapsed_statuses', defaultMessage: 'Collapsed toots' }, media: { id: 'settings.media', defaultMessage: 'Media' }, preferences: { id: 'settings.preferences', defaultMessage: 'Preferences' }, @@ -42,25 +43,31 @@ export default class LocalSettingsNavigation extends React.PureComponent { active={index === 1} index={1} onNavigate={onNavigate} - title={intl.formatMessage(messages.collapsed)} + title={intl.formatMessage(messages.content_warnings)} /> + diff --git a/app/javascript/flavours/glitch/features/local_settings/page/index.js b/app/javascript/flavours/glitch/features/local_settings/page/index.js index 1e61c67c0..37396d970 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js @@ -122,6 +122,19 @@ export default class LocalSettingsPage extends React.PureComponent { ), + ({ onChange, settings }) => ( +
+

+ + + +
+ ), ({ onChange, settings }) => (

diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index 1fceaa5ea..060f2f345 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -82,8 +82,8 @@ export default class Status extends ImmutablePureComponent { state = { fullscreen: false, - isExpanded: false, - threadExpanded: null, + isExpanded: this.props.settings.getIn(['content_warnings', 'auto_unfold']), + threadExpanded: undefined, }; componentWillMount () { diff --git a/app/javascript/flavours/glitch/reducers/local_settings.js b/app/javascript/flavours/glitch/reducers/local_settings.js index ebe0b1292..ce33cac83 100644 --- a/app/javascript/flavours/glitch/reducers/local_settings.js +++ b/app/javascript/flavours/glitch/reducers/local_settings.js @@ -14,6 +14,9 @@ const initialState = ImmutableMap({ show_reply_count : false, always_show_spoilers_field: false, confirm_missing_media_description: false, + content_warnings : ImmutableMap({ + auto_unfold : false, + }), collapsed : ImmutableMap({ enabled : true, auto : ImmutableMap({ -- cgit From 5c400a28422121df01fc5ae73bc201f3b9aa5288 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 28 Aug 2018 17:15:50 +0200 Subject: Allow text inputs in local settings dialog --- .../features/local_settings/page/item/index.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/local_settings/page/item/index.js b/app/javascript/flavours/glitch/features/local_settings/page/item/index.js index 66e84dfe1..fe237f11e 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/item/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/item/index.js @@ -19,18 +19,20 @@ export default class LocalSettingsPageItem extends React.PureComponent { message: PropTypes.string.isRequired, })), settings: ImmutablePropTypes.map.isRequired, + placeholder: PropTypes.string, }; handleChange = e => { const { target } = e; - const { item, onChange, options } = this.props; + const { item, onChange, options, placeholder } = this.props; if (options && options.length > 0) onChange(item, target.value); + else if (placeholder) onChange(item, target.value); else onChange(item, target.checked); } render () { const { handleChange } = this; - const { settings, item, id, options, children, dependsOn, dependsOnNot } = this.props; + const { settings, item, id, options, children, dependsOn, dependsOnNot, placeholder } = this.props; let enabled = true; if (dependsOn) { @@ -70,6 +72,22 @@ export default class LocalSettingsPageItem extends React.PureComponent {

); + } else if (placeholder) { + return ( + + ); } else return (
), - ({ onChange, settings }) => ( + ({ intl, onChange, settings }) => (

+ + +
), ({ onChange, settings }) => ( diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index 060f2f345..3d309976a 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -38,6 +38,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { HotKeys } from 'react-hotkeys'; import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/util/initial_state'; import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from 'flavours/glitch/util/fullscreen'; +import { autoUnfoldCW } from 'flavours/glitch/util/content_warning'; const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, @@ -82,7 +83,7 @@ export default class Status extends ImmutablePureComponent { state = { fullscreen: false, - isExpanded: this.props.settings.getIn(['content_warnings', 'auto_unfold']), + isExpanded: undefined, threadExpanded: undefined, }; @@ -95,9 +96,14 @@ export default class Status extends ImmutablePureComponent { } componentWillReceiveProps (nextProps) { + if (this.state.isExpanded === undefined) { + const isExpanded = autoUnfoldCW(nextProps.settings, nextProps.status); + if (isExpanded !== undefined) this.setState({ isExpanded: isExpanded }); + } if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) { this._scrolledIntoView = false; this.props.dispatch(fetchStatus(nextProps.params.statusId)); + this.setState({ isExpanded: autoUnfoldCW(nextProps.settings, nextProps.status) }); } } diff --git a/app/javascript/flavours/glitch/reducers/local_settings.js b/app/javascript/flavours/glitch/reducers/local_settings.js index ce33cac83..063ae3943 100644 --- a/app/javascript/flavours/glitch/reducers/local_settings.js +++ b/app/javascript/flavours/glitch/reducers/local_settings.js @@ -16,6 +16,7 @@ const initialState = ImmutableMap({ confirm_missing_media_description: false, content_warnings : ImmutableMap({ auto_unfold : false, + filter : null, }), collapsed : ImmutableMap({ enabled : true, diff --git a/app/javascript/flavours/glitch/util/content_warning.js b/app/javascript/flavours/glitch/util/content_warning.js new file mode 100644 index 000000000..29e221c8e --- /dev/null +++ b/app/javascript/flavours/glitch/util/content_warning.js @@ -0,0 +1,19 @@ +export function autoUnfoldCW (settings, status) { + if (!settings.getIn(['content_warnings', 'auto_unfold'])) { + return false; + } + + const rawRegex = settings.getIn(['content_warnings', 'filter']); + let regex = null; + + try { + regex = rawRegex && new RegExp(rawRegex.trim(), 'i'); + } catch (e) { + // Bad regex, don't affect filters + } + + if (!(status && regex)) { + return undefined; + } + return !regex.test(status.get('spoiler_text')); +} -- cgit From cc7adf7e842b662fafc1eb1a9de3b7a450abbd1a Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 1 Sep 2018 09:36:59 +0200 Subject: Fix composer not displaying on chrome mobile (fixes #696) --- app/javascript/flavours/glitch/styles/components/drawer.scss | 3 --- 1 file changed, 3 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/styles/components/drawer.scss b/app/javascript/flavours/glitch/styles/components/drawer.scss index 0432b233a..6a9af4490 100644 --- a/app/javascript/flavours/glitch/styles/components/drawer.scss +++ b/app/javascript/flavours/glitch/styles/components/drawer.scss @@ -5,7 +5,6 @@ padding: 10px 5px; width: 300px; flex: none; - contain: strict; &:first-child { padding-left: 10px; @@ -49,7 +48,6 @@ background: lighten($ui-base-color, 13%); overflow-x: hidden; overflow-y: auto; - contain: strict; & > .mastodon { flex: 1; @@ -253,7 +251,6 @@ background: $ui-base-color; overflow-x: hidden; overflow-y: auto; - contain: strict; & > header { border-bottom: 1px solid darken($ui-base-color, 4%); -- cgit From e915bc3e9e32e34bf80d1bd66ee3f80d2ca37969 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 3 Sep 2018 13:32:35 +0200 Subject: Fixes columns scrolling to top when opening media modal Fixes #700 --- app/javascript/flavours/glitch/components/scrollable_list.js | 6 +++++- app/javascript/flavours/glitch/features/account_timeline/index.js | 5 ----- .../flavours/glitch/features/bookmarked_statuses/index.js | 5 ----- app/javascript/flavours/glitch/features/community_timeline/index.js | 5 ----- app/javascript/flavours/glitch/features/direct_timeline/index.js | 5 ----- app/javascript/flavours/glitch/features/domain_blocks/index.js | 6 +----- .../flavours/glitch/features/favourited_statuses/index.js | 5 ----- app/javascript/flavours/glitch/features/favourites/index.js | 6 +++++- app/javascript/flavours/glitch/features/follow_requests/index.js | 6 +++++- app/javascript/flavours/glitch/features/followers/index.js | 6 +++++- app/javascript/flavours/glitch/features/hashtag_timeline/index.js | 5 ----- app/javascript/flavours/glitch/features/mutes/index.js | 6 +++++- app/javascript/flavours/glitch/features/pinned_statuses/index.js | 5 ----- app/javascript/flavours/glitch/features/public_timeline/index.js | 5 ----- app/javascript/flavours/glitch/features/reblogs/index.js | 6 +++++- .../flavours/glitch/features/standalone/community_timeline/index.js | 5 ----- .../flavours/glitch/features/standalone/hashtag_timeline/index.js | 5 ----- 17 files changed, 31 insertions(+), 61 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index b96b4dd98..a677cbf5b 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -149,6 +149,10 @@ export default class ScrollableList extends PureComponent { this.props.onLoadMore(); } + defaultShouldUpdateScroll = (prevRouterProps, { location }) => { + return !(location.state && location.state.mastodonModalOpen); + } + render () { const { children, scrollKey, trackScroll, shouldUpdateScroll, isLoading, hasMore, prepend, emptyMessage, onLoadMore } = this.props; const { fullscreen } = this.state; @@ -190,7 +194,7 @@ export default class ScrollableList extends PureComponent { if (trackScroll) { return ( - + {scrollableArea} ); diff --git a/app/javascript/flavours/glitch/features/account_timeline/index.js b/app/javascript/flavours/glitch/features/account_timeline/index.js index 20ba0a1b1..2216f9153 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/index.js +++ b/app/javascript/flavours/glitch/features/account_timeline/index.js @@ -60,10 +60,6 @@ export default class AccountTimeline extends ImmutablePureComponent { this.props.dispatch(expandAccountTimeline(this.props.params.accountId, { maxId, withReplies: this.props.withReplies })); } - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { statusIds, featuredStatusIds, isLoading, hasMore } = this.props; @@ -87,7 +83,6 @@ export default class AccountTimeline extends ImmutablePureComponent { isLoading={isLoading} hasMore={hasMore} onLoadMore={this.handleLoadMore} - shouldUpdateScroll={this.shouldUpdateScroll} /> ); diff --git a/app/javascript/flavours/glitch/features/bookmarked_statuses/index.js b/app/javascript/flavours/glitch/features/bookmarked_statuses/index.js index f1b4f947e..9468ad81d 100644 --- a/app/javascript/flavours/glitch/features/bookmarked_statuses/index.js +++ b/app/javascript/flavours/glitch/features/bookmarked_statuses/index.js @@ -66,10 +66,6 @@ export default class Bookmarks extends ImmutablePureComponent { this.props.dispatch(expandBookmarkedStatuses()); }, 300, { leading: true }) - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props; const pinned = !!columnId; @@ -91,7 +87,6 @@ export default class Bookmarks extends ImmutablePureComponent { trackScroll={!pinned} statusIds={statusIds} scrollKey={`bookmarked_statuses-${columnId}`} - shouldUpdateScroll={this.shouldUpdateScroll} hasMore={hasMore} isLoading={isLoading} onLoadMore={this.handleLoadMore} diff --git a/app/javascript/flavours/glitch/features/community_timeline/index.js b/app/javascript/flavours/glitch/features/community_timeline/index.js index e5006b4d3..b5843ca16 100644 --- a/app/javascript/flavours/glitch/features/community_timeline/index.js +++ b/app/javascript/flavours/glitch/features/community_timeline/index.js @@ -71,10 +71,6 @@ export default class CommunityTimeline extends React.PureComponent { this.props.dispatch(expandCommunityTimeline({ maxId })); } - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { intl, hasUnread, columnId, multiColumn } = this.props; const pinned = !!columnId; @@ -97,7 +93,6 @@ export default class CommunityTimeline extends React.PureComponent { } diff --git a/app/javascript/flavours/glitch/features/direct_timeline/index.js b/app/javascript/flavours/glitch/features/direct_timeline/index.js index 25af49342..418db7c79 100644 --- a/app/javascript/flavours/glitch/features/direct_timeline/index.js +++ b/app/javascript/flavours/glitch/features/direct_timeline/index.js @@ -71,10 +71,6 @@ export default class DirectTimeline extends React.PureComponent { this.props.dispatch(expandDirectTimeline({ maxId })); } - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { intl, hasUnread, columnId, multiColumn } = this.props; const pinned = !!columnId; @@ -97,7 +93,6 @@ export default class DirectTimeline extends React.PureComponent { } diff --git a/app/javascript/flavours/glitch/features/domain_blocks/index.js b/app/javascript/flavours/glitch/features/domain_blocks/index.js index 8b023e0bc..3b29e2a26 100644 --- a/app/javascript/flavours/glitch/features/domain_blocks/index.js +++ b/app/javascript/flavours/glitch/features/domain_blocks/index.js @@ -40,10 +40,6 @@ export default class Blocks extends ImmutablePureComponent { this.props.dispatch(expandDomainBlocks()); }, 300, { leading: true }); - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { intl, domains } = this.props; @@ -58,7 +54,7 @@ export default class Blocks extends ImmutablePureComponent { return ( - + {domains.map(domain => )} diff --git a/app/javascript/flavours/glitch/features/favourited_statuses/index.js b/app/javascript/flavours/glitch/features/favourited_statuses/index.js index 644493183..d8fa1b84e 100644 --- a/app/javascript/flavours/glitch/features/favourited_statuses/index.js +++ b/app/javascript/flavours/glitch/features/favourited_statuses/index.js @@ -66,10 +66,6 @@ export default class Favourites extends ImmutablePureComponent { this.props.dispatch(expandFavouritedStatuses()); }, 300, { leading: true }) - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props; const pinned = !!columnId; @@ -91,7 +87,6 @@ export default class Favourites extends ImmutablePureComponent { trackScroll={!pinned} statusIds={statusIds} scrollKey={`favourited_statuses-${columnId}`} - shouldUpdateScroll={this.shouldUpdateScroll} hasMore={hasMore} isLoading={isLoading} onLoadMore={this.handleLoadMore} diff --git a/app/javascript/flavours/glitch/features/favourites/index.js b/app/javascript/flavours/glitch/features/favourites/index.js index 055a15ccb..cf8b31eb3 100644 --- a/app/javascript/flavours/glitch/features/favourites/index.js +++ b/app/javascript/flavours/glitch/features/favourites/index.js @@ -33,6 +33,10 @@ export default class Favourites extends ImmutablePureComponent { } } + shouldUpdateScroll = (prevRouterProps, { location }) => { + return !(location.state && location.state.mastodonModalOpen); + } + render () { const { accountIds } = this.props; @@ -48,7 +52,7 @@ export default class Favourites extends ImmutablePureComponent { - +
{accountIds.map(id => )}
diff --git a/app/javascript/flavours/glitch/features/follow_requests/index.js b/app/javascript/flavours/glitch/features/follow_requests/index.js index 04ff3f111..1e4633984 100644 --- a/app/javascript/flavours/glitch/features/follow_requests/index.js +++ b/app/javascript/flavours/glitch/features/follow_requests/index.js @@ -42,6 +42,10 @@ export default class FollowRequests extends ImmutablePureComponent { } } + shouldUpdateScroll = (prevRouterProps, { location }) => { + return !(location.state && location.state.mastodonModalOpen); + } + render () { const { intl, accountIds } = this.props; @@ -57,7 +61,7 @@ export default class FollowRequests extends ImmutablePureComponent { - +
{accountIds.map(id => diff --git a/app/javascript/flavours/glitch/features/followers/index.js b/app/javascript/flavours/glitch/features/followers/index.js index c42e0386c..cdde1775c 100644 --- a/app/javascript/flavours/glitch/features/followers/index.js +++ b/app/javascript/flavours/glitch/features/followers/index.js @@ -56,6 +56,10 @@ export default class Followers extends ImmutablePureComponent { this.props.dispatch(expandFollowers(this.props.params.accountId)); } + shouldUpdateScroll = (prevRouterProps, { location }) => { + return !(location.state && location.state.mastodonModalOpen); + } + render () { const { accountIds, hasMore } = this.props; @@ -77,7 +81,7 @@ export default class Followers extends ImmutablePureComponent { - +
diff --git a/app/javascript/flavours/glitch/features/hashtag_timeline/index.js b/app/javascript/flavours/glitch/features/hashtag_timeline/index.js index b3e8b7a6e..8f77ed42b 100644 --- a/app/javascript/flavours/glitch/features/hashtag_timeline/index.js +++ b/app/javascript/flavours/glitch/features/hashtag_timeline/index.js @@ -82,10 +82,6 @@ export default class HashtagTimeline extends React.PureComponent { this.props.dispatch(expandHashtagTimeline(this.props.params.id, { maxId })); } - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { hasUnread, columnId, multiColumn } = this.props; const { id } = this.props.params; @@ -110,7 +106,6 @@ export default class HashtagTimeline extends React.PureComponent { scrollKey={`hashtag_timeline-${columnId}`} timelineId={`hashtag:${id}`} onLoadMore={this.handleLoadMore} - shouldUpdateScroll={this.shouldUpdateScroll} emptyMessage={} /> diff --git a/app/javascript/flavours/glitch/features/mutes/index.js b/app/javascript/flavours/glitch/features/mutes/index.js index 87517eec9..d94c1d8ad 100644 --- a/app/javascript/flavours/glitch/features/mutes/index.js +++ b/app/javascript/flavours/glitch/features/mutes/index.js @@ -42,6 +42,10 @@ export default class Mutes extends ImmutablePureComponent { } } + shouldUpdateScroll = (prevRouterProps, { location }) => { + return !(location.state && location.state.mastodonModalOpen); + } + render () { const { intl, accountIds } = this.props; @@ -56,7 +60,7 @@ export default class Mutes extends ImmutablePureComponent { return ( - +
{accountIds.map(id => diff --git a/app/javascript/flavours/glitch/features/pinned_statuses/index.js b/app/javascript/flavours/glitch/features/pinned_statuses/index.js index e7fa7ac0d..f56d70176 100644 --- a/app/javascript/flavours/glitch/features/pinned_statuses/index.js +++ b/app/javascript/flavours/glitch/features/pinned_statuses/index.js @@ -41,10 +41,6 @@ export default class PinnedStatuses extends ImmutablePureComponent { this.column = c; } - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { intl, statusIds, hasMore } = this.props; @@ -54,7 +50,6 @@ export default class PinnedStatuses extends ImmutablePureComponent { diff --git a/app/javascript/flavours/glitch/features/public_timeline/index.js b/app/javascript/flavours/glitch/features/public_timeline/index.js index 3eb92cafa..a6c0b1688 100644 --- a/app/javascript/flavours/glitch/features/public_timeline/index.js +++ b/app/javascript/flavours/glitch/features/public_timeline/index.js @@ -71,10 +71,6 @@ export default class PublicTimeline extends React.PureComponent { this.props.dispatch(expandPublicTimeline({ maxId })); } - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { intl, columnId, hasUnread, multiColumn } = this.props; const pinned = !!columnId; @@ -99,7 +95,6 @@ export default class PublicTimeline extends React.PureComponent { onLoadMore={this.handleLoadMore} trackScroll={!pinned} scrollKey={`public_timeline-${columnId}`} - shouldUpdateScroll={this.shouldUpdateScroll} emptyMessage={} /> diff --git a/app/javascript/flavours/glitch/features/reblogs/index.js b/app/javascript/flavours/glitch/features/reblogs/index.js index 25b792b39..c0a65d1de 100644 --- a/app/javascript/flavours/glitch/features/reblogs/index.js +++ b/app/javascript/flavours/glitch/features/reblogs/index.js @@ -33,6 +33,10 @@ export default class Reblogs extends ImmutablePureComponent { } } + shouldUpdateScroll = (prevRouterProps, { location }) => { + return !(location.state && location.state.mastodonModalOpen); + } + render () { const { accountIds } = this.props; @@ -48,7 +52,7 @@ export default class Reblogs extends ImmutablePureComponent { - +
{accountIds.map(id => )}
diff --git a/app/javascript/flavours/glitch/features/standalone/community_timeline/index.js b/app/javascript/flavours/glitch/features/standalone/community_timeline/index.js index 08b9e9e57..c488f9541 100644 --- a/app/javascript/flavours/glitch/features/standalone/community_timeline/index.js +++ b/app/javascript/flavours/glitch/features/standalone/community_timeline/index.js @@ -47,10 +47,6 @@ export default class CommunityTimeline extends React.PureComponent { this.props.dispatch(expandCommunityTimeline({ maxId })); } - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { intl } = this.props; @@ -66,7 +62,6 @@ export default class CommunityTimeline extends React.PureComponent { timelineId='community' onLoadMore={this.handleLoadMore} scrollKey='standalone_public_timeline' - shouldUpdateScroll={this.shouldUpdateScroll} trackScroll={false} />
diff --git a/app/javascript/flavours/glitch/features/standalone/hashtag_timeline/index.js b/app/javascript/flavours/glitch/features/standalone/hashtag_timeline/index.js index d2b1971ec..dc02f1c91 100644 --- a/app/javascript/flavours/glitch/features/standalone/hashtag_timeline/index.js +++ b/app/javascript/flavours/glitch/features/standalone/hashtag_timeline/index.js @@ -41,10 +41,6 @@ export default class HashtagTimeline extends React.PureComponent { this.props.dispatch(expandHashtagTimeline(this.props.hashtag, { maxId })); } - shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) - } - render () { const { hashtag } = this.props; @@ -59,7 +55,6 @@ export default class HashtagTimeline extends React.PureComponent { -- cgit From 27ee42299b5eeecd6c4b5b6ec5b2b9652c7a4fd7 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 31 Aug 2018 19:47:53 +0200 Subject: [Glitch] Inactive header in main profile to match column Port 1bfe735d574fdbb01b1aea07db6c69fb3a32b90f to glitch-soc --- .../flavours/glitch/styles/containers.scss | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/styles/containers.scss b/app/javascript/flavours/glitch/styles/containers.scss index b5d79f4d7..17901f233 100644 --- a/app/javascript/flavours/glitch/styles/containers.scss +++ b/app/javascript/flavours/glitch/styles/containers.scss @@ -347,6 +347,23 @@ margin-bottom: 10px; box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); + &.inactive { + opacity: 0.5; + + .public-account-header__image, + .avatar { + filter: grayscale(100%); + } + + .logo-button { + background-color: $secondary-text-color; + + svg path:last-child { + fill: $secondary-text-color; + } + } + } + &__image { border-radius: 4px 4px 0 0; overflow: hidden; @@ -588,6 +605,10 @@ border-bottom: 4px solid $highlight-text-color; opacity: 1; } + + &.inactive::after { + border-bottom-color: $secondary-text-color; + } } &:hover { -- cgit From 8e862ecf8dfde495b0030fe16c856f69da60dd3f Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 3 Sep 2018 17:38:11 +0200 Subject: [Glitch] Add aria-label to floatingActionButton Port 7c12c7b1246b991c68f4b51573538e02b3968beb to glitch-soc --- .../flavours/glitch/features/ui/components/columns_area.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/ui/components/columns_area.js b/app/javascript/flavours/glitch/features/ui/components/columns_area.js index 8fde279c7..f87c078ec 100644 --- a/app/javascript/flavours/glitch/features/ui/components/columns_area.js +++ b/app/javascript/flavours/glitch/features/ui/components/columns_area.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { injectIntl } from 'react-intl'; +import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; @@ -30,6 +30,10 @@ const componentMap = { 'LIST': ListTimeline, }; +const messages = defineMessages({ + publish: { id: 'compose_form.publish', defaultMessage: 'Toot' }, +}); + @component => injectIntl(component, { withRef: true }) export default class ColumnsArea extends ImmutablePureComponent { @@ -147,14 +151,14 @@ export default class ColumnsArea extends ImmutablePureComponent { } render () { - const { columns, children, singleColumn } = this.props; + const { columns, children, singleColumn, intl } = this.props; const { shouldAnimate } = this.state; const columnIndex = getIndex(this.context.router.history.location.pathname); this.pendingIndex = null; if (singleColumn) { - const floatingActionButton = this.context.router.history.location.pathname === '/statuses/new' ? null : ; + const floatingActionButton = this.context.router.history.location.pathname === '/statuses/new' ? null : ; return columnIndex !== -1 ? [ -- cgit From b3fdd166e819819a7a8f7cfa540986af047c05fa Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 3 Sep 2018 17:30:55 +0200 Subject: [Glitch] Skip VS15 (Emoji textual presentation) Port a060beee726de5295e1f608231975a90b7709a0a to glitch-soc --- app/javascript/flavours/glitch/util/emoji/index.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/util/emoji/index.js b/app/javascript/flavours/glitch/util/emoji/index.js index c6416db2d..82a1ef89c 100644 --- a/app/javascript/flavours/glitch/util/emoji/index.js +++ b/app/javascript/flavours/glitch/util/emoji/index.js @@ -62,6 +62,10 @@ const emojify = (str, customEmojis = {}) => { const title = shortCode ? `:${shortCode}:` : ''; replacement = `${match}`; rend = i + match.length; + // If the matched character was followed by VS15 (for selecting text presentation), skip it. + if (str.codePointAt(rend) === 65038) { + rend += 1; + } } rtn += str.slice(0, i) + replacement; str = str.slice(rend); -- cgit From 6ad7dac79130bb7b68ccb703739167a737ed6b49 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 31 Aug 2018 12:10:38 +0200 Subject: Let the front-end know the current account is a moderator --- app/javascript/flavours/glitch/util/initial_state.js | 1 + app/serializers/initial_state_serializer.rb | 1 + 2 files changed, 2 insertions(+) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/util/initial_state.js b/app/javascript/flavours/glitch/util/initial_state.js index 236ea1c3a..fdf004527 100644 --- a/app/javascript/flavours/glitch/util/initial_state.js +++ b/app/javascript/flavours/glitch/util/initial_state.js @@ -21,5 +21,6 @@ export const deleteModal = getMeta('delete_modal'); export const me = getMeta('me'); export const searchEnabled = getMeta('search_enabled'); export const maxChars = (initialState && initialState.max_toot_chars) || 500; +export const isStaff = getMeta('is_staff'); export default initialState; diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 204a13b55..0845d0210 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -32,6 +32,7 @@ class InitialStateSerializer < ActiveModel::Serializer store[:auto_play_gif] = object.current_account.user.setting_auto_play_gif store[:display_sensitive_media] = object.current_account.user.setting_display_sensitive_media store[:reduce_motion] = object.current_account.user.setting_reduce_motion + store[:is_staff] = object.current_account.user.staff? end store -- cgit From bd437f80771f2700c62d45ad57cd76f1184ecfbf Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 31 Aug 2018 12:33:32 +0200 Subject: Add admin links to status and account menus (fixes #673) If the current logged-in user is an admin, add quick links to the admin interface in account and toot dropdown menu. Suggestion by @ashkitten --- app/javascript/flavours/glitch/components/status_action_bar.js | 9 ++++++++- .../flavours/glitch/features/account/components/action_bar.js | 8 +++++++- .../flavours/glitch/features/status/components/action_bar.js | 9 ++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js index e26bdb717..f7e741d2d 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.js @@ -5,7 +5,7 @@ import IconButton from './icon_button'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { me } from 'flavours/glitch/util/initial_state'; +import { me, isStaff } from 'flavours/glitch/util/initial_state'; import RelativeTimestamp from './relative_timestamp'; const messages = defineMessages({ @@ -31,6 +31,8 @@ const messages = defineMessages({ pin: { id: 'status.pin', defaultMessage: 'Pin on profile' }, unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' }, embed: { id: 'status.embed', defaultMessage: 'Embed' }, + admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, + admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' }, }); const obfuscatedCount = count => { @@ -186,6 +188,11 @@ export default class StatusActionBar extends ImmutablePureComponent { menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick }); menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); + if (isStaff) { + menu.push(null); + menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` }); + menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` }); + } } if (status.get('in_reply_to_id', null) === null) { diff --git a/app/javascript/flavours/glitch/features/account/components/action_bar.js b/app/javascript/flavours/glitch/features/account/components/action_bar.js index 9c80a470b..26717ee49 100644 --- a/app/javascript/flavours/glitch/features/account/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/account/components/action_bar.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import { Link } from 'react-router-dom'; import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; -import { me } from 'flavours/glitch/util/initial_state'; +import { me, isStaff } from 'flavours/glitch/util/initial_state'; const messages = defineMessages({ mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' }, @@ -25,6 +25,7 @@ const messages = defineMessages({ showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' }, unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' }, + admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, }); @injectIntl @@ -120,6 +121,11 @@ export default class ActionBar extends React.PureComponent { } } + if (account.get('id') !== me && isStaff) { + menu.push(null); + menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${account.get('id')}` }); + } + return (
{extraInfo} diff --git a/app/javascript/flavours/glitch/features/status/components/action_bar.js b/app/javascript/flavours/glitch/features/status/components/action_bar.js index 413833a79..009aa49eb 100644 --- a/app/javascript/flavours/glitch/features/status/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/status/components/action_bar.js @@ -4,7 +4,7 @@ import IconButton from 'flavours/glitch/components/icon_button'; import ImmutablePropTypes from 'react-immutable-proptypes'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import { defineMessages, injectIntl } from 'react-intl'; -import { me } from 'flavours/glitch/util/initial_state'; +import { me, isStaff } from 'flavours/glitch/util/initial_state'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, @@ -26,6 +26,8 @@ const messages = defineMessages({ pin: { id: 'status.pin', defaultMessage: 'Pin on profile' }, unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' }, embed: { id: 'status.embed', defaultMessage: 'Embed' }, + admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, + admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' }, }); @injectIntl @@ -146,6 +148,11 @@ export default class ActionBar extends React.PureComponent { menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick }); menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); + if (isStaff) { + menu.push(null); + menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` }); + menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` }); + } } const shareButton = ('share' in navigator) && status.get('visibility') === 'public' && ( -- cgit