diff options
Diffstat (limited to 'app/javascript/flavours/glitch/features/ui/containers')
6 files changed, 186 insertions, 0 deletions
diff --git a/app/javascript/flavours/glitch/features/ui/containers/bundle_container.js b/app/javascript/flavours/glitch/features/ui/containers/bundle_container.js new file mode 100644 index 000000000..c9086c9bc --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/containers/bundle_container.js @@ -0,0 +1,19 @@ +import { connect } from 'react-redux'; + +import Bundle from '../components/bundle'; + +import { fetchBundleRequest, fetchBundleSuccess, fetchBundleFail } from 'flavours/glitch/actions/bundles'; + +const mapDispatchToProps = dispatch => ({ + onFetch () { + dispatch(fetchBundleRequest()); + }, + onFetchSuccess () { + dispatch(fetchBundleSuccess()); + }, + onFetchFail (error) { + dispatch(fetchBundleFail(error)); + }, +}); + +export default connect(null, mapDispatchToProps)(Bundle); diff --git a/app/javascript/flavours/glitch/features/ui/containers/columns_area_container.js b/app/javascript/flavours/glitch/features/ui/containers/columns_area_container.js new file mode 100644 index 000000000..1107be740 --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/containers/columns_area_container.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import ColumnsArea from '../components/columns_area'; +import { openModal } from 'flavours/glitch/actions/modal'; + +const mapStateToProps = state => ({ + columns: state.getIn(['settings', 'columns']), +}); + +const mapDispatchToProps = dispatch => ({ + openSettings (e) { + e.preventDefault(); + e.stopPropagation(); + dispatch(openModal('SETTINGS', {})); + }, +}); + +export default connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })(ColumnsArea); diff --git a/app/javascript/flavours/glitch/features/ui/containers/loading_bar_container.js b/app/javascript/flavours/glitch/features/ui/containers/loading_bar_container.js new file mode 100644 index 000000000..63e994f92 --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/containers/loading_bar_container.js @@ -0,0 +1,8 @@ +import { connect } from 'react-redux'; +import LoadingBar from 'react-redux-loading-bar'; + +const mapStateToProps = (state, ownProps) => ({ + loading: state.get('loadingBar')[ownProps.scope || 'default'], +}); + +export default connect(mapStateToProps)(LoadingBar.WrappedComponent); diff --git a/app/javascript/flavours/glitch/features/ui/containers/modal_container.js b/app/javascript/flavours/glitch/features/ui/containers/modal_container.js new file mode 100644 index 000000000..560c34f01 --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/containers/modal_container.js @@ -0,0 +1,27 @@ +import { connect } from 'react-redux'; +import { openModal, closeModal } from 'flavours/glitch/actions/modal'; +import ModalRoot from '../components/modal_root'; + +const mapStateToProps = state => ({ + ignoreFocus: state.getIn(['modal', 'ignoreFocus']), + type: state.getIn(['modal', 'stack', 0, 'modalType'], null), + props: state.getIn(['modal', 'stack', 0, 'modalProps'], {}), +}); + +const mapDispatchToProps = dispatch => ({ + onClose (confirmationMessage, ignoreFocus = false) { + if (confirmationMessage) { + dispatch( + openModal('CONFIRM', { + message: confirmationMessage.message, + confirm: confirmationMessage.confirm, + onConfirm: () => dispatch(closeModal(undefined, { ignoreFocus })), + }), + ); + } else { + dispatch(closeModal(undefined, { ignoreFocus })); + } + }, +}); + +export default connect(mapStateToProps, mapDispatchToProps)(ModalRoot); diff --git a/app/javascript/flavours/glitch/features/ui/containers/notifications_container.js b/app/javascript/flavours/glitch/features/ui/containers/notifications_container.js new file mode 100644 index 000000000..82278a3be --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/containers/notifications_container.js @@ -0,0 +1,29 @@ +import { injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; +import { NotificationStack } from 'react-notification'; +import { dismissAlert } from 'flavours/glitch/actions/alerts'; +import { getAlerts } from 'flavours/glitch/selectors'; + +const mapStateToProps = (state, { intl }) => { + const notifications = getAlerts(state); + + notifications.forEach(notification => ['title', 'message'].forEach(key => { + const value = notification[key]; + + if (typeof value === 'object') { + notification[key] = intl.formatMessage(value, notification[`${key}_values`]); + } + })); + + return { notifications }; +}; + +const mapDispatchToProps = (dispatch) => { + return { + onDismiss: alert => { + dispatch(dismissAlert(alert)); + }, + }; +}; + +export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(NotificationStack)); 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 new file mode 100644 index 000000000..3cd0707f2 --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/containers/status_list_container.js @@ -0,0 +1,86 @@ +import { connect } from 'react-redux'; +import StatusList from 'flavours/glitch/components/status_list'; +import { scrollTopTimeline, loadPending } from 'flavours/glitch/actions/timelines'; +import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import { createSelector } from 'reselect'; +import { debounce } from 'lodash'; +import { me } from 'flavours/glitch/initial_state'; + +const getRegex = createSelector([ + (state, { regex }) => regex, +], (rawRegex) => { + let regex = null; + + try { + regex = rawRegex && new RegExp(rawRegex.trim(), 'i'); + } catch (e) { + // Bad regex, don't affect filters + } + return regex; +}); + +const makeGetStatusIds = (pending = false) => createSelector([ + (state, { type }) => state.getIn(['settings', type], ImmutableMap()), + (state, { type }) => state.getIn(['timelines', type, pending ? 'pendingItems' : 'items'], ImmutableList()), + (state) => state.get('statuses'), + getRegex, +], (columnSettings, statusIds, statuses, regex) => { + return statusIds.filter(id => { + if (id === null) return true; + + const statusForId = statuses.get(id); + let showStatus = true; + + if (statusForId.get('account') === me) return true; + + if (columnSettings.getIn(['shows', 'reblog']) === false) { + showStatus = showStatus && statusForId.get('reblog') === null; + } + + if (columnSettings.getIn(['shows', 'reply']) === false) { + showStatus = showStatus && (statusForId.get('in_reply_to_id') === null || statusForId.get('in_reply_to_account_id') === me); + } + + if (columnSettings.getIn(['shows', 'direct']) === false) { + showStatus = showStatus && statusForId.get('visibility') !== 'direct'; + } + + if (showStatus && regex) { + const searchIndex = statusForId.get('reblog') ? statuses.getIn([statusForId.get('reblog'), 'search_index']) : statusForId.get('search_index'); + showStatus = !regex.test(searchIndex); + } + + return showStatus; + }); +}); + +const makeMapStateToProps = () => { + const getStatusIds = makeGetStatusIds(); + const getPendingStatusIds = makeGetStatusIds(true); + + const mapStateToProps = (state, { timelineId, regex }) => ({ + statusIds: getStatusIds(state, { type: timelineId, regex }), + isLoading: state.getIn(['timelines', timelineId, 'isLoading'], true), + isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false), + hasMore: state.getIn(['timelines', timelineId, 'hasMore']), + numPending: getPendingStatusIds(state, { type: timelineId }).size, + }); + + return mapStateToProps; +}; + +const mapDispatchToProps = (dispatch, { timelineId }) => ({ + + onScrollToTop: debounce(() => { + dispatch(scrollTopTimeline(timelineId, true)); + }, 100), + + onScroll: debounce(() => { + dispatch(scrollTopTimeline(timelineId, false)); + }, 100), + + onLoadPending: () => dispatch(loadPending(timelineId)), + +}); + +export default connect(makeMapStateToProps, mapDispatchToProps)(StatusList); |