diff --git a/app/javascript/flavours/glitch/components/dropdown_menu.js b/app/javascript/flavours/glitch/components/dropdown_menu.js index 245bebef3..27b2586e5 100644 --- a/app/javascript/flavours/glitch/components/dropdown_menu.js +++ b/app/javascript/flavours/glitch/components/dropdown_menu.js @@ -43,6 +43,7 @@ class DropdownMenu extends React.PureComponent { componentDidMount () { document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); + if (this.focusedItem) this.focusedItem.focus(); this.setState({ mounted: true }); } @@ -55,6 +56,46 @@ class DropdownMenu extends React.PureComponent { this.node = c; } + setFocusRef = c => { + this.focusedItem = c; + } + + handleKeyDown = e => { + const items = Array.from(this.node.getElementsByTagName('a')); + const index = items.indexOf(e.currentTarget); + let element; + + switch(e.key) { + case 'Enter': + this.handleClick(e); + break; + case 'ArrowDown': + element = items[index+1]; + if (element) { + element.focus(); + } + break; + case 'ArrowUp': + element = items[index-1]; + if (element) { + element.focus(); + } + break; + case 'Home': + element = items[0]; + if (element) { + element.focus(); + } + break; + case 'End': + element = items[items.length-1]; + if (element) { + element.focus(); + } + break; + } + } + handleClick = e => { const i = Number(e.currentTarget.getAttribute('data-index')); const { action, to } = this.props.items[i]; @@ -79,7 +120,7 @@ class DropdownMenu extends React.PureComponent { return (
  • - + {text}
  • @@ -156,9 +197,6 @@ export default class Dropdown extends React.PureComponent { handleKeyDown = e => { switch(e.key) { - case 'Enter': - this.handleClick(e); - break; case 'Escape': this.handleClose(); break; diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.js index 925132b07..7f5150f7b 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.js @@ -202,6 +202,7 @@ export default class MediaGallery extends React.PureComponent { static propTypes = { sensitive: PropTypes.bool, + revealed: PropTypes.bool, standalone: PropTypes.bool, letterbox: PropTypes.bool, fullwidth: PropTypes.bool, @@ -216,7 +217,7 @@ export default class MediaGallery extends React.PureComponent { }; state = { - visible: !this.props.sensitive || displaySensitiveMedia, + visible: this.props.revealed === undefined ? (!this.props.sensitive || displaySensitiveMedia) : this.props.revealed, }; componentWillReceiveProps (nextProps) { diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index a208f1a8e..7a0a2dfa9 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -37,6 +37,7 @@ export default class Header extends ImmutablePureComponent { } let displayName = account.get('display_name_html'); + let fields = account.get('fields'); let info = ''; let mutingInfo = ''; let actionBtn = ''; @@ -100,30 +101,43 @@ export default class Header extends ImmutablePureComponent { @{account.get('acct')} {account.get('locked') ? : null}
    + {fields.size > 0 && ( + + + {fields.map((pair, i) => ( + + + ))} + +
    + +
    + )} + + {fields.size == 0 && metadata.length && ( + + + {(() => { + let data = []; + for (let i = 0; i < metadata.length; i++) { + data.push( + + + + + ); + } + return data; + })()} + +
    + ) || null} + {info} {mutingInfo} {actionBtn}
    - - {metadata.length && ( - - - {(() => { - let data = []; - for (let i = 0; i < metadata.length; i++) { - data.push( - - - - - ); - } - return data; - })()} - -
    - ) || null} ); } diff --git a/app/javascript/flavours/glitch/features/emoji_picker/index.js b/app/javascript/flavours/glitch/features/emoji_picker/index.js index 4b1ef6c97..4cf833a3e 100644 --- a/app/javascript/flavours/glitch/features/emoji_picker/index.js +++ b/app/javascript/flavours/glitch/features/emoji_picker/index.js @@ -241,12 +241,12 @@ class EmojiPickerMenu extends React.PureComponent { static defaultProps = { style: {}, loading: true, - placement: 'bottom', frequentlyUsedEmojis: [], }; state = { modifierOpen: false, + placement: null, }; handleDocumentClick = e => { @@ -378,7 +378,7 @@ export default class EmojiPickerDropdown extends React.PureComponent { this.dropdown = c; } - onShowDropdown = () => { + onShowDropdown = ({ target }) => { this.setState({ active: true }); if (!EmojiPicker) { @@ -393,6 +393,9 @@ export default class EmojiPickerDropdown extends React.PureComponent { this.setState({ loading: false }); }); } + + const { top } = target.getBoundingClientRect(); + this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' }); } onHideDropdown = () => { @@ -404,7 +407,7 @@ export default class EmojiPickerDropdown extends React.PureComponent { if (this.state.active) { this.onHideDropdown(); } else { - this.onShowDropdown(); + this.onShowDropdown(e); } } } @@ -426,7 +429,7 @@ export default class EmojiPickerDropdown extends React.PureComponent { render () { const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis } = this.props; const title = intl.formatMessage(messages.emoji); - const { active, loading } = this.state; + const { active, loading, placement } = this.state; return (
    @@ -438,7 +441,7 @@ export default class EmojiPickerDropdown extends React.PureComponent { />
    - + )} @@ -48,7 +49,7 @@ export default class StatusCheckBox extends React.PureComponent { } else { media = ( - {Component => } + {Component => } ); } 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 b5fc33d03..3b7a5ff20 100644 --- a/app/javascript/flavours/glitch/features/ui/components/report_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/report_modal.js @@ -30,7 +30,7 @@ const makeMapStateToProps = () => { account: getAccount(state, accountId), comment: state.getIn(['reports', 'new', 'comment']), forward: state.getIn(['reports', 'new', 'forward']), - statusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}`, 'items'])).union(state.getIn(['reports', 'new', 'status_ids'])), + statusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}:with_replies`, 'items'])).union(state.getIn(['reports', 'new', 'status_ids'])), }; }; @@ -64,12 +64,12 @@ export default class ReportModal extends ImmutablePureComponent { } componentDidMount () { - this.props.dispatch(refreshAccountTimeline(this.props.account.get('id'))); + this.props.dispatch(refreshAccountTimeline(this.props.account.get('id'), true)); } componentWillReceiveProps (nextProps) { if (this.props.account !== nextProps.account && nextProps.account) { - this.props.dispatch(refreshAccountTimeline(nextProps.account.get('id'))); + this.props.dispatch(refreshAccountTimeline(nextProps.account.get('id'), true)); } } diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index 8c6d68dc4..3be6e19f7 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -92,6 +92,7 @@ export default class Video extends React.PureComponent { width: PropTypes.number, height: PropTypes.number, sensitive: PropTypes.bool, + revealed: PropTypes.bool, startTime: PropTypes.number, onOpenVideo: PropTypes.func, onCloseVideo: PropTypes.func, @@ -111,7 +112,7 @@ export default class Video extends React.PureComponent { fullscreen: false, hovered: false, muted: false, - revealed: !this.props.sensitive || displaySensitiveMedia, + revealed: this.props.revealed === undefined ? (!this.props.sensitive || displaySensitiveMedia) : this.props.revealed, }; setPlayerRef = c => { @@ -255,7 +256,7 @@ export default class Video extends React.PureComponent { } render () { - const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, letterbox, fullwidth, detailed } = this.props; + const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, letterbox, fullwidth, detailed, sensitive } = this.props; const { containerWidth, currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state; const progress = (currentTime / duration) * 100; const playerStyle = {}; @@ -270,6 +271,13 @@ export default class Video extends React.PureComponent { playerStyle.height = height; } + let warning; + if (sensitive) { + warning = ; + } else { + warning = ; + } + return (