1import React from 'react' 2import Text from '../../../common-adapters/text' 3import Button from '../../../common-adapters/button' 4import {Box2} from '../../../common-adapters/box' 5import {MenuItems} from '../../../common-adapters/floating-menu/menu-layout' 6import FloatingMenu from '../../../common-adapters/floating-menu' 7import * as Styles from '../../../styles' 8 9const Kb = {Box2, Button, FloatingMenu, Text} 10 11type PopupProps = { 12 attachTo?: () => React.Component<any> | null 13 onHidden: () => void 14 onResolve: () => void 15 text: string 16 visible: boolean 17} 18 19const items: MenuItems = [] 20 21const UnknownMentionPopup = (props: PopupProps) => { 22 const header = ( 23 <Kb.Box2 direction="vertical" gap="tiny" style={styles.popupContainer} gapStart={true}> 24 <Kb.Text type="BodySemibold">User or team?</Kb.Text> 25 <Kb.Text type="BodySmall"> 26 {props.text} could be either a user or team. You can find out with a quick request to Keybase. 27 </Kb.Text> 28 <Kb.Button label="Lookup" onClick={props.onResolve} /> 29 </Kb.Box2> 30 ) 31 return ( 32 <Kb.FloatingMenu 33 attachTo={props.attachTo} 34 closeOnSelect={true} 35 header={header} 36 items={items} 37 onHidden={props.onHidden} 38 visible={props.visible} 39 /> 40 ) 41} 42 43type Props = { 44 allowFontScaling?: boolean 45 channel: string 46 name: string 47 onResolve: () => void 48 style?: Styles.StylesCrossPlatform 49} 50 51type State = { 52 showPopup: boolean 53} 54 55class UnknownMention extends React.Component<Props, State> { 56 _mentionRef = React.createRef<Text>() 57 state = {showPopup: false} 58 _getAttachmentRef = () => { 59 return this._mentionRef.current 60 } 61 _onMouseOver = () => { 62 this.setState({showPopup: true}) 63 } 64 _onMouseLeave = () => { 65 this.setState({showPopup: false}) 66 } 67 render() { 68 let text = `@${this.props.name}` 69 if (this.props.channel.length > 0) { 70 text += `#${this.props.channel}` 71 } 72 const content = ( 73 <Kb.Text 74 ref={this._mentionRef} 75 type="BodySemibold" 76 className={Styles.classNames({'hover-underline': !Styles.isMobile})} 77 allowFontScaling={this.props.allowFontScaling} 78 style={Styles.collapseStyles([this.props.style, styles.text])} 79 onClick={this._onMouseOver} 80 > 81 <Kb.Text 82 type="BodySemibold" 83 allowFontScaling={this.props.allowFontScaling} 84 style={Styles.collapseStyles([this.props.style, styles.text])} 85 > 86 {text} 87 </Kb.Text> 88 </Kb.Text> 89 ) 90 const popups = ( 91 <UnknownMentionPopup 92 attachTo={this._getAttachmentRef} 93 onHidden={this._onMouseLeave} 94 onResolve={this.props.onResolve} 95 text={text} 96 visible={this.state.showPopup} 97 /> 98 ) 99 return Styles.isMobile ? ( 100 <> 101 {content} 102 {popups} 103 </> 104 ) : ( 105 <Kb.Box2 106 direction="horizontal" 107 style={styles.container} 108 onMouseOver={this._onMouseOver} 109 onMouseLeave={this._onMouseLeave} 110 > 111 {content} 112 {popups} 113 </Kb.Box2> 114 ) 115 } 116} 117 118const styles = Styles.styleSheetCreate( 119 () => 120 ({ 121 container: Styles.platformStyles({ 122 isElectron: { 123 display: 'inline-block', 124 }, 125 }), 126 popupContainer: Styles.platformStyles({ 127 common: { 128 padding: Styles.globalMargins.tiny, 129 textAlign: 'center', 130 }, 131 isElectron: { 132 width: 200, 133 }, 134 }), 135 text: Styles.platformStyles({ 136 common: { 137 backgroundColor: Styles.globalColors.greyLight, 138 borderRadius: 2, 139 letterSpacing: 0.3, 140 paddingLeft: 2, 141 paddingRight: 2, 142 }, 143 isElectron: { 144 display: 'inline-block', 145 }, 146 }), 147 warning: { 148 color: Styles.globalColors.redDark, 149 }, 150 } as const) 151) 152 153export default UnknownMention 154