From 967456b6a9ef34d8ffc386b89993d790c26089e1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 19 Jun 2019 23:42:38 +0200 Subject: [Glitch] Add audio uploads Port front-end changes from f7f23b4a19a84371f44ec5297125e96ba81681a1 to glitch-soc Signed-off-by: Thibaut Girka --- .../flavours/glitch/features/compose/containers/options_container.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features/compose/containers') diff --git a/app/javascript/flavours/glitch/features/compose/containers/options_container.js b/app/javascript/flavours/glitch/features/compose/containers/options_container.js index c8c7ecd43..df842f3bf 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/options_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/options_container.js @@ -16,7 +16,7 @@ function mapStateToProps (state) { acceptContentTypes: state.getIn(['media_attachments', 'accept_content_types']).toArray().join(','), resetFileKey: state.getIn(['compose', 'resetFileKey']), hasPoll: !!poll, - allowMedia: !poll && (media ? media.size < 4 && !media.some(item => item.get('type') === 'video') : true), + allowMedia: !poll && (media ? media.size < 4 && !media.some(item => ['video', 'audio'].includes(item.get('type'))) : true), hasMedia: media && !!media.size, allowPoll: !(media && !!media.size), showContentTypeChoice: state.getIn(['local_settings', 'show_content_type_choice']), -- cgit From 43698e08cad195df6f85aea26c710c2e1614a4a3 Mon Sep 17 00:00:00 2001 From: ThibG Date: Thu, 27 Jun 2019 21:12:26 +0200 Subject: [Glitch] Add message telling FTS is disabled when no toot can be found because of this Port ca8944728f4568bbef8edae99382cd44cbc144d6 to glitch-soc --- app/javascript/flavours/glitch/actions/search.js | 7 +++---- .../glitch/features/compose/components/search_results.js | 16 ++++++++++++++-- .../compose/containers/search_results_container.js | 1 + app/javascript/flavours/glitch/reducers/search.js | 3 ++- .../flavours/glitch/styles/components/search.scss | 5 +++++ 5 files changed, 25 insertions(+), 7 deletions(-) (limited to 'app/javascript/flavours/glitch/features/compose/containers') diff --git a/app/javascript/flavours/glitch/actions/search.js b/app/javascript/flavours/glitch/actions/search.js index b2d24e10b..9ce77b24b 100644 --- a/app/javascript/flavours/glitch/actions/search.js +++ b/app/javascript/flavours/glitch/actions/search.js @@ -48,7 +48,7 @@ export function submitSearch() { dispatch(importFetchedStatuses(response.data.statuses)); } - dispatch(fetchSearchSuccess(response.data)); + dispatch(fetchSearchSuccess(response.data, value)); dispatch(fetchRelationships(response.data.accounts.map(item => item.id))); }).catch(error => { dispatch(fetchSearchFail(error)); @@ -62,12 +62,11 @@ export function fetchSearchRequest() { }; }; -export function fetchSearchSuccess(results) { +export function fetchSearchSuccess(results, searchTerm) { return { type: SEARCH_FETCH_SUCCESS, results, - accounts: results.accounts, - statuses: results.statuses, + searchTerm, }; }; diff --git a/app/javascript/flavours/glitch/features/compose/components/search_results.js b/app/javascript/flavours/glitch/features/compose/components/search_results.js index 69df8cdc9..dd99f3430 100644 --- a/app/javascript/flavours/glitch/features/compose/components/search_results.js +++ b/app/javascript/flavours/glitch/features/compose/components/search_results.js @@ -7,6 +7,7 @@ import StatusContainer from 'flavours/glitch/containers/status_container'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Hashtag from 'flavours/glitch/components/hashtag'; import Icon from 'flavours/glitch/components/icon'; +import { searchEnabled } from 'flavours/glitch/util/initial_state'; const messages = defineMessages({ dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' }, @@ -20,6 +21,7 @@ class SearchResults extends ImmutablePureComponent { suggestions: ImmutablePropTypes.list.isRequired, fetchSuggestions: PropTypes.func.isRequired, dismissSuggestion: PropTypes.func.isRequired, + searchTerm: PropTypes.string, intl: PropTypes.object.isRequired, }; @@ -27,8 +29,8 @@ class SearchResults extends ImmutablePureComponent { this.props.fetchSuggestions(); } - render() { - const { intl, results, suggestions, dismissSuggestion } = this.props; + render () { + const { intl, results, suggestions, dismissSuggestion, searchTerm } = this.props; if (results.isEmpty() && !suggestions.isEmpty()) { return ( @@ -51,6 +53,16 @@ class SearchResults extends ImmutablePureComponent { ); + } else if(results.get('statuses') && results.get('statuses').size === 0 && !searchEnabled && !(searchTerm.startsWith('@') || searchTerm.startsWith('#') || searchTerm.includes(' '))) { + statuses = ( +
+
+ +
+ +
+
+ ); } let accounts, statuses, hashtags; diff --git a/app/javascript/flavours/glitch/features/compose/containers/search_results_container.js b/app/javascript/flavours/glitch/features/compose/containers/search_results_container.js index f9637861a..e4d5f3420 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/search_results_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/search_results_container.js @@ -5,6 +5,7 @@ import { fetchSuggestions, dismissSuggestion } from '../../../actions/suggestion const mapStateToProps = state => ({ results: state.getIn(['search', 'results']), suggestions: state.getIn(['suggestions', 'items']), + searchTerm: state.getIn(['search', 'searchTerm']), }); const mapDispatchToProps = dispatch => ({ diff --git a/app/javascript/flavours/glitch/reducers/search.js b/app/javascript/flavours/glitch/reducers/search.js index 9a525bf47..1c32a5b9f 100644 --- a/app/javascript/flavours/glitch/reducers/search.js +++ b/app/javascript/flavours/glitch/reducers/search.js @@ -16,6 +16,7 @@ const initialState = ImmutableMap({ submitted: false, hidden: false, results: ImmutableMap(), + searchTerm: '', }); export default function search(state = initialState, action) { @@ -40,7 +41,7 @@ export default function search(state = initialState, action) { accounts: ImmutableList(action.results.accounts.map(item => item.id)), statuses: ImmutableList(action.results.statuses.map(item => item.id)), hashtags: fromJS(action.results.hashtags), - })).set('submitted', true); + })).set('submitted', true).set('searchTerm', action.searchTerm); default: return state; } diff --git a/app/javascript/flavours/glitch/styles/components/search.scss b/app/javascript/flavours/glitch/styles/components/search.scss index 7c5039efc..117da362f 100644 --- a/app/javascript/flavours/glitch/styles/components/search.scss +++ b/app/javascript/flavours/glitch/styles/components/search.scss @@ -78,6 +78,11 @@ font-weight: 500; } +.search-results__info { + padding: 10px; + color: $secondary-text-color; +} + .trends { &__header { color: $dark-text-color; -- cgit From 51411267fda00db576230a270a10e31992378c18 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 27 Jul 2019 05:49:50 +0200 Subject: [Glitch] Add search results pagination to web UI (#11409) Port 8a4674f2c3d89c998eb5438b96b7977dc2be3167 to glitch-soc Signed-off-by: Thibaut Girka --- app/javascript/flavours/glitch/actions/search.js | 54 ++++++++++++++++++++-- .../features/compose/components/search_results.js | 18 +++++++- .../compose/containers/search_results_container.js | 4 +- app/javascript/flavours/glitch/reducers/search.js | 3 ++ .../flavours/glitch/styles/components/search.scss | 5 +- 5 files changed, 76 insertions(+), 8 deletions(-) (limited to 'app/javascript/flavours/glitch/features/compose/containers') diff --git a/app/javascript/flavours/glitch/actions/search.js b/app/javascript/flavours/glitch/actions/search.js index 9ce77b24b..a025f352a 100644 --- a/app/javascript/flavours/glitch/actions/search.js +++ b/app/javascript/flavours/glitch/actions/search.js @@ -10,6 +10,10 @@ export const SEARCH_FETCH_REQUEST = 'SEARCH_FETCH_REQUEST'; export const SEARCH_FETCH_SUCCESS = 'SEARCH_FETCH_SUCCESS'; export const SEARCH_FETCH_FAIL = 'SEARCH_FETCH_FAIL'; +export const SEARCH_EXPAND_REQUEST = 'SEARCH_EXPAND_REQUEST'; +export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS'; +export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL'; + export function changeSearch(value) { return { type: SEARCH_CHANGE, @@ -77,8 +81,50 @@ export function fetchSearchFail(error) { }; }; -export function showSearch() { - return { - type: SEARCH_SHOW, - }; +export const expandSearch = type => (dispatch, getState) => { + const value = getState().getIn(['search', 'value']); + const offset = getState().getIn(['search', 'results', type]).size; + + dispatch(expandSearchRequest()); + + api(getState).get('/api/v2/search', { + params: { + q: value, + type, + offset, + }, + }).then(({ data }) => { + if (data.accounts) { + dispatch(importFetchedAccounts(data.accounts)); + } + + if (data.statuses) { + dispatch(importFetchedStatuses(data.statuses)); + } + + dispatch(expandSearchSuccess(data, value, type)); + dispatch(fetchRelationships(data.accounts.map(item => item.id))); + }).catch(error => { + dispatch(expandSearchFail(error)); + }); }; + +export const expandSearchRequest = () => ({ + type: SEARCH_EXPAND_REQUEST, +}); + +export const expandSearchSuccess = (results, searchTerm, searchType) => ({ + type: SEARCH_EXPAND_SUCCESS, + results, + searchTerm, + searchType, +}); + +export const expandSearchFail = error => ({ + type: SEARCH_EXPAND_FAIL, + error, +}); + +export const showSearch = () => ({ + type: SEARCH_SHOW, +}); diff --git a/app/javascript/flavours/glitch/features/compose/components/search_results.js b/app/javascript/flavours/glitch/features/compose/components/search_results.js index dd99f3430..7220d8529 100644 --- a/app/javascript/flavours/glitch/features/compose/components/search_results.js +++ b/app/javascript/flavours/glitch/features/compose/components/search_results.js @@ -8,6 +8,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import Hashtag from 'flavours/glitch/components/hashtag'; import Icon from 'flavours/glitch/components/icon'; import { searchEnabled } from 'flavours/glitch/util/initial_state'; +import LoadMore from 'flavours/glitch/components/load_more'; const messages = defineMessages({ dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' }, @@ -20,15 +21,24 @@ class SearchResults extends ImmutablePureComponent { results: ImmutablePropTypes.map.isRequired, suggestions: ImmutablePropTypes.list.isRequired, fetchSuggestions: PropTypes.func.isRequired, + expandSearch: PropTypes.func.isRequired, dismissSuggestion: PropTypes.func.isRequired, searchTerm: PropTypes.string, intl: PropTypes.object.isRequired, }; componentDidMount () { - this.props.fetchSuggestions(); + if (this.props.searchTerm === '') { + this.props.fetchSuggestions(); + } } + handleLoadMoreAccounts = () => this.props.expandSearch('accounts'); + + handleLoadMoreStatuses = () => this.props.expandSearch('statuses'); + + handleLoadMoreHashtags = () => this.props.expandSearch('hashtags'); + render () { const { intl, results, suggestions, dismissSuggestion, searchTerm } = this.props; @@ -75,6 +85,8 @@ class SearchResults extends ImmutablePureComponent {
{results.get('accounts').map(accountId => )} + + {results.get('accounts').size >= 5 && } ); } @@ -86,6 +98,8 @@ class SearchResults extends ImmutablePureComponent {
{results.get('statuses').map(statusId => )} + + {results.get('statuses').size >= 5 && } ); } @@ -97,6 +111,8 @@ class SearchResults extends ImmutablePureComponent {
{results.get('hashtags').map(hashtag => )} + + {results.get('hashtags').size >= 5 && } ); } diff --git a/app/javascript/flavours/glitch/features/compose/containers/search_results_container.js b/app/javascript/flavours/glitch/features/compose/containers/search_results_container.js index e4d5f3420..1f714ff83 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/search_results_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/search_results_container.js @@ -1,6 +1,7 @@ import { connect } from 'react-redux'; import SearchResults from '../components/search_results'; -import { fetchSuggestions, dismissSuggestion } from '../../../actions/suggestions'; +import { fetchSuggestions, dismissSuggestion } from 'mastodon/actions/suggestions'; +import { expandSearch } from 'mastodon/actions/search'; const mapStateToProps = state => ({ results: state.getIn(['search', 'results']), @@ -10,6 +11,7 @@ const mapStateToProps = state => ({ const mapDispatchToProps = dispatch => ({ fetchSuggestions: () => dispatch(fetchSuggestions()), + expandSearch: type => dispatch(expandSearch(type)), dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))), }); diff --git a/app/javascript/flavours/glitch/reducers/search.js b/app/javascript/flavours/glitch/reducers/search.js index 1c32a5b9f..f4d99a99a 100644 --- a/app/javascript/flavours/glitch/reducers/search.js +++ b/app/javascript/flavours/glitch/reducers/search.js @@ -3,6 +3,7 @@ import { SEARCH_CLEAR, SEARCH_FETCH_SUCCESS, SEARCH_SHOW, + SEARCH_EXPAND_SUCCESS, } from 'flavours/glitch/actions/search'; import { COMPOSE_MENTION, @@ -42,6 +43,8 @@ export default function search(state = initialState, action) { statuses: ImmutableList(action.results.statuses.map(item => item.id)), hashtags: fromJS(action.results.hashtags), })).set('submitted', true).set('searchTerm', action.searchTerm); + case SEARCH_EXPAND_SUCCESS: + return state.updateIn(['results', action.searchType], list => list.concat(action.results[action.searchType].map(item => item.id))); default: return state; } diff --git a/app/javascript/flavours/glitch/styles/components/search.scss b/app/javascript/flavours/glitch/styles/components/search.scss index 117da362f..0e518997d 100644 --- a/app/javascript/flavours/glitch/styles/components/search.scss +++ b/app/javascript/flavours/glitch/styles/components/search.scss @@ -79,8 +79,9 @@ } .search-results__info { - padding: 10px; - color: $secondary-text-color; + padding: 20px; + color: $darker-text-color; + text-align: center; } .trends { -- cgit From ab019800f8862a84eab679ea5848c3df0531ddc9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 14 Aug 2019 04:07:32 +0200 Subject: [Glitch] Add media editing modal Port 23f7afa562c49b24e979505680463bc712b11d94 to glitch-soc Signed-off-by: Thibaut Girka --- .../glitch/features/compose/components/upload.js | 84 +------------- .../compose/containers/upload_container.js | 6 +- .../features/ui/components/focal_point_modal.js | 129 +++++++++++++++++---- .../flavours/glitch/features/video/index.js | 11 +- .../flavours/glitch/styles/components/media.scss | 5 + .../flavours/glitch/styles/components/modal.scss | 46 ++++++-- 6 files changed, 159 insertions(+), 122 deletions(-) (limited to 'app/javascript/flavours/glitch/features/compose/containers') diff --git a/app/javascript/flavours/glitch/features/compose/components/upload.js b/app/javascript/flavours/glitch/features/compose/components/upload.js index 84edf664e..f89145a52 100644 --- a/app/javascript/flavours/glitch/features/compose/components/upload.js +++ b/app/javascript/flavours/glitch/features/compose/components/upload.js @@ -4,18 +4,12 @@ import PropTypes from 'prop-types'; import Motion from 'flavours/glitch/util/optional_motion'; import spring from 'react-motion/lib/spring'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import Icon from 'flavours/glitch/components/icon'; import { isUserTouching } from 'flavours/glitch/util/is_mobile'; -const messages = defineMessages({ - description: { id: 'upload_form.description', defaultMessage: 'Describe for the visually impaired' }, -}); - -// The component. -export default @injectIntl -class Upload extends ImmutablePureComponent { +export default class Upload extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object, @@ -23,30 +17,10 @@ class Upload extends ImmutablePureComponent { static propTypes = { media: ImmutablePropTypes.map.isRequired, - intl: PropTypes.object.isRequired, onUndo: PropTypes.func.isRequired, - onDescriptionChange: PropTypes.func.isRequired, onOpenFocalPoint: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, - }; - - state = { - hovered: false, - focused: false, - dirtyDescription: null, }; - handleKeyDown = (e) => { - if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { - this.handleSubmit(); - } - } - - handleSubmit = () => { - this.handleInputBlur(); - this.props.onSubmit(this.context.router.history); - } - handleUndoClick = e => { e.stopPropagation(); this.props.onUndo(this.props.media.get('id')); @@ -57,69 +31,21 @@ class Upload extends ImmutablePureComponent { this.props.onOpenFocalPoint(this.props.media.get('id')); } - handleInputChange = e => { - this.setState({ dirtyDescription: e.target.value }); - } - - handleMouseEnter = () => { - this.setState({ hovered: true }); - } - - handleMouseLeave = () => { - this.setState({ hovered: false }); - } - - handleInputFocus = () => { - this.setState({ focused: true }); - } - - handleClick = () => { - this.setState({ focused: true }); - } - - handleInputBlur = () => { - const { dirtyDescription } = this.state; - - this.setState({ focused: false, dirtyDescription: null }); - - if (dirtyDescription !== null) { - this.props.onDescriptionChange(this.props.media.get('id'), dirtyDescription); - } - } - render () { const { intl, media } = this.props; - const active = this.state.hovered || this.state.focused || isUserTouching(); - const description = this.state.dirtyDescription || (this.state.dirtyDescription !== '' && media.get('description')) || ''; - const computedClass = classNames('composer--upload_form--item', { active }); const focusX = media.getIn(['meta', 'focus', 'x']); const focusY = media.getIn(['meta', 'focus', 'y']); const x = ((focusX / 2) + .5) * 100; const y = ((focusY / -2) + .5) * 100; return ( -
+
{({ scale }) => (
-
+
- {media.get('type') === 'image' && } -
- -
-