Merge pull request #232 from glitch-soc/hotkeys-glitch
Implement status hotkeys + spoiler expanding
This commit is contained in:
		
						commit
						84840e8d8c
					
				| @ -9,6 +9,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; | |||||||
| import { MediaGallery, Video } from 'themes/glitch/util/async-components'; | import { MediaGallery, Video } from 'themes/glitch/util/async-components'; | ||||||
| import { HotKeys } from 'react-hotkeys'; | import { HotKeys } from 'react-hotkeys'; | ||||||
| import NotificationOverlayContainer from 'themes/glitch/features/notifications/containers/overlay_container'; | import NotificationOverlayContainer from 'themes/glitch/features/notifications/containers/overlay_container'; | ||||||
|  | import classNames from 'classnames'; | ||||||
| 
 | 
 | ||||||
| // We use the component (and not the container) since we do not want
 | // We use the component (and not the container) since we do not want
 | ||||||
| // to use the progress bar to show download progress
 | // to use the progress bar to show download progress
 | ||||||
| @ -21,6 +22,7 @@ export default class Status extends ImmutablePureComponent { | |||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|  |     containerId: PropTypes.string, | ||||||
|     id: PropTypes.string, |     id: PropTypes.string, | ||||||
|     status: ImmutablePropTypes.map, |     status: ImmutablePropTypes.map, | ||||||
|     account: ImmutablePropTypes.map, |     account: ImmutablePropTypes.map, | ||||||
| @ -188,7 +190,9 @@ export default class Status extends ImmutablePureComponent { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   handleExpandedToggle = () => { |   handleExpandedToggle = () => { | ||||||
|     this.setExpansion(this.state.isExpanded || !this.props.status.get('spoiler') ? null : true); |     if (this.props.status.get('spoiler_text')) { | ||||||
|  |       this.setExpansion(this.state.isExpanded ? null : true); | ||||||
|  |     } | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   handleOpenVideo = startTime => { |   handleOpenVideo = startTime => { | ||||||
| @ -222,11 +226,11 @@ export default class Status extends ImmutablePureComponent { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   handleHotkeyMoveUp = () => { |   handleHotkeyMoveUp = () => { | ||||||
|     this.props.onMoveUp(this.props.status.get('id')); |     this.props.onMoveUp(this.props.containerId || this.props.id); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   handleHotkeyMoveDown = () => { |   handleHotkeyMoveDown = () => { | ||||||
|     this.props.onMoveDown(this.props.status.get('id')); |     this.props.onMoveDown(this.props.containerId || this.props.id); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   handleRef = c => { |   handleRef = c => { | ||||||
| @ -371,31 +375,24 @@ export default class Status extends ImmutablePureComponent { | |||||||
|       openProfile: this.handleHotkeyOpenProfile, |       openProfile: this.handleHotkeyOpenProfile, | ||||||
|       moveUp: this.handleHotkeyMoveUp, |       moveUp: this.handleHotkeyMoveUp, | ||||||
|       moveDown: this.handleHotkeyMoveDown, |       moveDown: this.handleHotkeyMoveDown, | ||||||
|  |       toggleSpoiler: this.handleExpandedToggle, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     const computedClass = classNames('status', `status-${status.get('visibility')}`, { | ||||||
|  |       collapsed: isExpanded === false, | ||||||
|  |       'has-background': isExpanded === false && background, | ||||||
|  |       'marked-for-delete': this.state.markedForDelete, | ||||||
|  |       muted, | ||||||
|  |     }, 'focusable'); | ||||||
|  | 
 | ||||||
|     return ( |     return ( | ||||||
|       <HotKeys handlers={handlers}> |       <HotKeys handlers={handlers}> | ||||||
|         <div |         <div | ||||||
|           className={ |           className={computedClass} | ||||||
|             `status${ |           style={isExpanded === false && background ? { backgroundImage: `url(${background})` } : null} | ||||||
|               muted ? ' muted' : '' |  | ||||||
|             } status-${status.get('visibility')}${ |  | ||||||
|               isExpanded === false ? ' collapsed' : '' |  | ||||||
|             }${ |  | ||||||
|               isExpanded === false && background ? ' has-background' : '' |  | ||||||
|             }${ |  | ||||||
|               this.state.markedForDelete ? ' marked-for-delete' : '' |  | ||||||
|             }` |  | ||||||
|           } |  | ||||||
|           style={{ |  | ||||||
|             backgroundImage: ( |  | ||||||
|               isExpanded === false && background ? |  | ||||||
|               `url(${background})` : |  | ||||||
|               'none' |  | ||||||
|             ), |  | ||||||
|           }} |  | ||||||
|           {...selectorAttribs} |           {...selectorAttribs} | ||||||
|           ref={handleRef} |           ref={handleRef} | ||||||
|  |           tabIndex='0' | ||||||
|         > |         > | ||||||
|           {prepend && account ? ( |           {prepend && account ? ( | ||||||
|             <StatusPrepend |             <StatusPrepend | ||||||
|  | |||||||
| @ -45,6 +45,7 @@ const makeMapStateToProps = () => { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return { |     return { | ||||||
|  |       containerId : props.containerId || props.id,  //  Should match reblogStatus's id for reblogs
 | ||||||
|       status      : status, |       status      : status, | ||||||
|       account     : account || props.account, |       account     : account || props.account, | ||||||
|       settings    : state.get('local_settings'), |       settings    : state.get('local_settings'), | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ import NotificationOverlayContainer from '../containers/overlay_container'; | |||||||
| export default class NotificationFollow extends ImmutablePureComponent { | export default class NotificationFollow extends ImmutablePureComponent { | ||||||
| 
 | 
 | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|  |     hidden: PropTypes.bool, | ||||||
|     id: PropTypes.string.isRequired, |     id: PropTypes.string.isRequired, | ||||||
|     account: ImmutablePropTypes.map.isRequired, |     account: ImmutablePropTypes.map.isRequired, | ||||||
|     notification: ImmutablePropTypes.map.isRequired, |     notification: ImmutablePropTypes.map.isRequired, | ||||||
| @ -57,7 +58,7 @@ export default class NotificationFollow extends ImmutablePureComponent { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { account, notification } = this.props; |     const { account, notification, hidden } = this.props; | ||||||
| 
 | 
 | ||||||
|     //  Links to the display name.
 |     //  Links to the display name.
 | ||||||
|     const displayName = account.get('display_name_html') || account.get('username'); |     const displayName = account.get('display_name_html') || account.get('username'); | ||||||
| @ -87,7 +88,7 @@ export default class NotificationFollow extends ImmutablePureComponent { | |||||||
|             /> |             /> | ||||||
|           </div> |           </div> | ||||||
| 
 | 
 | ||||||
|           <AccountContainer id={account.get('id')} withNote={false} /> |           <AccountContainer hidden={hidden} id={account.get('id')} withNote={false} /> | ||||||
|           <NotificationOverlayContainer notification={notification} /> |           <NotificationOverlayContainer notification={notification} /> | ||||||
|         </div> |         </div> | ||||||
|       </HotKeys> |       </HotKeys> | ||||||
|  | |||||||
| @ -16,70 +16,75 @@ export default class Notification extends ImmutablePureComponent { | |||||||
|     onMoveUp: PropTypes.func.isRequired, |     onMoveUp: PropTypes.func.isRequired, | ||||||
|     onMoveDown: PropTypes.func.isRequired, |     onMoveDown: PropTypes.func.isRequired, | ||||||
|     onMention: PropTypes.func.isRequired, |     onMention: PropTypes.func.isRequired, | ||||||
|     settings: ImmutablePropTypes.map.isRequired, |  | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   renderFollow () { |  | ||||||
|     const { notification } = this.props; |  | ||||||
|     return ( |  | ||||||
|       <NotificationFollow |  | ||||||
|         id={notification.get('id')} |  | ||||||
|         account={notification.get('account')} |  | ||||||
|         notification={notification} |  | ||||||
|       /> |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   renderMention () { |  | ||||||
|     const { notification } = this.props; |  | ||||||
|     return ( |  | ||||||
|       <StatusContainer |  | ||||||
|         id={notification.get('status')} |  | ||||||
|         notification={notification} |  | ||||||
|         withDismiss |  | ||||||
|       /> |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   renderFavourite () { |  | ||||||
|     const { notification } = this.props; |  | ||||||
|     return ( |  | ||||||
|       <StatusContainer |  | ||||||
|         id={notification.get('status')} |  | ||||||
|         account={notification.get('account')} |  | ||||||
|         prepend='favourite' |  | ||||||
|         muted |  | ||||||
|         notification={notification} |  | ||||||
|         withDismiss |  | ||||||
|       /> |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   renderReblog () { |  | ||||||
|     const { notification } = this.props; |  | ||||||
|     return ( |  | ||||||
|       <StatusContainer |  | ||||||
|         id={notification.get('status')} |  | ||||||
|         account={notification.get('account')} |  | ||||||
|         prepend='reblog' |  | ||||||
|         muted |  | ||||||
|         notification={notification} |  | ||||||
|         withDismiss |  | ||||||
|       /> |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   render () { |   render () { | ||||||
|     const { notification } = this.props; |     const { | ||||||
|  |       hidden, | ||||||
|  |       notification, | ||||||
|  |       onMoveDown, | ||||||
|  |       onMoveUp, | ||||||
|  |       onMention, | ||||||
|  |     } = this.props; | ||||||
|  | 
 | ||||||
|     switch(notification.get('type')) { |     switch(notification.get('type')) { | ||||||
|     case 'follow': |     case 'follow': | ||||||
|       return this.renderFollow(); |       return ( | ||||||
|  |         <NotificationFollow | ||||||
|  |           hidden={hidden} | ||||||
|  |           id={notification.get('id')} | ||||||
|  |           account={notification.get('account')} | ||||||
|  |           notification={notification} | ||||||
|  |           onMoveDown={onMoveDown} | ||||||
|  |           onMoveUp={onMoveUp} | ||||||
|  |           onMention={onMention} | ||||||
|  |         /> | ||||||
|  |       ); | ||||||
|     case 'mention': |     case 'mention': | ||||||
|       return this.renderMention(); |       return ( | ||||||
|  |         <StatusContainer | ||||||
|  |           containerId={notification.get('id')} | ||||||
|  |           hidden={hidden} | ||||||
|  |           id={notification.get('status')} | ||||||
|  |           notification={notification} | ||||||
|  |           onMoveDown={onMoveDown} | ||||||
|  |           onMoveUp={onMoveUp} | ||||||
|  |           onMention={onMention} | ||||||
|  |           withDismiss | ||||||
|  |         /> | ||||||
|  |       ); | ||||||
|     case 'favourite': |     case 'favourite': | ||||||
|       return this.renderFavourite(); |       return ( | ||||||
|  |         <StatusContainer | ||||||
|  |           containerId={notification.get('id')} | ||||||
|  |           hidden={hidden} | ||||||
|  |           id={notification.get('status')} | ||||||
|  |           account={notification.get('account')} | ||||||
|  |           prepend='favourite' | ||||||
|  |           muted | ||||||
|  |           notification={notification} | ||||||
|  |           onMoveDown={onMoveDown} | ||||||
|  |           onMoveUp={onMoveUp} | ||||||
|  |           onMention={onMention} | ||||||
|  |           withDismiss | ||||||
|  |         /> | ||||||
|  |       ); | ||||||
|     case 'reblog': |     case 'reblog': | ||||||
|       return this.renderReblog(); |       return ( | ||||||
|  |         <StatusContainer | ||||||
|  |           containerId={notification.get('id')} | ||||||
|  |           hidden={hidden} | ||||||
|  |           id={notification.get('status')} | ||||||
|  |           account={notification.get('account')} | ||||||
|  |           prepend='reblog' | ||||||
|  |           muted | ||||||
|  |           notification={notification} | ||||||
|  |           onMoveDown={onMoveDown} | ||||||
|  |           onMoveUp={onMoveUp} | ||||||
|  |           onMention={onMention} | ||||||
|  |           withDismiss | ||||||
|  |         /> | ||||||
|  |       ); | ||||||
|     default: |     default: | ||||||
|       return null; |       return null; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -11,7 +11,6 @@ const makeMapStateToProps = () => { | |||||||
| 
 | 
 | ||||||
|   const mapStateToProps = (state, props) => ({ |   const mapStateToProps = (state, props) => ({ | ||||||
|     notification: getNotification(state, props.notification, props.accountId), |     notification: getNotification(state, props.notification, props.accountId), | ||||||
|     settings: state.get('local_settings'), |  | ||||||
|     notifCleaning: state.getIn(['notifications', 'cleaningMode']), |     notifCleaning: state.getIn(['notifications', 'cleaningMode']), | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -41,7 +41,7 @@ export default class DetailedStatus extends ImmutablePureComponent { | |||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const status = this.props.status.get('reblog') ? this.props.status.get('reblog') : this.props.status; |     const status = this.props.status.get('reblog') ? this.props.status.get('reblog') : this.props.status; | ||||||
|     const { settings } = this.props; |     const { expanded, setExpansion, settings } = this.props; | ||||||
| 
 | 
 | ||||||
|     let media           = ''; |     let media           = ''; | ||||||
|     let mediaIcon       = null; |     let mediaIcon       = null; | ||||||
| @ -109,6 +109,8 @@ export default class DetailedStatus extends ImmutablePureComponent { | |||||||
|           status={status} |           status={status} | ||||||
|           media={media} |           media={media} | ||||||
|           mediaIcon={mediaIcon} |           mediaIcon={mediaIcon} | ||||||
|  |           expanded={expanded} | ||||||
|  |           setExpansion={setExpansion} | ||||||
|         /> |         /> | ||||||
| 
 | 
 | ||||||
|         <div className='detailed-status__meta'> |         <div className='detailed-status__meta'> | ||||||
|  | |||||||
| @ -71,6 +71,7 @@ export default class Status extends ImmutablePureComponent { | |||||||
| 
 | 
 | ||||||
|   state = { |   state = { | ||||||
|     fullscreen: false, |     fullscreen: false, | ||||||
|  |     isExpanded: null, | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   componentWillMount () { |   componentWillMount () { | ||||||
| @ -88,6 +89,12 @@ export default class Status extends ImmutablePureComponent { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   handleExpandedToggle = () => { | ||||||
|  |     if (this.props.status.get('spoiler_text')) { | ||||||
|  |       this.setExpansion(this.state.isExpanded ? null : true); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   handleFavouriteClick = (status) => { |   handleFavouriteClick = (status) => { | ||||||
|     if (status.get('favourited')) { |     if (status.get('favourited')) { | ||||||
|       this.props.dispatch(unfavourite(status)); |       this.props.dispatch(unfavourite(status)); | ||||||
| @ -241,6 +248,10 @@ export default class Status extends ImmutablePureComponent { | |||||||
|     )); |     )); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   setExpansion = value => { | ||||||
|  |     this.setState({ isExpanded: value ? true : null }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|     this.node = c; |     this.node = c; | ||||||
|   } |   } | ||||||
| @ -272,8 +283,9 @@ export default class Status extends ImmutablePureComponent { | |||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     let ancestors, descendants; |     let ancestors, descendants; | ||||||
|  |     const { setExpansion } = this; | ||||||
|     const { status, settings, ancestorsIds, descendantsIds } = this.props; |     const { status, settings, ancestorsIds, descendantsIds } = this.props; | ||||||
|     const { fullscreen } = this.state; |     const { fullscreen, isExpanded } = this.state; | ||||||
| 
 | 
 | ||||||
|     if (status === null) { |     if (status === null) { | ||||||
|       return ( |       return ( | ||||||
| @ -300,6 +312,7 @@ export default class Status extends ImmutablePureComponent { | |||||||
|       boost: this.handleHotkeyBoost, |       boost: this.handleHotkeyBoost, | ||||||
|       mention: this.handleHotkeyMention, |       mention: this.handleHotkeyMention, | ||||||
|       openProfile: this.handleHotkeyOpenProfile, |       openProfile: this.handleHotkeyOpenProfile, | ||||||
|  |       toggleSpoiler: this.handleExpandedToggle, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
| @ -317,6 +330,8 @@ export default class Status extends ImmutablePureComponent { | |||||||
|                   settings={settings} |                   settings={settings} | ||||||
|                   onOpenVideo={this.handleOpenVideo} |                   onOpenVideo={this.handleOpenVideo} | ||||||
|                   onOpenMedia={this.handleOpenMedia} |                   onOpenMedia={this.handleOpenMedia} | ||||||
|  |                   expanded={isExpanded} | ||||||
|  |                   setExpansion={setExpansion} | ||||||
|                 /> |                 /> | ||||||
| 
 | 
 | ||||||
|                 <ActionBar |                 <ActionBar | ||||||
|  | |||||||
| @ -84,6 +84,7 @@ const keyMap = { | |||||||
|   goToProfile: 'g u', |   goToProfile: 'g u', | ||||||
|   goToBlocked: 'g b', |   goToBlocked: 'g b', | ||||||
|   goToMuted: 'g m', |   goToMuted: 'g m', | ||||||
|  |   toggleSpoiler: 'x', | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @connect(mapStateToProps) | @connect(mapStateToProps) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user