diff --git a/app/javascript/gabsocial/actions/notifications.js b/app/javascript/gabsocial/actions/notifications.js index 7e7ad7da..8de231eb 100644 --- a/app/javascript/gabsocial/actions/notifications.js +++ b/app/javascript/gabsocial/actions/notifications.js @@ -7,27 +7,26 @@ import { importFetchedStatus, importFetchedStatuses, } from './importer'; -import { saveSettings } from './settings'; import { defineMessages } from 'react-intl'; import { List as ImmutableList } from 'immutable'; import { unescapeHTML } from '../utils/html'; import { getFilters, regexFromFilters } from '../selectors'; import { me } from '../initial_state'; -export const NOTIFICATIONS_INITIALIZE = 'NOTIFICATIONS_INITIALIZE'; -export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE'; +export const NOTIFICATIONS_INITIALIZE = 'NOTIFICATIONS_INITIALIZE'; +export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE'; export const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE'; -export const NOTIFICATIONS_DEQUEUE = 'NOTIFICATIONS_DEQUEUE'; +export const NOTIFICATIONS_DEQUEUE = 'NOTIFICATIONS_DEQUEUE'; export const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST'; export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS'; -export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL'; +export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL'; export const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET'; -export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR'; +export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR'; export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP'; -export const NOTIFICATIONS_MARK_READ = 'NOTIFICATIONS_MARK_READ'; +export const NOTIFICATIONS_MARK_READ = 'NOTIFICATIONS_MARK_READ'; export const MAX_QUEUED_NOTIFICATIONS = 40 @@ -52,7 +51,7 @@ export function initializeNotifications() { export function updateNotifications(notification, intlMessages, intlLocale) { return (dispatch, getState) => { - const showInColumn = getState().getIn(['settings', 'notifications', 'shows', notification.type], true); + const showInColumn = getState().getIn(['notifications', 'filter', notification.type], true); if (showInColumn) { dispatch(importFetchedAccount(notification.account)); @@ -73,7 +72,8 @@ export function updateNotifications(notification, intlMessages, intlLocale) { export function updateNotificationsQueue(notification, intlMessages, intlLocale, curPath) { return (dispatch, getState) => { - const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true); + // : todo : + // const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true); const filters = getFilters(getState(), { contextType: 'notifications' }); let filtered = false; @@ -87,17 +87,18 @@ export function updateNotificationsQueue(notification, intlMessages, intlLocale, } // Desktop notifications - if (typeof window.Notification !== 'undefined' && showAlert && !filtered) { - const title = new IntlMessageFormat(intlMessages[`notification.${notification.type}`], intlLocale).format({ name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username }); - const body = (notification.status && notification.status.spoiler_text.length > 0) ? notification.status.spoiler_text : unescapeHTML(notification.status ? notification.status.content : ''); + // : todo : + // if (typeof window.Notification !== 'undefined' && showAlert && !filtered) { + // const title = new IntlMessageFormat(intlMessages[`notification.${notification.type}`], intlLocale).format({ name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username }); + // const body = (notification.status && notification.status.spoiler_text.length > 0) ? notification.status.spoiler_text : unescapeHTML(notification.status ? notification.status.content : ''); - const notify = new Notification(title, { body, icon: notification.account.avatar, tag: notification.id }); + // const notify = new Notification(title, { body, icon: notification.account.avatar, tag: notification.id }); - notify.addEventListener('click', () => { - window.focus(); - notify.close(); - }); - } + // notify.addEventListener('click', () => { + // window.focus(); + // notify.close(); + // }); + // } if (isOnNotificationsPage) { dispatch({ @@ -134,22 +135,22 @@ export function dequeueNotifications() { } }; -const excludeTypesFromSettings = state => state.getIn(['settings', 'notifications', 'shows']).filter(enabled => !enabled).keySeq().toJS(); - const excludeTypesFromFilter = filter => { const allTypes = ImmutableList(['follow', 'favourite', 'reblog', 'mention', 'poll']); return allTypes.filterNot(item => item === filter).toJS(); }; -const noOp = () => {}; +const noOp = () => { }; export function expandNotifications({ maxId } = {}, done = noOp) { return (dispatch, getState) => { - if (!me) return; + if (!me) return - const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']); - const notifications = getState().get('notifications'); - const isLoadingMore = !!maxId; + const onlyVerified = getState().getIn(['notifications', 'filter', 'onlyVerified']) + const onlyFollowing = getState().getIn(['notifications', 'filter', 'onlyFollowing']) + const activeFilter = getState().getIn(['notifications', 'filter', 'active']) + const notifications = getState().get('notifications') + const isLoadingMore = !!maxId if (notifications.get('isLoading')) { done(); @@ -157,16 +158,16 @@ export function expandNotifications({ maxId } = {}, done = noOp) { } console.log('activeFilter:', activeFilter) - console.log('excludeTypesFromSettings(getState()):', excludeTypesFromSettings(getState())) + // console.log('excludeTypesFromSettings(getState()):', excludeTypesFromSettings(getState())) console.log('excludeTypesFromFilter(activeFilter):', excludeTypesFromFilter(activeFilter)) // : todo : // filter verified and following here too const params = { max_id: maxId, - exclude_types: activeFilter === 'all' - ? excludeTypesFromSettings(getState()) - : excludeTypesFromFilter(activeFilter), + only_verified: onlyVerified, + only_following: onlyFollowing, + exclude_types: activeFilter === 'all' ? [] : excludeTypesFromFilter(activeFilter), }; if (!maxId && notifications.get('items').size > 0) { @@ -237,17 +238,16 @@ export function scrollTopNotifications(top) { } }; -export function setFilter (filterType) { +export function setFilter(path, value) { return dispatch => { dispatch({ type: NOTIFICATIONS_FILTER_SET, - path: ['notifications', 'quickFilter', 'active'], - value: filterType, - }); - dispatch(expandNotifications()); - dispatch(saveSettings()); - }; -}; + path: path, + value: value, + }) + dispatch(expandNotifications()) + } +} export function markReadNotifications() { return (dispatch, getState) => { diff --git a/app/javascript/gabsocial/actions/settings.js b/app/javascript/gabsocial/actions/settings.js index 5a6fccfb..551f72b5 100644 --- a/app/javascript/gabsocial/actions/settings.js +++ b/app/javascript/gabsocial/actions/settings.js @@ -1,10 +1,9 @@ -import api from '../api'; -import debounce from 'lodash.debounce'; -// import { showAlertForError } from './alerts'; -import { me } from '../initial_state'; +import api from '../api' +import debounce from 'lodash.debounce' +import { me } from '../initial_state' -export const SETTING_CHANGE = 'SETTING_CHANGE'; -export const SETTING_SAVE = 'SETTING_SAVE'; +export const SETTING_CHANGE = 'SETTING_CHANGE' +export const SETTING_SAVE = 'SETTING_SAVE' export function changeSetting(path, value) { return dispatch => { @@ -12,26 +11,24 @@ export function changeSetting(path, value) { type: SETTING_CHANGE, path, value, - }); + }) - dispatch(saveSettings()); - }; -}; + dispatch(saveSettings()) + } +} const debouncedSave = debounce((dispatch, getState) => { - if (!me) return; + if (!me) return - if (getState().getIn(['settings', 'saved'])) { - return; - } + if (getState().getIn(['settings', 'saved'])) return - const data = getState().get('settings').filter((_, path) => path !== 'saved').toJS(); + const data = getState().get('settings').filter((_, path) => path !== 'saved').toJS() api().put('/api/web/settings', { data }) .then(() => dispatch({ type: SETTING_SAVE })) - // .catch(error => dispatch(showAlertForError(error))); -}, 5000, { trailing: true }); + .catch(() => { /* */ }) +}, 5000, { trailing: true }) export function saveSettings() { - return (dispatch, getState) => debouncedSave(dispatch, getState); -}; + return (dispatch, getState) => debouncedSave(dispatch, getState) +} diff --git a/app/javascript/gabsocial/assets/pencil_icon.js b/app/javascript/gabsocial/assets/pencil_icon.js new file mode 100644 index 00000000..b63d2b3d --- /dev/null +++ b/app/javascript/gabsocial/assets/pencil_icon.js @@ -0,0 +1,26 @@ +const PencilIcon = ({ + className = '', + width = '16px', + height = '16px', + viewBox = '0 0 64 64', + title = 'Pencil', +}) => ( + + + + + +) + +export default PencilIcon \ No newline at end of file diff --git a/app/javascript/gabsocial/components/floating_action_button.js b/app/javascript/gabsocial/components/floating_action_button.js index f8893493..d497b41c 100644 --- a/app/javascript/gabsocial/components/floating_action_button.js +++ b/app/javascript/gabsocial/components/floating_action_button.js @@ -1,4 +1,3 @@ -import Icon from './icon' import Button from './button' export default class FloatingActionButton extends PureComponent { @@ -21,13 +20,12 @@ export default class FloatingActionButton extends PureComponent { + icon='pencil' + /> ) } } \ No newline at end of file diff --git a/app/javascript/gabsocial/components/icon.js b/app/javascript/gabsocial/components/icon.js index 67478fad..d2c21317 100644 --- a/app/javascript/gabsocial/components/icon.js +++ b/app/javascript/gabsocial/components/icon.js @@ -44,6 +44,7 @@ import MoreIcon from '../assets/more_icon' import NotificationsIcon from '../assets/notifications_icon' import OLListIcon from '../assets/ol_list_icon' import PauseIcon from '../assets/pause_icon' +import PencilIcon from '../assets/pencil_icon' import PinIcon from '../assets/pin_icon' import PlayIcon from '../assets/play_icon' import PollIcon from '../assets/poll_icon' @@ -111,6 +112,7 @@ const ICONS = { 'notifications': NotificationsIcon, 'ol-list': OLListIcon, 'pause': PauseIcon, + 'pencil': PencilIcon, 'pin': PinIcon, 'play': PlayIcon, 'poll': PollIcon, diff --git a/app/javascript/gabsocial/components/panel/notification_filter_panel.js b/app/javascript/gabsocial/components/panel/notification_filter_panel.js index cb6512b8..1890d995 100644 --- a/app/javascript/gabsocial/components/panel/notification_filter_panel.js +++ b/app/javascript/gabsocial/components/panel/notification_filter_panel.js @@ -1,7 +1,7 @@ import { defineMessages, injectIntl } from 'react-intl' import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePropTypes from 'react-immutable-proptypes' -import { changeSetting, saveSettings } from '../../actions/settings' +import { setFilter } from '../../actions/notifications' import PanelLayout from './panel_layout' import SettingSwitch from '../setting_switch' @@ -12,14 +12,13 @@ const messages = defineMessages({ }) const mapStateToProps = state => ({ - settings: state.getIn(['settings', 'notifications']), + settings: state.getIn(['notifications', 'filter']), }) const mapDispatchToProps = (dispatch) => { return { - onChange(key, checked) { - dispatch(changeSetting(['notifications', ...key], checked)) - dispatch(saveSettings()) + onChange(path, value) { + dispatch(setFilter(path, value)) }, } } @@ -43,7 +42,7 @@ class NotificationFilterPanel extends ImmutablePureComponent { @@ -51,7 +50,7 @@ class NotificationFilterPanel extends ImmutablePureComponent { diff --git a/app/javascript/gabsocial/components/setting_switch.js b/app/javascript/gabsocial/components/setting_switch.js index b94fe06e..c1e651cf 100644 --- a/app/javascript/gabsocial/components/setting_switch.js +++ b/app/javascript/gabsocial/components/setting_switch.js @@ -7,7 +7,10 @@ export default class SettingSwitch extends ImmutablePureComponent { static propTypes = { prefix: PropTypes.string, settings: ImmutablePropTypes.map.isRequired, - settingPath: PropTypes.array.isRequired, + settingPath: PropTypes.oneOfType([ + PropTypes.array, + PropTypes.string, + ]).isRequired, description: PropTypes.string, label: PropTypes.string.isRequired, onChange: PropTypes.func.isRequired, @@ -26,14 +29,17 @@ export default class SettingSwitch extends ImmutablePureComponent { description } = this.props - const id = ['setting-toggle', prefix, ...settingPath].filter(Boolean).join('-') - + const isArray = Array.isArray(settingPath) + const checked = isArray ? settings.getIn(settingPath) : settings.get(settingPath) + const idVal = isArray ? settingPath.join('-') : settingPath + const id = ['setting-toggle', prefix, idVal].filter(Boolean).join('-') + return ( diff --git a/app/javascript/gabsocial/components/sidebar.js b/app/javascript/gabsocial/components/sidebar.js index 73d4d17d..4c3aa057 100644 --- a/app/javascript/gabsocial/components/sidebar.js +++ b/app/javascript/gabsocial/components/sidebar.js @@ -1,12 +1,14 @@ import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePureComponent from 'react-immutable-pure-component' import { injectIntl, defineMessages } from 'react-intl' +import * as Constants from '../constants' import Button from './button' import { closeSidebar } from '../actions/sidebar' import { openModal } from '../actions/modal' import { openPopover } from '../actions/popover' import { me } from '../initial_state' import { makeGetAccount } from '../selectors' +import Responsive from '../features/ui/util/responsive_component' import SidebarSectionTitle from './sidebar_section_title' import SidebarSectionItem from './sidebar_section_item' import SidebarHeader from './sidebar_header' @@ -197,7 +199,7 @@ class Sidebar extends ImmutablePureComponent {
-
+
@@ -226,13 +228,23 @@ class Sidebar extends ImmutablePureComponent { } - + + + + + +
diff --git a/app/javascript/gabsocial/components/status/status.js b/app/javascript/gabsocial/components/status/status.js index 53bb2300..99fe0308 100644 --- a/app/javascript/gabsocial/components/status/status.js +++ b/app/javascript/gabsocial/components/status/status.js @@ -387,6 +387,7 @@ class Status extends ImmutablePureComponent { const containerClasses = cx({ default: 1, + radiusSmall: !borderless && !isChild, mb15: !borderless && !isChild, backgroundColorPrimary: 1, pb15: featured, diff --git a/app/javascript/gabsocial/components/tab_bar_item.js b/app/javascript/gabsocial/components/tab_bar_item.js index 80ae9678..a650b639 100644 --- a/app/javascript/gabsocial/components/tab_bar_item.js +++ b/app/javascript/gabsocial/components/tab_bar_item.js @@ -57,6 +57,7 @@ class TabBarItem extends PureComponent { justifyContentCenter: 1, borderBottom2PX: 1, py5: 1, + outlineNone: 1, cursorPointer: 1, backgroundTransparent: 1, borderColorTransparent: !isActive, diff --git a/app/javascript/gabsocial/features/notifications/components/notification/notification-alt.js b/app/javascript/gabsocial/features/notifications/components/notification.js similarity index 96% rename from app/javascript/gabsocial/features/notifications/components/notification/notification-alt.js rename to app/javascript/gabsocial/features/notifications/components/notification.js index 256e2035..ed2434bb 100644 --- a/app/javascript/gabsocial/features/notifications/components/notification/notification-alt.js +++ b/app/javascript/gabsocial/features/notifications/components/notification.js @@ -3,12 +3,12 @@ import { injectIntl, defineMessages } from 'react-intl' import ImmutablePureComponent from 'react-immutable-pure-component' import { HotKeys } from 'react-hotkeys' import ImmutablePropTypes from 'react-immutable-proptypes' -import StatusContainer from '../../../../containers/status_container' -import AccountContainer from '../../../../containers/account_container' -import Avatar from '../../../../components/avatar' -import Icon from '../../../../components/icon' -import Text from '../../../../components/text' -import DisplayName from '../../../../components/display_name' +import StatusContainer from '../../../containers/status_container' +import AccountContainer from '../../../containers/account_container' +import Avatar from '../../../components/avatar' +import Icon from '../../../components/icon' +import Text from '../../../components/text' +import DisplayName from '../../../components/display_name' const messages = defineMessages({ poll: { id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' }, diff --git a/app/javascript/gabsocial/features/notifications/components/notification/index.js b/app/javascript/gabsocial/features/notifications/components/notification/index.js deleted file mode 100644 index e207d02f..00000000 --- a/app/javascript/gabsocial/features/notifications/components/notification/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './notification' \ No newline at end of file diff --git a/app/javascript/gabsocial/features/notifications/components/notification/notification.js b/app/javascript/gabsocial/features/notifications/components/notification/notification.js deleted file mode 100644 index 5ca67b0c..00000000 --- a/app/javascript/gabsocial/features/notifications/components/notification/notification.js +++ /dev/null @@ -1,274 +0,0 @@ -import { injectIntl, FormattedMessage } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { HotKeys } from 'react-hotkeys'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import StatusContainer from '../../../../containers/status_container'; -import AccountContainer from '../../../../containers/account_container'; -import Button from '../../../../components/button' -import Icon from '../../../../components/icon'; - -const notificationForScreenReader = (intl, message, timestamp) => { - const output = [message]; - - output.push(intl.formatDate(timestamp, { hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' })); - - return output.join(', '); -}; - -export default -@injectIntl -class Notification extends ImmutablePureComponent { - - static contextTypes = { - router: PropTypes.object, - }; - - static propTypes = { - notification: ImmutablePropTypes.map.isRequired, - hidden: PropTypes.bool, - onMoveUp: PropTypes.func.isRequired, - onMoveDown: PropTypes.func.isRequired, - onMention: PropTypes.func.isRequired, - onFavorite: PropTypes.func.isRequired, - onRepost: PropTypes.func.isRequired, - onToggleHidden: PropTypes.func.isRequired, - status: ImmutablePropTypes.map, - intl: PropTypes.object.isRequired, - getScrollPosition: PropTypes.func, - updateScrollBottom: PropTypes.func, - cacheMediaWidth: PropTypes.func, - cachedMediaWidth: PropTypes.number, - }; - - handleMoveUp = () => { - const { notification, onMoveUp } = this.props; - onMoveUp(notification.get('id')); - } - - handleMoveDown = () => { - const { notification, onMoveDown } = this.props; - onMoveDown(notification.get('id')); - } - - handleOpen = () => { - const { notification } = this.props; - - if (notification.get('status')) { - this.context.router.history.push(`/${notification.getIn(['account', 'acct'])}/posts/${notification.get('status')}`); - } else { - this.handleOpenProfile(); - } - } - - handleOpenProfile = () => { - const { notification } = this.props; - this.context.router.history.push(`/${notification.getIn(['account', 'acct'])}`); - } - - handleMention = e => { - e.preventDefault(); - - const { notification, onMention } = this.props; - onMention(notification.get('account'), this.context.router.history); - } - - handleHotkeyFavorite = () => { - const { status } = this.props; - if (status) this.props.onFavorite(status); - } - - handleHotkeyBoost = e => { - const { status } = this.props; - if (status) this.props.onRepost(status, e); - } - - handleHotkeyToggleHidden = () => { - const { status } = this.props; - if (status) this.props.onToggleHidden(status); - } - - getHandlers() { - return { - reply: this.handleMention, - favorite: this.handleHotkeyFavorite, - boost: this.handleHotkeyBoost, - mention: this.handleMention, - open: this.handleOpen, - openProfile: this.handleOpenProfile, - moveUp: this.handleMoveUp, - moveDown: this.handleMoveDown, - toggleHidden: this.handleHotkeyToggleHidden, - }; - } - - renderFollow(notification, account, link) { - const { intl } = this.props; - - return ( - -
-
-
- -
- - - - -
- -
-
- ); - } - - renderMention(notification) { - return ( -