From d8fbd74c47de3148d6693b5cb15e7e868f72448e Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 28 Aug 2018 12:01:04 +0200 Subject: [Glitch] Add aria-label to column regions Port 66dbb59aa16981643e3bfa3f94d441bc3166eab3 to glitch-soc --- .../flavours/glitch/features/community_timeline/index.js | 2 +- app/javascript/flavours/glitch/features/direct_timeline/index.js | 2 +- app/javascript/flavours/glitch/features/drawer/index.js | 8 +++++++- .../flavours/glitch/features/favourited_statuses/index.js | 2 +- app/javascript/flavours/glitch/features/getting_started/index.js | 3 ++- app/javascript/flavours/glitch/features/hashtag_timeline/index.js | 2 +- app/javascript/flavours/glitch/features/home_timeline/index.js | 2 +- app/javascript/flavours/glitch/features/list_timeline/index.js | 2 +- app/javascript/flavours/glitch/features/notifications/index.js | 1 + app/javascript/flavours/glitch/features/public_timeline/index.js | 2 +- .../glitch/features/standalone/community_timeline/index.js | 2 +- .../flavours/glitch/features/standalone/public_timeline/index.js | 2 +- app/javascript/flavours/glitch/features/status/index.js | 3 ++- 13 files changed, 21 insertions(+), 12 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/community_timeline/index.js b/app/javascript/flavours/glitch/features/community_timeline/index.js index e5006b4d3..5bd9d037c 100644 --- a/app/javascript/flavours/glitch/features/community_timeline/index.js +++ b/app/javascript/flavours/glitch/features/community_timeline/index.js @@ -80,7 +80,7 @@ export default class CommunityTimeline extends React.PureComponent { const pinned = !!columnId; return ( - + + ({ account: state.getIn(['accounts', me]), @@ -92,7 +98,7 @@ class Drawer extends React.Component { // The result. return ( -
+
{multiColumn ? ( + { @@ -148,7 +149,7 @@ export default class GettingStarted extends ImmutablePureComponent { ]); return ( - +
diff --git a/app/javascript/flavours/glitch/features/hashtag_timeline/index.js b/app/javascript/flavours/glitch/features/hashtag_timeline/index.js index b3e8b7a6e..f710456d5 100644 --- a/app/javascript/flavours/glitch/features/hashtag_timeline/index.js +++ b/app/javascript/flavours/glitch/features/hashtag_timeline/index.js @@ -92,7 +92,7 @@ export default class HashtagTimeline extends React.PureComponent { const pinned = !!columnId; return ( - + + + + + + { @@ -387,7 +388,7 @@ export default class Status extends ImmutablePureComponent { }; return ( - + Date: Tue, 28 Aug 2018 12:10:40 +0200 Subject: [Glitch] Give focused status a sensible aria-label for screen readers Port 248df68c36a2f1ffd9c214afe7d1b0c62b4a5f27 to glitch-soc --- .../flavours/glitch/components/status.js | 29 +++++++++++++++++++++- .../flavours/glitch/features/status/index.js | 3 ++- 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 9f47abfef..13ff781fe 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -7,7 +7,7 @@ import StatusIcons from './status_icons'; import StatusContent from './status_content'; import StatusActionBar from './status_action_bar'; import AttachmentList from './attachment_list'; -import { FormattedMessage } from 'react-intl'; +import { injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { MediaGallery, Video } from 'flavours/glitch/util/async-components'; import { HotKeys } from 'react-hotkeys'; @@ -19,6 +19,24 @@ import { autoUnfoldCW } from 'flavours/glitch/util/content_warning'; // to use the progress bar to show download progress import Bundle from '../features/ui/components/bundle'; +export const textForScreenReader = (intl, status, rebloggedByText = false, expanded = false) => { + const displayName = status.getIn(['account', 'display_name']); + + const values = [ + displayName.length === 0 ? status.getIn(['account', 'acct']).split('@')[0] : displayName, + status.get('spoiler_text') && !expanded ? status.get('spoiler_text') : status.get('search_index').slice(status.get('spoiler_text').length), + intl.formatDate(status.get('created_at'), { hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' }), + status.getIn(['account', 'acct']), + ]; + + if (rebloggedByText) { + values.push(rebloggedByText); + } + + return values.join(', '); +}; + +@injectIntl export default class Status extends ImmutablePureComponent { static contextTypes = { @@ -52,6 +70,7 @@ export default class Status extends ImmutablePureComponent { getScrollPosition: PropTypes.func, updateScrollBottom: PropTypes.func, expanded: PropTypes.bool, + intl: PropTypes.object.isRequired, }; state = { @@ -337,6 +356,7 @@ export default class Status extends ImmutablePureComponent { } = this; const { router } = this.context; const { + intl, status, account, settings, @@ -473,6 +493,12 @@ export default class Status extends ImmutablePureComponent { selectorAttribs[`data-${notifKind}-by`] = `@${account.get('acct')}`; } + let rebloggedByText; + + if (prepend === 'reblog') { + rebloggedByText = intl.formatMessage({ id: 'status.reblogged_by', defaultMessage: '{name} boosted' }, { name: account.get('acct') }); + } + const handlers = { reply: this.handleHotkeyReply, favourite: this.handleHotkeyFavourite, @@ -501,6 +527,7 @@ export default class Status extends ImmutablePureComponent { ref={handleRef} tabIndex='0' data-featured={featured ? 'true' : null} + aria-label={textForScreenReader(intl, status, rebloggedByText, !status.get('hidden'))} >
diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index 565b4b725..0697b49ad 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -39,6 +39,7 @@ 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'; +import { textForScreenReader } from 'flavours/glitch/components/status'; const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, @@ -401,7 +402,7 @@ export default class Status extends ImmutablePureComponent { {ancestors} -
+
Date: Thu, 6 Sep 2018 15:47:13 +0200 Subject: Keep track of unread notifications when the notification column isn't mounted --- .../flavours/glitch/actions/notifications.js | 15 +++++++++++++ .../glitch/features/notifications/index.js | 24 ++++++++++++++++++++ .../flavours/glitch/reducers/notifications.js | 26 ++++++++++++++++------ 3 files changed, 58 insertions(+), 7 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js index e88eda78f..ee148e4ef 100644 --- a/app/javascript/flavours/glitch/actions/notifications.js +++ b/app/javascript/flavours/glitch/actions/notifications.js @@ -25,6 +25,9 @@ export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL'; export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR'; export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP'; +export const NOTIFICATIONS_MOUNT = 'NOTIFICATIONS_MOUNT'; +export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT'; + defineMessages({ mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' }, }); @@ -216,3 +219,15 @@ export function deleteMarkedNotificationsSuccess() { type: NOTIFICATIONS_DELETE_MARKED_SUCCESS, }; }; + +export function mountNotifications() { + return { + type: NOTIFICATIONS_MOUNT, + }; +}; + +export function unmountNotifications() { + return { + type: NOTIFICATIONS_UNMOUNT, + }; +}; diff --git a/app/javascript/flavours/glitch/features/notifications/index.js b/app/javascript/flavours/glitch/features/notifications/index.js index 266d6807d..ee711bd8a 100644 --- a/app/javascript/flavours/glitch/features/notifications/index.js +++ b/app/javascript/flavours/glitch/features/notifications/index.js @@ -8,6 +8,8 @@ import { enterNotificationClearingMode, expandNotifications, scrollTopNotifications, + mountNotifications, + unmountNotifications, } from 'flavours/glitch/actions/notifications'; import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns'; import NotificationContainer from './containers/notification_container'; @@ -42,6 +44,12 @@ const mapDispatchToProps = dispatch => ({ onEnterCleaningMode(yes) { dispatch(enterNotificationClearingMode(yes)); }, + onMount() { + dispatch(mountNotifications()); + }, + onUnmount() { + dispatch(unmountNotifications()); + }, dispatch, }); @@ -62,6 +70,8 @@ export default class Notifications extends React.PureComponent { localSettings: ImmutablePropTypes.map, notifCleaningActive: PropTypes.bool, onEnterCleaningMode: PropTypes.func, + onMount: PropTypes.func, + onUnmount: PropTypes.func, }; static defaultProps = { @@ -126,6 +136,20 @@ export default class Notifications extends React.PureComponent { } } + componentDidMount () { + const { onMount } = this.props; + if (onMount) { + onMount(); + } + } + + componentWillUnmount () { + const { onUnmount } = this.props; + if (onUnmount) { + onUnmount(); + } + } + render () { const { intl, notifications, shouldUpdateScroll, isLoading, isUnread, columnId, multiColumn, hasMore } = this.props; const pinned = !!columnId; diff --git a/app/javascript/flavours/glitch/reducers/notifications.js b/app/javascript/flavours/glitch/reducers/notifications.js index b712aaa67..9087e226c 100644 --- a/app/javascript/flavours/glitch/reducers/notifications.js +++ b/app/javascript/flavours/glitch/reducers/notifications.js @@ -1,4 +1,6 @@ import { + NOTIFICATIONS_MOUNT, + NOTIFICATIONS_UNMOUNT, NOTIFICATIONS_UPDATE, NOTIFICATIONS_EXPAND_SUCCESS, NOTIFICATIONS_EXPAND_REQUEST, @@ -24,6 +26,7 @@ const initialState = ImmutableMap({ items: ImmutableList(), hasMore: true, top: true, + mounted: 0, unread: 0, lastReadId: '0', isLoading: false, @@ -41,7 +44,7 @@ const notificationToMap = (state, notification) => ImmutableMap({ }); const normalizeNotification = (state, notification) => { - const top = state.get('top'); + const top = state.get('top') && state.get('mounted') > 0; if (top) { state = state.set('lastReadId', notification.id); @@ -59,7 +62,7 @@ const normalizeNotification = (state, notification) => { }; const expandNormalizedNotifications = (state, notifications, next) => { - const top = state.get('top'); + const top = state.get('top') && state.get('mounted') > 0; const lastReadId = state.get('lastReadId'); let items = ImmutableList(); @@ -102,18 +105,23 @@ const filterNotifications = (state, relationship) => { return state.update('items', list => list.filterNot(item => item !== null && item.get('account') === relationship.id)); }; +const clearUnread = (state) => { + state = state.set('unread', 0); + const lastNotification = state.get('items').find(item => item !== null); + return state.set('lastReadId', lastNotification ? lastNotification.get('id') : '0'); +} + const updateTop = (state, top) => { - if (top) { - state = state.set('unread', 0); - const lastNotification = state.get('items').find(item => item !== null); - state = state.set('lastReadId', lastNotification ? lastNotification.get('id') : '0'); + if (top && state.get('mounted') > 0) { + state = clearUnread(state); } return state.set('top', top); }; const deleteByStatus = (state, statusId) => { - if (!state.get('top')) { + const top = state.get('top') && state.get('mounted') > 0; + if (!top) { const lastReadId = state.get('lastReadId'); const deletedUnread = state.get('items').filter(item => item !== null && item.get('status') === statusId && compareId(item.get('id'), lastReadId) > 0); state = state.update('unread', unread => unread - deletedUnread.size); @@ -153,6 +161,10 @@ export default function notifications(state = initialState, action) { let st; switch(action.type) { + case NOTIFICATIONS_MOUNT: + return (state.get('top') ? clearUnread(state) : state).update('mounted', count => count + 1); + case NOTIFICATIONS_UNMOUNT: + return state.update('mounted', count => count - 1); case NOTIFICATIONS_EXPAND_REQUEST: case NOTIFICATIONS_DELETE_MARKED_REQUEST: return state.set('isLoading', true); -- cgit From d315f1dc02f15b55585a853ac19aefbe6983d87d Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 6 Sep 2018 17:47:33 +0200 Subject: Count unread notifications when window loses focus --- .../flavours/glitch/actions/notifications.js | 9 ++++++ .../flavours/glitch/features/ui/index.js | 26 +++++++++++++++- .../flavours/glitch/reducers/notifications.js | 36 +++++++++++++++++++--- 3 files changed, 65 insertions(+), 6 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js index ee148e4ef..fb84cd01e 100644 --- a/app/javascript/flavours/glitch/actions/notifications.js +++ b/app/javascript/flavours/glitch/actions/notifications.js @@ -28,6 +28,8 @@ export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP'; export const NOTIFICATIONS_MOUNT = 'NOTIFICATIONS_MOUNT'; export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT'; +export const NOTIFICATIONS_SET_VISIBILITY = 'NOTIFICATIONS_SET_VISIBILITY'; + defineMessages({ mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' }, }); @@ -231,3 +233,10 @@ export function unmountNotifications() { type: NOTIFICATIONS_UNMOUNT, }; }; + +export function notificationsSetVisibility(visibility) { + return { + type: NOTIFICATIONS_SET_VISIBILITY, + visibility: visibility, + }; +}; diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js index 1cff94321..c41436090 100644 --- a/app/javascript/flavours/glitch/features/ui/index.js +++ b/app/javascript/flavours/glitch/features/ui/index.js @@ -10,7 +10,7 @@ import { isMobile } from 'flavours/glitch/util/is_mobile'; import { debounce } from 'lodash'; import { uploadCompose, resetCompose } from 'flavours/glitch/actions/compose'; import { expandHomeTimeline } from 'flavours/glitch/actions/timelines'; -import { expandNotifications } from 'flavours/glitch/actions/notifications'; +import { expandNotifications, notificationsSetVisibility } from 'flavours/glitch/actions/notifications'; import { fetchFilters } from 'flavours/glitch/actions/filters'; import { clearHeight } from 'flavours/glitch/actions/height_cache'; import { WrappedSwitch, WrappedRoute } from 'flavours/glitch/util/react_router_helpers'; @@ -206,7 +206,27 @@ export default class UI extends React.Component { } } + handleVisibilityChange = () => { + const visibility = !document[this.visibilityHiddenProp]; + this.props.dispatch(notificationsSetVisibility(visibility)); + } + componentWillMount () { + if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support + this.visibilityHiddenProp = 'hidden'; + this.visibilityChange = 'visibilitychange'; + } else if (typeof document.msHidden !== 'undefined') { + this.visibilityHiddenProp = 'msHidden'; + this.visibilityChange = 'msvisibilitychange'; + } else if (typeof document.webkitHidden !== 'undefined') { + this.visibilityHiddenProp = 'webkitHidden'; + this.visibilityChange = 'webkitvisibilitychange'; + } + if (this.visibilityChange !== undefined) { + document.addEventListener(this.visibilityChange, this.handleVisibilityChange, false); + this.handleVisibilityChange(); + } + window.addEventListener('beforeunload', this.handleBeforeUnload, false); window.addEventListener('resize', this.handleResize, { passive: true }); document.addEventListener('dragenter', this.handleDragEnter, false); @@ -250,6 +270,10 @@ export default class UI extends React.Component { } componentWillUnmount () { + if (this.visibilityChange !== undefined) { + document.removeEventListener(this.visibilityChange, this.handleVisibilityChange); + } + window.removeEventListener('beforeunload', this.handleBeforeUnload); window.removeEventListener('resize', this.handleResize); document.removeEventListener('dragenter', this.handleDragEnter); diff --git a/app/javascript/flavours/glitch/reducers/notifications.js b/app/javascript/flavours/glitch/reducers/notifications.js index 9087e226c..0b816e85e 100644 --- a/app/javascript/flavours/glitch/reducers/notifications.js +++ b/app/javascript/flavours/glitch/reducers/notifications.js @@ -1,6 +1,7 @@ import { NOTIFICATIONS_MOUNT, NOTIFICATIONS_UNMOUNT, + NOTIFICATIONS_SET_VISIBILITY, NOTIFICATIONS_UPDATE, NOTIFICATIONS_EXPAND_SUCCESS, NOTIFICATIONS_EXPAND_REQUEST, @@ -31,6 +32,7 @@ const initialState = ImmutableMap({ lastReadId: '0', isLoading: false, cleaningMode: false, + isTabVisible: true, // notification removal mark of new notifs loaded whilst cleaningMode is true. markNewForDelete: false, }); @@ -44,7 +46,7 @@ const notificationToMap = (state, notification) => ImmutableMap({ }); const normalizeNotification = (state, notification) => { - const top = state.get('top') && state.get('mounted') > 0; + const top = !shouldCountUnreadNotifications(state); if (top) { state = state.set('lastReadId', notification.id); @@ -62,7 +64,7 @@ const normalizeNotification = (state, notification) => { }; const expandNormalizedNotifications = (state, notifications, next) => { - const top = state.get('top') && state.get('mounted') > 0; + const top = !(shouldCountUnreadNotifications(state)); const lastReadId = state.get('lastReadId'); let items = ImmutableList(); @@ -112,7 +114,9 @@ const clearUnread = (state) => { } const updateTop = (state, top) => { - if (top && state.get('mounted') > 0) { + state = state.set('top', top); + + if (!shouldCountUnreadNotifications(state)) { state = clearUnread(state); } @@ -120,7 +124,7 @@ const updateTop = (state, top) => { }; const deleteByStatus = (state, statusId) => { - const top = state.get('top') && state.get('mounted') > 0; + const top = !(shouldCountUnreadNotifications(state)); if (!top) { const lastReadId = state.get('lastReadId'); const deletedUnread = state.get('items').filter(item => item !== null && item.get('status') === statusId && compareId(item.get('id'), lastReadId) > 0); @@ -157,14 +161,36 @@ const deleteMarkedNotifs = (state) => { return state.update('items', list => list.filterNot(item => item.get('markedForDelete'))); }; +const updateMounted = (state) => { + state = state.update('mounted', count => count + 1); + if (!shouldCountUnreadNotifications(state)) { + state = clearUnread(state); + } + return state; +}; + +const updateVisibility = (state, visibility) => { + state = state.set('isTabVisible', visibility); + if (!shouldCountUnreadNotifications(state)) { + state = clearUnread(state); + } + return state; +}; + +const shouldCountUnreadNotifications = (state) => { + return !(state.get('isTabVisible') && state.get('top') && state.get('mounted') > 0); +}; + export default function notifications(state = initialState, action) { let st; switch(action.type) { case NOTIFICATIONS_MOUNT: - return (state.get('top') ? clearUnread(state) : state).update('mounted', count => count + 1); + return updateMounted(state); case NOTIFICATIONS_UNMOUNT: return state.update('mounted', count => count - 1); + case NOTIFICATIONS_SET_VISIBILITY: + return updateVisibility(state, action.visibility); case NOTIFICATIONS_EXPAND_REQUEST: case NOTIFICATIONS_DELETE_MARKED_REQUEST: return state.set('isLoading', true); -- cgit From 0f155af32a330bc8eb79c6e3ccec5331a1e37922 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 6 Sep 2018 16:09:57 +0200 Subject: Add notification badge to favicon --- app/javascript/flavours/glitch/features/ui/index.js | 10 ++++++++++ package.json | 1 + yarn.lock | 4 ++++ 3 files changed, 15 insertions(+) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js index c41436090..3dd894383 100644 --- a/app/javascript/flavours/glitch/features/ui/index.js +++ b/app/javascript/flavours/glitch/features/ui/index.js @@ -17,6 +17,7 @@ import { WrappedSwitch, WrappedRoute } from 'flavours/glitch/util/react_router_h import UploadArea from './components/upload_area'; import ColumnsAreaContainer from './containers/columns_area_container'; import classNames from 'classnames'; +import Favico from 'favico.js'; import { Drawer, Status, @@ -64,6 +65,7 @@ const mapStateToProps = state => ({ isWide: state.getIn(['local_settings', 'stretch']), navbarUnder: state.getIn(['local_settings', 'navbar_under']), dropdownMenuIsOpen: state.getIn(['dropdown_menu', 'openId']) !== null, + unreadNotifications: state.getIn(['notifications', 'unread']), }); const keyMap = { @@ -115,6 +117,7 @@ export default class UI extends React.Component { history: PropTypes.object.isRequired, intl: PropTypes.object.isRequired, dropdownMenuIsOpen: PropTypes.bool, + unreadNotifications: PropTypes.number, }; state = { @@ -239,6 +242,8 @@ export default class UI extends React.Component { navigator.serviceWorker.addEventListener('message', this.handleServiceWorkerPostMessage); } + this.favicon = new Favico({ animation:"none" }); + this.props.dispatch(expandHomeTimeline()); this.props.dispatch(expandNotifications()); setTimeout(() => this.props.dispatch(fetchFilters()), 500); @@ -267,6 +272,11 @@ export default class UI extends React.Component { if (![this.props.location.pathname, '/'].includes(prevProps.location.pathname)) { this.columnsAreaNode.handleChildrenContentChange(); } + if (this.props.unreadNotifications != prevProps.unreadNotifications) { + if (this.favicon) { + this.favicon.badge(this.props.unreadNotifications); + } + } } componentWillUnmount () { diff --git a/package.json b/package.json index 3f6f4c7fd..5636cb883 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "escape-html": "^1.0.3", "exif-js": "^2.3.0", "express": "^4.16.2", + "favico.js": "^0.3.10", "file-loader": "^1.1.11", "font-awesome": "^4.7.0", "glob": "^7.1.1", diff --git a/yarn.lock b/yarn.lock index e8c41786d..6b83d0544 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3091,6 +3091,10 @@ fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" +favico.js@^0.3.10: + version "0.3.10" + resolved "https://registry.yarnpkg.com/favico.js/-/favico.js-0.3.10.tgz#80586e27a117f24a8d51c18a99bdc714d4339301" + faye-websocket@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" -- cgit From 2cdc00bc8b41235b06090d34187ca71b8749aa27 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 6 Sep 2018 19:17:14 +0200 Subject: Add unread notifications badge to the navigation bar --- .../flavours/glitch/features/drawer/header/index.js | 9 ++++++++- app/javascript/flavours/glitch/features/drawer/index.js | 4 ++++ .../flavours/glitch/styles/components/index.scss | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/drawer/header/index.js b/app/javascript/flavours/glitch/features/drawer/header/index.js index deec42435..435538de4 100644 --- a/app/javascript/flavours/glitch/features/drawer/header/index.js +++ b/app/javascript/flavours/glitch/features/drawer/header/index.js @@ -46,6 +46,7 @@ const messages = defineMessages({ // The component. export default function DrawerHeader ({ columns, + unreadNotifications, intl, onSettingsClick, }) { @@ -77,7 +78,12 @@ export default function DrawerHeader ({ aria-label={intl.formatMessage(messages.notifications)} title={intl.formatMessage(messages.notifications)} to='/notifications' - > + > + + + { unreadNotifications > 0 &&
} + + ))} {renderForColumn('COMMUNITY', ( ({ searchHidden: state.getIn(['search', 'hidden']), searchValue: state.getIn(['search', 'value']), submitted: state.getIn(['search', 'submitted']), + unreadNotifications: state.getIn(['notifications', 'unread']), }); // Dispatch mapping. @@ -87,6 +88,7 @@ class Drawer extends React.Component { searchValue, submitted, isSearchPage, + unreadNotifications, } = this.props; const computedClass = classNames('drawer', `mbstobon-${elefriend}`); @@ -96,6 +98,7 @@ class Drawer extends React.Component { {multiColumn ? ( @@ -139,6 +142,7 @@ Drawer.propTypes = { searchHidden: PropTypes.bool, searchValue: PropTypes.string, submitted: PropTypes.bool, + unreadNotifications: PropTypes.number, // Dispatch props. onChange: PropTypes.func, diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index 1419888fa..52fe90885 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -1121,6 +1121,22 @@ left: 0; } +.icon-badge-wrapper { + position: relative; +} + +.icon-badge { + position: absolute; + display: block; + right: -.25em; + top: -.25em; + background-color: $ui-highlight-color; + border-radius: 50%; + font-size: 75%; + width: 1em; + height: 1em; +} + ::-webkit-scrollbar-thumb { border-radius: 0; } -- cgit From b28cbb8b25f3363bded6d6cbb8791ee80b24eeef Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 6 Sep 2018 19:42:16 +0200 Subject: Add unread notifications badge to the mobile navbar --- .../glitch/features/ui/components/tabs_bar.js | 24 +++++++++++++++++++++- .../flavours/glitch/styles/components/index.scss | 2 +- 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/features') 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 b2fee21e1..6b9cf27e1 100644 --- a/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js +++ b/app/javascript/flavours/glitch/features/ui/components/tabs_bar.js @@ -4,10 +4,32 @@ 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'; +import { connect } from 'react-redux'; + +const mapStateToProps = state => ({ + unreadNotifications: state.getIn(['notifications', 'unread']), +}); + +@connect(mapStateToProps) +class NotificationsIcon extends React.PureComponent { + static propTypes = { + unreadNotifications: PropTypes.number, + }; + + render() { + const { unreadNotifications } = this.props; + return ( + + + { unreadNotifications > 0 &&
} + + ); + } +} export const links = [ , - , + , , , diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index 52fe90885..81405f4b5 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -571,7 +571,7 @@ } } - span { + span:last-child { margin-left: 5px; display: none; } -- cgit From ba4521b175a2d0906e2a62e93e39cb80fa9286c9 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 6 Sep 2018 20:46:42 +0200 Subject: Move compose box options to their own page --- .../features/local_settings/navigation/index.js | 19 +++-- .../glitch/features/local_settings/page/index.js | 97 +++++++++++----------- 2 files changed, 63 insertions(+), 53 deletions(-) (limited to 'app/javascript/flavours/glitch/features') 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 0c1040290..a992b1ffc 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' }, + compose: { id: 'settings.compose_box_opts', defaultMessage: 'Compose box options' }, content_warnings: { id: 'settings.content_warnings', defaultMessage: 'Content Warnings' }, collapsed: { id: 'settings.collapsed_statuses', defaultMessage: 'Collapsed toots' }, media: { id: 'settings.media', defaultMessage: 'Media' }, @@ -43,31 +44,37 @@ export default class LocalSettingsNavigation extends React.PureComponent { active={index === 1} index={1} onNavigate={onNavigate} - title={intl.formatMessage(messages.content_warnings)} + title={intl.formatMessage(messages.compose)} /> + 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 0db49ba5d..9f300e7e9 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js @@ -74,53 +74,56 @@ export default class LocalSettingsPage extends React.PureComponent { -
-

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

+ + + + + + + + + + + +
), ({ intl, onChange, settings }) => ( -- cgit From 324ce93368bbac88a5b53083c8932ec175450f55 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 6 Sep 2018 20:55:11 +0200 Subject: Add preferences for notification badges --- .../flavours/glitch/features/drawer/header/index.js | 4 +++- .../flavours/glitch/features/drawer/index.js | 4 ++++ .../glitch/features/local_settings/page/index.js | 20 +++++++++++++++++++- .../glitch/features/ui/components/tabs_bar.js | 6 ++++-- app/javascript/flavours/glitch/features/ui/index.js | 7 +++++-- .../flavours/glitch/reducers/local_settings.js | 4 ++++ 6 files changed, 39 insertions(+), 6 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/drawer/header/index.js b/app/javascript/flavours/glitch/features/drawer/header/index.js index 435538de4..7fefd32c9 100644 --- a/app/javascript/flavours/glitch/features/drawer/header/index.js +++ b/app/javascript/flavours/glitch/features/drawer/header/index.js @@ -47,6 +47,7 @@ const messages = defineMessages({ export default function DrawerHeader ({ columns, unreadNotifications, + showNotificationsBadge, intl, onSettingsClick, }) { @@ -81,7 +82,7 @@ export default function DrawerHeader ({ > - { unreadNotifications > 0 &&
} + { showNotificationsBadge && unreadNotifications > 0 &&
} ))} @@ -119,6 +120,7 @@ export default function DrawerHeader ({ DrawerHeader.propTypes = { columns: ImmutablePropTypes.list, unreadNotifications: PropTypes.number, + showNotificationsBadge: PropTypes.bool, intl: PropTypes.object, onSettingsClick: PropTypes.func, }; diff --git a/app/javascript/flavours/glitch/features/drawer/index.js b/app/javascript/flavours/glitch/features/drawer/index.js index e8d9c86cb..72b36fcae 100644 --- a/app/javascript/flavours/glitch/features/drawer/index.js +++ b/app/javascript/flavours/glitch/features/drawer/index.js @@ -35,6 +35,7 @@ const mapStateToProps = state => ({ searchValue: state.getIn(['search', 'value']), submitted: state.getIn(['search', 'submitted']), unreadNotifications: state.getIn(['notifications', 'unread']), + showNotificationsBadge: state.getIn(['local_settings', 'notifications', 'tab_badge']), }); // Dispatch mapping. @@ -89,6 +90,7 @@ class Drawer extends React.Component { submitted, isSearchPage, unreadNotifications, + showNotificationsBadge, } = this.props; const computedClass = classNames('drawer', `mbstobon-${elefriend}`); @@ -99,6 +101,7 @@ class Drawer extends React.Component { @@ -143,6 +146,7 @@ Drawer.propTypes = { searchValue: PropTypes.string, submitted: PropTypes.bool, unreadNotifications: PropTypes.number, + showNotificationsBadge: PropTypes.bool, // Dispatch props. onChange: PropTypes.func, 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 9f300e7e9..2e14c9dd5 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js @@ -42,6 +42,25 @@ export default class LocalSettingsPage extends React.PureComponent { > +
+

+ + + + + + +

(
-

({ unreadNotifications: state.getIn(['notifications', 'unread']), + showBadge: state.getIn(['local_settings', 'notifications', 'tab_badge']), }); @connect(mapStateToProps) class NotificationsIcon extends React.PureComponent { static propTypes = { unreadNotifications: PropTypes.number, + showBadge: PropTypes.bool, }; render() { - const { unreadNotifications } = this.props; + const { unreadNotifications, showBadge } = this.props; return ( - { unreadNotifications > 0 &&
} + { showBadge && unreadNotifications > 0 &&
} ); } diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js index 3dd894383..064804b79 100644 --- a/app/javascript/flavours/glitch/features/ui/index.js +++ b/app/javascript/flavours/glitch/features/ui/index.js @@ -66,6 +66,7 @@ const mapStateToProps = state => ({ navbarUnder: state.getIn(['local_settings', 'navbar_under']), dropdownMenuIsOpen: state.getIn(['dropdown_menu', 'openId']) !== null, unreadNotifications: state.getIn(['notifications', 'unread']), + showFaviconBadge: state.getIn(['local_settings', 'notifications', 'favicon_badge']), }); const keyMap = { @@ -118,6 +119,7 @@ export default class UI extends React.Component { intl: PropTypes.object.isRequired, dropdownMenuIsOpen: PropTypes.bool, unreadNotifications: PropTypes.number, + showFaviconBadge: PropTypes.bool, }; state = { @@ -272,9 +274,10 @@ export default class UI extends React.Component { if (![this.props.location.pathname, '/'].includes(prevProps.location.pathname)) { this.columnsAreaNode.handleChildrenContentChange(); } - if (this.props.unreadNotifications != prevProps.unreadNotifications) { + if (this.props.unreadNotifications != prevProps.unreadNotifications || + this.props.showFaviconBadge != prevProps.showFaviconBadge) { if (this.favicon) { - this.favicon.badge(this.props.unreadNotifications); + this.favicon.badge(this.props.showFaviconBadge ? this.props.unreadNotifications : 0); } } } diff --git a/app/javascript/flavours/glitch/reducers/local_settings.js b/app/javascript/flavours/glitch/reducers/local_settings.js index 063ae3943..f5f7220b9 100644 --- a/app/javascript/flavours/glitch/reducers/local_settings.js +++ b/app/javascript/flavours/glitch/reducers/local_settings.js @@ -37,6 +37,10 @@ const initialState = ImmutableMap({ letterbox : true, fullwidth : true, }), + notifications : ImmutableMap({ + favicon_badge : false, + tab_badge : true, + }), }); const hydrate = (state, localSettings) => state.mergeDeep(localSettings); -- cgit From 49eaf72faf5b8b6f574a759a990c230f82c3b891 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 10 Sep 2018 17:49:45 +0200 Subject: [Glitch] Add embed_url to preview cards Port front-end changes from c083816c2479dcdfa6674c47a75a8293bf64a947 to glitch-soc --- app/javascript/flavours/glitch/features/status/components/card.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/status/components/card.js b/app/javascript/flavours/glitch/features/status/components/card.js index 680bf63ab..d3e322c36 100644 --- a/app/javascript/flavours/glitch/features/status/components/card.js +++ b/app/javascript/flavours/glitch/features/status/components/card.js @@ -101,7 +101,7 @@ export default class Card extends React.PureComponent { onClick={this.handlePhotoClick} role='button' tabIndex='0' - src={card.get('url')} + src={card.get('embed_url')} alt={card.get('title')} width={card.get('width')} height={card.get('height')} -- cgit From cc5826521619e64022a965e2d414fd29c834612c Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 10 Sep 2018 17:51:00 +0200 Subject: [Glitch] Ensure link thumbnails are not stretched to super low quality Port front-end changes from c36b9cc5a6cf3feacb925213f5530c90dd31fa7a to glitch-soc --- .../flavours/glitch/features/status/components/card.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/status/components/card.js b/app/javascript/flavours/glitch/features/status/components/card.js index d3e322c36..f7d980066 100644 --- a/app/javascript/flavours/glitch/features/status/components/card.js +++ b/app/javascript/flavours/glitch/features/status/components/card.js @@ -59,6 +59,8 @@ export default class Card extends React.PureComponent { renderLink () { const { card, maxDescription } = this.props; + const { width } = this.state; + const horizontal = card.get('width') > card.get('height') && (card.get('width') + 100 >= width); let image = ''; let provider = card.get('provider_name'); @@ -75,17 +77,15 @@ export default class Card extends React.PureComponent { provider = decodeIDNA(getHostname(card.get('url'))); } - const className = classnames('status-card', { - 'horizontal': card.get('width') > card.get('height'), - }); + const className = classnames('status-card', { horizontal }); return ( - + {image}
{card.get('title')} -

{(card.get('description') || '').substring(0, maxDescription)}

+ {!horizontal &&

{(card.get('description') || '').substring(0, maxDescription)}

} {provider}
-- cgit From dfa6fb49277d385b6de93ea43e428d53eb7721a9 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 10 Sep 2018 17:52:40 +0200 Subject: [Glitch] Fix oEmbed image_modal src. Port 25b0d7538eb83c5fd02409ca22345c9af752b3ed to glitch-soc --- app/javascript/flavours/glitch/features/status/components/card.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/status/components/card.js b/app/javascript/flavours/glitch/features/status/components/card.js index f7d980066..2f6a7831e 100644 --- a/app/javascript/flavours/glitch/features/status/components/card.js +++ b/app/javascript/flavours/glitch/features/status/components/card.js @@ -43,7 +43,7 @@ export default class Card extends React.PureComponent { Immutable.fromJS([ { type: 'image', - url: card.get('url'), + url: card.get('embed_url'), description: card.get('title'), meta: { original: { -- cgit From bc5009cd45a4fd8fb2178909e1da981e878b879e Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 10 Sep 2018 17:53:28 +0200 Subject: [Glitch] Click card to embed external content Port front-end changes from f7765acf9d92951a616f41b738d5d23ede58c162 to glitch-soc --- .../glitch/features/status/components/card.js | 150 ++++++++++++--------- .../flavours/glitch/styles/components/status.scss | 63 +++++++-- 2 files changed, 141 insertions(+), 72 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/status/components/card.js b/app/javascript/flavours/glitch/features/status/components/card.js index 2f6a7831e..8a6383471 100644 --- a/app/javascript/flavours/glitch/features/status/components/card.js +++ b/app/javascript/flavours/glitch/features/status/components/card.js @@ -20,6 +20,16 @@ const getHostname = url => { return parser.hostname; }; +const trim = (text, len) => { + const cut = text.indexOf(' ', len); + + if (cut === -1) { + return text; + } + + return text.substring(0, cut) + (text.length > len ? '…' : ''); +}; + export default class Card extends React.PureComponent { static propTypes = { @@ -33,9 +43,16 @@ export default class Card extends React.PureComponent { }; state = { - width: 0, + width: 280, + embedded: false, }; + componentWillReceiveProps (nextProps) { + if (this.props.card !== nextProps.card) { + this.setState({ embedded: false }); + } + } + handlePhotoClick = () => { const { card, onOpenMedia } = this.props; @@ -57,56 +74,14 @@ export default class Card extends React.PureComponent { ); }; - renderLink () { - const { card, maxDescription } = this.props; - const { width } = this.state; - const horizontal = card.get('width') > card.get('height') && (card.get('width') + 100 >= width); - - let image = ''; - let provider = card.get('provider_name'); - - if (card.get('image')) { - image = ( -
- {card.get('title')} -
- ); - } - - if (provider.length < 1) { - provider = decodeIDNA(getHostname(card.get('url'))); - } - - const className = classnames('status-card', { horizontal }); - - return ( - - {image} - -
- {card.get('title')} - {!horizontal &&

{(card.get('description') || '').substring(0, maxDescription)}

} - {provider} -
-
- ); - } - - renderPhoto () { + handleEmbedClick = () => { const { card } = this.props; - return ( - {card.get('title')} - ); + if (card.get('type') === 'photo') { + this.handlePhotoClick(); + } else { + this.setState({ embedded: true }); + } } setRef = c => { @@ -125,7 +100,7 @@ export default class Card extends React.PureComponent { return (
@@ -133,23 +108,76 @@ export default class Card extends React.PureComponent { } render () { - const { card } = this.props; + const { card, maxDescription } = this.props; + const { width, embedded } = this.state; if (card === null) { return null; } - switch(card.get('type')) { - case 'link': - return this.renderLink(); - case 'photo': - return this.renderPhoto(); - case 'video': - return this.renderVideo(); - case 'rich': - default: - return null; + const provider = card.get('provider_name').length === 0 ? decodeIDNA(getHostname(card.get('url'))) : card.get('provider_name'); + const horizontal = card.get('width') > card.get('height') && (card.get('width') + 100 >= width) || card.get('type') !== 'link'; + const className = classnames('status-card', { horizontal }); + const interactive = card.get('type') !== 'link'; + const title = interactive ? {card.get('title')} : {card.get('title')}; + const ratio = card.get('width') / card.get('height'); + const height = card.get('width') > card.get('height') ? (width / ratio) : (width * ratio); + + const description = ( +
+ {title} + {!horizontal &&

{trim(card.get('description') || '', maxDescription)}

} + {provider} +
+ ); + + let embed = ''; + let thumbnail =
; + + if (interactive) { + if (embedded) { + embed = this.renderVideo(); + } else { + let iconVariant = 'play'; + + if (card.get('type') === 'photo') { + iconVariant = 'search-plus'; + } + + embed = ( +
+ {thumbnail} + +
+
+ + +
+
+
+ ); + } + + return ( +
+ {embed} + {description} +
+ ); + } else if (card.get('image')) { + embed = ( +
+ {thumbnail} +
+ ); } + + return ( + + {embed} + {description} + + ); } } diff --git a/app/javascript/flavours/glitch/styles/components/status.scss b/app/javascript/flavours/glitch/styles/components/status.scss index b841d73c4..5c1cb62a8 100644 --- a/app/javascript/flavours/glitch/styles/components/status.scss +++ b/app/javascript/flavours/glitch/styles/components/status.scss @@ -623,7 +623,6 @@ .status-card { display: flex; - cursor: pointer; font-size: 14px; border: 1px solid lighten($ui-base-color, 8%); border-radius: 4px; @@ -632,20 +631,58 @@ text-decoration: none; overflow: hidden; - &:hover { - background: lighten($ui-base-color, 8%); + &__actions { + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; + display: flex; + justify-content: center; + align-items: center; + + & > div { + background: rgba($base-shadow-color, 0.6); + border-radius: 4px; + padding: 12px 9px; + flex: 0 0 auto; + display: flex; + justify-content: center; + align-items: center; + } + + button, + a { + display: inline; + color: $primary-text-color; + background: transparent; + border: 0; + padding: 0 5px; + text-decoration: none; + opacity: 0.6; + font-size: 18px; + line-height: 18px; + + &:hover, + &:active, + &:focus { + opacity: 1; + } + } + + a { + font-size: 19px; + position: relative; + bottom: -1px; + } } } -.status-card-video, -.status-card-rich, -.status-card-photo { - margin-top: 14px; - overflow: hidden; +a.status-card { + cursor: pointer; - iframe { - width: 100%; - height: auto; + &:hover { + background: lighten($ui-base-color, 8%); } } @@ -673,6 +710,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + text-decoration: none; } .status-card__content { @@ -694,6 +732,7 @@ .status-card__image { flex: 0 0 100px; background: lighten($ui-base-color, 8%); + position: relative; } .status-card.horizontal { @@ -719,6 +758,8 @@ width: 100%; height: 100%; object-fit: cover; + background-size: cover; + background-position: center center; } .status__video-player { -- cgit From d9a92d504053568ce424f23667c7dc6121d9b20d Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 10 Sep 2018 17:58:21 +0200 Subject: [Glitch] After click to embed video, autoplay it Port 478ca39e5e8463044a259388459da56d2141e104 to glitch-soc --- .../glitch/features/status/components/card.js | 25 +++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/status/components/card.js b/app/javascript/flavours/glitch/features/status/components/card.js index 8a6383471..b52f3c4fa 100644 --- a/app/javascript/flavours/glitch/features/status/components/card.js +++ b/app/javascript/flavours/glitch/features/status/components/card.js @@ -30,6 +30,29 @@ const trim = (text, len) => { return text.substring(0, cut) + (text.length > len ? '…' : ''); }; +const domParser = new DOMParser(); + +const addAutoPlay = html => { + const document = domParser.parseFromString(html, 'text/html').documentElement; + const iframe = document.querySelector('iframe'); + + if (iframe) { + if (iframe.src.indexOf('?') !== -1) { + iframe.src += '&'; + } else { + iframe.src += '?'; + } + + iframe.src += 'autoplay=1&auto_play=1'; + + // DOM parser creates html/body elements around original HTML fragment, + // so we need to get innerHTML out of the body and not the entire document + return document.querySelector('body').innerHTML; + } + + return html; +}; + export default class Card extends React.PureComponent { static propTypes = { @@ -92,7 +115,7 @@ export default class Card extends React.PureComponent { renderVideo () { const { card } = this.props; - const content = { __html: card.get('html') }; + const content = { __html: addAutoPlay(card.get('html')) }; const { width } = this.state; const ratio = card.get('width') / card.get('height'); const height = card.get('width') > card.get('height') ? (width / ratio) : (width * ratio); -- cgit From 65f625cf237feb55a21495606d5e2c258bbe50cc Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 11 Sep 2018 16:11:26 +0200 Subject: [Glitch] Hide floating action button on thread views Port f66a7860291e6b2fef1844b580c22296dbad9202 to glitch-soc --- app/javascript/flavours/glitch/features/ui/components/columns_area.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') 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 f87c078ec..71cb7e8c9 100644 --- a/app/javascript/flavours/glitch/features/ui/components/columns_area.js +++ b/app/javascript/flavours/glitch/features/ui/components/columns_area.js @@ -30,6 +30,8 @@ const componentMap = { 'LIST': ListTimeline, }; +const shouldHideFAB = path => path.match(/^\/statuses\//); + const messages = defineMessages({ publish: { id: 'compose_form.publish', defaultMessage: 'Toot' }, }); @@ -158,7 +160,7 @@ export default class ColumnsArea extends ImmutablePureComponent { this.pendingIndex = null; if (singleColumn) { - const floatingActionButton = this.context.router.history.location.pathname === '/statuses/new' ? null : ; + const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : ; return columnIndex !== -1 ? [ -- cgit From 59de2868c13a61bce08923f841024fefebe3b3da Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 11 Sep 2018 15:45:51 +0200 Subject: Fix media description in various media modals --- app/javascript/flavours/glitch/features/ui/components/media_modal.js | 2 +- app/javascript/flavours/glitch/features/ui/components/video_modal.js | 2 +- .../flavours/glitch/features/ui/components/zoomable_image.js | 1 + app/javascript/flavours/glitch/features/video/index.js | 3 ++- 4 files changed, 5 insertions(+), 3 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/ui/components/media_modal.js b/app/javascript/flavours/glitch/features/ui/components/media_modal.js index d4fd45d4d..1f3ac18ea 100644 --- a/app/javascript/flavours/glitch/features/ui/components/media_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/media_modal.js @@ -129,7 +129,7 @@ export default class MediaModal extends ImmutablePureComponent { startTime={time || 0} onCloseVideo={onClose} detailed - description={image.get('description')} + alt={image.get('description')} key={image.get('url')} /> ); diff --git a/app/javascript/flavours/glitch/features/ui/components/video_modal.js b/app/javascript/flavours/glitch/features/ui/components/video_modal.js index e0cb7fc09..69e0ee46e 100644 --- a/app/javascript/flavours/glitch/features/ui/components/video_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/video_modal.js @@ -24,7 +24,7 @@ export default class VideoModal extends ImmutablePureComponent { startTime={time} onCloseVideo={onClose} detailed - description={media.get('description')} + alt={media.get('description')} />
diff --git a/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js b/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js index 0a0a4d41a..3f6562bc9 100644 --- a/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js +++ b/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js @@ -137,6 +137,7 @@ export default class ZoomableImage extends React.PureComponent { role='presentation' ref={this.setImageRef} alt={alt} + title={alt} src={src} style={{ transform: `scale(${scale})`, diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index 44aba797c..65e10e0cf 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -261,11 +261,12 @@ export default class Video extends React.PureComponent { } handleOpenVideo = () => { - const { src, preview, width, height } = this.props; + const { src, preview, width, height, alt } = this.props; const media = fromJS({ type: 'video', url: src, preview_url: preview, + description: alt, width, height, }); -- cgit From 307fb338ee4432a933ad8c8efe70b1a78d8b3bc0 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 11 Sep 2018 21:34:07 +0200 Subject: Fix composer actions modal --- app/javascript/flavours/glitch/features/composer/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js index 77f9ee0c1..ff01408e7 100644 --- a/app/javascript/flavours/glitch/features/composer/index.js +++ b/app/javascript/flavours/glitch/features/composer/index.js @@ -146,7 +146,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onMount() { dispatch(mountCompose()); }, - onOpenActionModal(props) { + onOpenActionsModal(props) { dispatch(openModal('ACTIONS', props)); }, onOpenDoodleModal() { -- cgit From b3c698d6f4c0e35006173877db750841f96a2674 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 13 Sep 2018 11:55:41 +0200 Subject: Auto-focus emoji picker's search field --- app/javascript/flavours/glitch/features/emoji_picker/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/emoji_picker/index.js b/app/javascript/flavours/glitch/features/emoji_picker/index.js index d22a50848..a78117971 100644 --- a/app/javascript/flavours/glitch/features/emoji_picker/index.js +++ b/app/javascript/flavours/glitch/features/emoji_picker/index.js @@ -340,6 +340,7 @@ class EmojiPickerMenu extends React.PureComponent { skin={skinTone} showPreview={false} backgroundImageFn={backgroundImageFn} + autoFocus emojiTooltip /> -- cgit From 1cb3af21c5bb8f944a88c4e89ab28ff6b7e02552 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 13 Sep 2018 12:05:18 +0200 Subject: Autofocus comment textarea in report modal --- app/javascript/flavours/glitch/features/ui/components/report_modal.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/ui/components/report_modal.js b/app/javascript/flavours/glitch/features/ui/components/report_modal.js index 81643b6c2..a139394ac 100644 --- a/app/javascript/flavours/glitch/features/ui/components/report_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/report_modal.js @@ -106,6 +106,7 @@ export default class ReportModal extends ImmutablePureComponent { onChange={this.handleCommentChange} onKeyDown={this.handleKeyDown} disabled={isSubmitting} + autoFocus /> {domain && ( -- cgit From cf142e85569be5e7e0dae7e02f490c737a238319 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 13 Sep 2018 11:20:21 +0200 Subject: [Glitch] Highlight active tab in action bar Port 7b7c26063e3fcf9e75a61780d81bd60b7c398ead to glitch-soc --- .../glitch/features/account/components/action_bar.js | 14 +++++++------- .../flavours/glitch/styles/components/accounts.scss | 5 +++++ 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'app/javascript/flavours/glitch/features') 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 26717ee49..e60b25855 100644 --- a/app/javascript/flavours/glitch/features/account/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/account/components/action_bar.js @@ -2,7 +2,7 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; -import { Link } from 'react-router-dom'; +import { NavLink } from 'react-router-dom'; import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; import { me, isStaff } from 'flavours/glitch/util/initial_state'; @@ -136,20 +136,20 @@ export default class ActionBar extends React.PureComponent {
- + - + - + - + - + - +
diff --git a/app/javascript/flavours/glitch/styles/components/accounts.scss b/app/javascript/flavours/glitch/styles/components/accounts.scss index b2b6248ff..3eddd7fb4 100644 --- a/app/javascript/flavours/glitch/styles/components/accounts.scss +++ b/app/javascript/flavours/glitch/styles/components/accounts.scss @@ -239,6 +239,11 @@ flex: 0 1 100%; border-left: 1px solid lighten($ui-base-color, 8%); padding: 10px 0; + border-bottom: 4px solid transparent; + + &.active { + border-bottom: 4px solid $ui-highlight-color; + } & > span { display: block; -- cgit From 657805f444ffd8d1cc0a36e0c37276a01611dc26 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sun, 16 Sep 2018 12:15:58 +0200 Subject: Fix thread CW expansion not being reset when changing threads --- app/javascript/flavours/glitch/features/status/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index 3d309976a..33a7bd075 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -103,7 +103,7 @@ export default class Status extends ImmutablePureComponent { 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) }); + this.setState({ isExpanded: autoUnfoldCW(nextProps.settings, nextProps.status), threadExpanded: undefined }); } } -- cgit From 925c185ef9cfba24cdeb7c3555b7f75c55738cab Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 17 Sep 2018 14:19:35 +0200 Subject: Prevent clicks on video from initiating selections --- app/javascript/flavours/glitch/components/media_gallery.js | 6 ++++++ app/javascript/flavours/glitch/features/video/index.js | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.js index 1de12c5e0..605a2862b 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.js @@ -78,6 +78,11 @@ class Item extends React.PureComponent { e.stopPropagation(); } + handleMouseDown = (e) => { + e.preventDefault(); + e.stopPropagation(); + } + render () { const { attachment, index, size, standalone, letterbox, displayWidth } = this.props; @@ -181,6 +186,7 @@ class Item extends React.PureComponent { onClick={this.handleClick} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} + onMouseDown={this.handleMouseDown} autoPlay={autoPlay} loop muted diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index 65e10e0cf..5cbe01f26 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -135,7 +135,10 @@ export default class Video extends React.PureComponent { this.seek = c; } - handleClickRoot = e => e.stopPropagation(); + handleMouseDownRoot = e => { + e.preventDefault(); + e.stopPropagation(); + } handlePlay = () => { this.setState({ paused: false }); @@ -319,7 +322,7 @@ export default class Video extends React.PureComponent { ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} - onClick={this.handleClickRoot} + onMouseDown={this.handleMouseDownRoot} tabIndex={0} >
- + -- cgit From 5833cc41c2a3e53332968dbeed384f565472eba4 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 21 Sep 2018 07:25:46 +0200 Subject: [Glitch] Add edit profile action button to profile Port some parts from 1a7a74ff76a129031a3fd6d73688ab9409899002 --- .../flavours/glitch/features/account/components/header.js | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index eda0d637e..9cf2e9131 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -15,6 +15,7 @@ const messages = defineMessages({ follow: { id: 'account.follow', defaultMessage: 'Follow' }, requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, + edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, }); @injectIntl @@ -27,6 +28,10 @@ export default class Header extends ImmutablePureComponent { intl: PropTypes.object.isRequired, }; + openEditProfile = () => { + window.open('/settings/profile', '_blank'); + } + render () { const { account, intl } = this.props; @@ -77,6 +82,12 @@ export default class Header extends ImmutablePureComponent {
); } + } else { + actionBtn = ( +
+ +
+ ); } if (account.get('moved') && !account.getIn(['relationship', 'following'])) { -- cgit From 9e8d776a77731598c1ad57c5d61d8c74dc04b5a4 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 21 Sep 2018 07:37:37 +0200 Subject: [Glitch] Display verified links in glitch flavor Port front-end changes from f4d549d30081478b1fe2bde9d340262e132bb891 to glitch-soc --- .../glitch/features/account/components/header.js | 14 +++++++++++++- .../flavours/glitch/styles/components/metadata.scss | 21 ++++++--------------- 2 files changed, 19 insertions(+), 16 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index 9cf2e9131..f0d36947d 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -16,8 +16,18 @@ const messages = defineMessages({ requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, + link_verified_on: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' }, }); +const dateFormatOptions = { + month: 'short', + day: 'numeric', + year: 'numeric', + hour12: false, + hour: '2-digit', + minute: '2-digit', +}; + @injectIntl export default class Header extends ImmutablePureComponent { @@ -122,7 +132,9 @@ export default class Header extends ImmutablePureComponent { {fields.map((pair, i) => (
-
+
+ {pair.get('verified_at') && } +
))}
diff --git a/app/javascript/flavours/glitch/styles/components/metadata.scss b/app/javascript/flavours/glitch/styles/components/metadata.scss index 2efe6cd66..32bdcdcf1 100644 --- a/app/javascript/flavours/glitch/styles/components/metadata.scss +++ b/app/javascript/flavours/glitch/styles/components/metadata.scss @@ -4,17 +4,11 @@ overflow: hidden; margin: 20px -10px -20px; border-bottom: 0; - - a { - text-decoration: none; - - &:hover{ - text-decoration: underline; - } - } + border-top: 0; dl { - border-top: 1px solid lighten($ui-base-color, 8%); + border-top: 1px solid lighten($ui-base-color, 4%); + border-bottom: 0; display: flex; } @@ -35,10 +29,6 @@ width: 120px; flex: 0 0 auto; font-weight: 500; - - a { - color: $primary-text-color; - } } dd { @@ -46,8 +36,9 @@ color: $primary-text-color; background: $ui-base-color; - a { - color: $highlight-text-color; + &.verified { + border: 1px solid rgba($valid-value-color, 0.5); + background: rgba($valid-value-color, 0.25); } } } -- cgit From d3426ed87ab3be29dece3f8d2c22bece9dda32dc Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 21 Sep 2018 23:20:06 +0200 Subject: Disable the “TOOT” button (and secondary toot button) if the toot text is empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/javascript/flavours/glitch/features/composer/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js index ff01408e7..c1bd77844 100644 --- a/app/javascript/flavours/glitch/features/composer/index.js +++ b/app/javascript/flavours/glitch/features/composer/index.js @@ -242,7 +242,7 @@ const handlers = { } // Submit disabled: - if (isSubmitting || isUploading || (!!text.length && !text.trim().length && !anyMedia)) { + if (isSubmitting || isUploading || (!text.trim().length && !anyMedia)) { return; } @@ -415,7 +415,7 @@ class Composer extends React.Component { spoilersAlwaysOn, } = this.props; - let disabledButton = isSubmitting || isUploading || (!!text.length && !text.trim().length && !anyMedia); + let disabledButton = isSubmitting || isUploading || (!text.trim().length && !anyMedia); return (
-- cgit From fa18859b206bbfd61e08a8f8b39de972dcf3b440 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 22 Sep 2018 23:08:03 +0200 Subject: [Glitch] Adjust beforeUnload conditions Port 05f90e3695c410526fc7fa79fc6a9bdaa717cb87 to glitch-soc --- app/javascript/flavours/glitch/features/ui/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js index 064804b79..ecbac1f8f 100644 --- a/app/javascript/flavours/glitch/features/ui/index.js +++ b/app/javascript/flavours/glitch/features/ui/index.js @@ -60,7 +60,8 @@ const messages = defineMessages({ }); const mapStateToProps = state => ({ - hasComposingText: state.getIn(['compose', 'text']) !== '', + hasComposingText: state.getIn(['compose', 'text']).trim().length !== 0, + hasMediaAttachments: state.getIn(['compose', 'media_attachments']).size > 0, layout: state.getIn(['local_settings', 'layout']), isWide: state.getIn(['local_settings', 'stretch']), navbarUnder: state.getIn(['local_settings', 'navbar_under']), @@ -113,6 +114,7 @@ export default class UI extends React.Component { navbarUnder: PropTypes.bool, isComposing: PropTypes.bool, hasComposingText: PropTypes.bool, + hasMediaAttachments: PropTypes.bool, match: PropTypes.object.isRequired, location: PropTypes.object.isRequired, history: PropTypes.object.isRequired, @@ -128,9 +130,9 @@ export default class UI extends React.Component { }; handleBeforeUnload = (e) => { - const { intl, hasComposingText } = this.props; + const { intl, hasComposingText, hasMediaAttachments } = this.props; - if (hasComposingText) { + if (hasComposingText || hasMediaAttachments) { // Setting returnValue to any string causes confirmation dialog. // Many browsers no longer display this text to users, // but we set user-friendly message for other browsers, e.g. Edge. -- cgit From 9594c68532b3baeba340c426cf3490fa826fc017 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 28 Sep 2018 18:44:55 +0200 Subject: Scroll to textarea when composing a toot --- app/javascript/flavours/glitch/features/composer/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js index ff01408e7..0820ab2e3 100644 --- a/app/javascript/flavours/glitch/features/composer/index.js +++ b/app/javascript/flavours/glitch/features/composer/index.js @@ -347,6 +347,7 @@ class Composer extends React.Component { if (textarea) { textarea.setSelectionRange(selectionStart, selectionEnd); textarea.focus(); + textarea.scrollIntoView(); } // Refocuses the textarea after submitting. -- cgit From 15134beb1e45be35a5c0091220c9074b79f64653 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 28 Sep 2018 18:18:57 +0200 Subject: Fix styling issue in “Compose box options” local settings page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/javascript/flavours/glitch/features/local_settings/page/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') 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 2e14c9dd5..3859c1947 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js @@ -96,7 +96,7 @@ export default class LocalSettingsPage extends React.PureComponent {
), ({ intl, onChange, settings }) => ( -
+

Date: Fri, 28 Sep 2018 20:58:03 +0200 Subject: Make pre-selection of usernames optional when replying to a toot Fixes #751 --- app/javascript/flavours/glitch/features/composer/index.js | 5 ++++- .../flavours/glitch/features/local_settings/page/index.js | 8 ++++++++ app/javascript/flavours/glitch/reducers/local_settings.js | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js index ff01408e7..1280af75e 100644 --- a/app/javascript/flavours/glitch/features/composer/index.js +++ b/app/javascript/flavours/glitch/features/composer/index.js @@ -102,6 +102,7 @@ function mapStateToProps (state) { anyMedia: state.getIn(['compose', 'media_attachments']).size > 0, spoilersAlwaysOn: spoilersAlwaysOn, mediaDescriptionConfirmation: state.getIn(['local_settings', 'confirm_missing_media_description']), + preselectOnReply: state.getIn(['local_settings', 'preselect_on_reply']), }; }; @@ -328,13 +329,14 @@ class Composer extends React.Component { isSubmitting, preselectDate, text, + preselectOnReply, } = this.props; let selectionEnd, selectionStart; // Caret/selection handling. if (focusDate !== prevProps.focusDate) { switch (true) { - case preselectDate !== prevProps.preselectDate: + case preselectDate !== prevProps.preselectDate && preselectOnReply: selectionStart = text.search(/\s/) + 1; selectionEnd = text.length; break; @@ -533,6 +535,7 @@ Composer.propTypes = { anyMedia: PropTypes.bool, spoilersAlwaysOn: PropTypes.bool, mediaDescriptionConfirmation: PropTypes.bool, + preselectOnReply: PropTypes.bool, // Dispatch props. onCancelReply: PropTypes.func, 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 3859c1947..5b4e0cb01 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js @@ -106,6 +106,14 @@ export default class LocalSettingsPage extends React.PureComponent { > + + + Date: Sat, 29 Sep 2018 16:44:02 -0700 Subject: Add option to hide action bar in collapsed toots --- app/javascript/flavours/glitch/components/status.js | 2 +- .../flavours/glitch/features/local_settings/page/index.js | 12 ++++++++++++ app/javascript/flavours/glitch/locales/en.js | 1 + app/javascript/flavours/glitch/reducers/local_settings.js | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index 4d47660c2..665aa457a 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -566,7 +566,7 @@ export default class Status extends ImmutablePureComponent { parseClick={parseClick} disabled={!router} /> - {!isCollapsed || !muted ? ( + {!isCollapsed || !(muted || !settings.getIn(['collapsed', 'show_action_bar'])) ? ( +
+

+ + + +
), ({ onChange, settings }) => ( diff --git a/app/javascript/flavours/glitch/locales/en.js b/app/javascript/flavours/glitch/locales/en.js index fb3763ced..90e924d4a 100644 --- a/app/javascript/flavours/glitch/locales/en.js +++ b/app/javascript/flavours/glitch/locales/en.js @@ -18,6 +18,7 @@ const messages = { 'settings.auto_collapse_notifications': 'Notifications', 'settings.auto_collapse_reblogs': 'Boosts', 'settings.auto_collapse_replies': 'Replies', + 'settings.show_action_bar': 'Show action buttons in collapsed toots', 'settings.close': 'Close', 'settings.collapsed_statuses': 'Collapsed toots', 'settings.enable_collapsed': 'Enable collapsed toots', diff --git a/app/javascript/flavours/glitch/reducers/local_settings.js b/app/javascript/flavours/glitch/reducers/local_settings.js index 260a9f08f..19233a963 100644 --- a/app/javascript/flavours/glitch/reducers/local_settings.js +++ b/app/javascript/flavours/glitch/reducers/local_settings.js @@ -33,6 +33,7 @@ const initialState = ImmutableMap({ user_backgrounds : false, preview_images : false, }), + show_action_bar : true, }), media : ImmutableMap({ letterbox : true, -- cgit