Change hashtags and mentions in bios to open in-app in web UI (#24643)
This commit is contained in:
		
							parent
							
								
									e9a79d46cd
								
							
						
					
					
						commit
						8099ba04be
					
				| @ -135,8 +135,7 @@ export const showSearch = () => ({ | ||||
|   type: SEARCH_SHOW, | ||||
| }); | ||||
| 
 | ||||
| export const openURL = routerHistory => (dispatch, getState) => { | ||||
|   const value = getState().getIn(['search', 'value']); | ||||
| export const openURL = (value, history, onFailure) => (dispatch, getState) => { | ||||
|   const signedIn = !!getState().getIn(['meta', 'me']); | ||||
| 
 | ||||
|   if (!signedIn) { | ||||
| @ -148,15 +147,21 @@ export const openURL = routerHistory => (dispatch, getState) => { | ||||
|   api(getState).get('/api/v2/search', { params: { q: value, resolve: true } }).then(response => { | ||||
|     if (response.data.accounts?.length > 0) { | ||||
|       dispatch(importFetchedAccounts(response.data.accounts)); | ||||
|       routerHistory.push(`/@${response.data.accounts[0].acct}`); | ||||
|       history.push(`/@${response.data.accounts[0].acct}`); | ||||
|     } else if (response.data.statuses?.length > 0) { | ||||
|       dispatch(importFetchedStatuses(response.data.statuses)); | ||||
|       routerHistory.push(`/@${response.data.statuses[0].account.acct}/${response.data.statuses[0].id}`); | ||||
|       history.push(`/@${response.data.statuses[0].account.acct}/${response.data.statuses[0].id}`); | ||||
|     } else if (onFailure) { | ||||
|       onFailure(); | ||||
|     } | ||||
| 
 | ||||
|     dispatch(fetchSearchSuccess(response.data, value)); | ||||
|   }).catch(err => { | ||||
|     dispatch(fetchSearchFail(err)); | ||||
| 
 | ||||
|     if (onFailure) { | ||||
|       onFailure(); | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -80,6 +80,7 @@ class Header extends ImmutablePureComponent { | ||||
| 
 | ||||
|   static contextTypes = { | ||||
|     identity: PropTypes.object, | ||||
|     router: PropTypes.object, | ||||
|   }; | ||||
| 
 | ||||
|   static propTypes = { | ||||
| @ -101,11 +102,16 @@ class Header extends ImmutablePureComponent { | ||||
|     onChangeLanguages: PropTypes.func.isRequired, | ||||
|     onInteractionModal: PropTypes.func.isRequired, | ||||
|     onOpenAvatar: PropTypes.func.isRequired, | ||||
|     onOpenURL: PropTypes.func.isRequired, | ||||
|     intl: PropTypes.object.isRequired, | ||||
|     domain: PropTypes.string.isRequired, | ||||
|     hidden: PropTypes.bool, | ||||
|   }; | ||||
| 
 | ||||
|   setRef = c => { | ||||
|     this.node = c; | ||||
|   }; | ||||
| 
 | ||||
|   openEditProfile = () => { | ||||
|     window.open('/settings/profile', '_blank'); | ||||
|   }; | ||||
| @ -162,6 +168,61 @@ class Header extends ImmutablePureComponent { | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   handleHashtagClick = e => { | ||||
|     const { router } = this.context; | ||||
|     const value = e.currentTarget.textContent.replace(/^#/, ''); | ||||
| 
 | ||||
|     if (router && e.button === 0 && !(e.ctrlKey || e.metaKey)) { | ||||
|       e.preventDefault(); | ||||
|       router.history.push(`/tags/${value}`); | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   handleMentionClick = e => { | ||||
|     const { router } = this.context; | ||||
|     const { onOpenURL } = this.props; | ||||
| 
 | ||||
|     if (router && e.button === 0 && !(e.ctrlKey || e.metaKey)) { | ||||
|       e.preventDefault(); | ||||
| 
 | ||||
|       const link = e.currentTarget; | ||||
| 
 | ||||
|       onOpenURL(link.href, router.history, () => { | ||||
|         window.location = link.href; | ||||
|       }); | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   _attachLinkEvents () { | ||||
|     const node = this.node; | ||||
| 
 | ||||
|     if (!node) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     const links = node.querySelectorAll('a'); | ||||
| 
 | ||||
|     let link; | ||||
| 
 | ||||
|     for (var i = 0; i < links.length; ++i) { | ||||
|       link = links[i]; | ||||
| 
 | ||||
|       if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) { | ||||
|         link.addEventListener('click', this.handleHashtagClick, false); | ||||
|       } else if (link.classList.contains('mention')) { | ||||
|         link.addEventListener('click', this.handleMentionClick, false); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   componentDidMount () { | ||||
|     this._attachLinkEvents(); | ||||
|   } | ||||
| 
 | ||||
|   componentDidUpdate () { | ||||
|     this._attachLinkEvents(); | ||||
|   } | ||||
| 
 | ||||
|   render () { | ||||
|     const { account, hidden, intl, domain } = this.props; | ||||
|     const { signedIn, permissions } = this.context.identity; | ||||
| @ -360,7 +421,7 @@ class Header extends ImmutablePureComponent { | ||||
| 
 | ||||
|           {!(suspended || hidden) && ( | ||||
|             <div className='account__header__extra'> | ||||
|               <div className='account__header__bio'> | ||||
|               <div className='account__header__bio' ref={this.setRef}> | ||||
|                 {(account.get('id') !== me && signedIn) && <AccountNoteContainer account={account} />} | ||||
| 
 | ||||
|                 {account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />} | ||||
|  | ||||
| @ -26,6 +26,7 @@ export default class Header extends ImmutablePureComponent { | ||||
|     onChangeLanguages: PropTypes.func.isRequired, | ||||
|     onInteractionModal: PropTypes.func.isRequired, | ||||
|     onOpenAvatar: PropTypes.func.isRequired, | ||||
|     onOpenURL: PropTypes.func.isRequired, | ||||
|     hideTabs: PropTypes.bool, | ||||
|     domain: PropTypes.string.isRequired, | ||||
|     hidden: PropTypes.bool, | ||||
| @ -137,6 +138,7 @@ export default class Header extends ImmutablePureComponent { | ||||
|           onChangeLanguages={this.handleChangeLanguages} | ||||
|           onInteractionModal={this.handleInteractionModal} | ||||
|           onOpenAvatar={this.handleOpenAvatar} | ||||
|           onOpenURL={this.props.onOpenURL} | ||||
|           domain={this.props.domain} | ||||
|           hidden={hidden} | ||||
|         /> | ||||
|  | ||||
| @ -10,6 +10,7 @@ import { | ||||
|   pinAccount, | ||||
|   unpinAccount, | ||||
| } from '../../../actions/accounts'; | ||||
| import { openURL } from 'mastodon/actions/search'; | ||||
| import { | ||||
|   mentionCompose, | ||||
|   directCompose, | ||||
| @ -159,6 +160,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ | ||||
|     })); | ||||
|   }, | ||||
| 
 | ||||
|   onOpenURL (url, routerHistory, onFailure) { | ||||
|     dispatch(openURL(url, routerHistory, onFailure)); | ||||
|   }, | ||||
| 
 | ||||
| }); | ||||
| 
 | ||||
| export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Header)); | ||||
|  | ||||
| @ -161,9 +161,9 @@ class Search extends React.PureComponent { | ||||
| 
 | ||||
|   handleURLClick = () => { | ||||
|     const { router } = this.context; | ||||
|     const { onOpenURL } = this.props; | ||||
|     const { value, onOpenURL } = this.props; | ||||
| 
 | ||||
|     onOpenURL(router.history); | ||||
|     onOpenURL(value, router.history); | ||||
|   }; | ||||
| 
 | ||||
|   handleStatusSearch = () => { | ||||
|  | ||||
| @ -34,8 +34,8 @@ const mapDispatchToProps = dispatch => ({ | ||||
|     dispatch(showSearch()); | ||||
|   }, | ||||
| 
 | ||||
|   onOpenURL (routerHistory) { | ||||
|     dispatch(openURL(routerHistory)); | ||||
|   onOpenURL (q, routerHistory) { | ||||
|     dispatch(openURL(q, routerHistory)); | ||||
|   }, | ||||
| 
 | ||||
|   onClickSearchResult (q, type) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user