diff --git a/CHANGELOG.md b/CHANGELOG.md index 43de8c20..9de8e25d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Release date: TBD - Suppressed verbose error which is related to certificates - Clear cache on desktop app update: The application cache will be purged whenever the desktop app version changes - Added CTRL+SHIFT+MINUS as a shortcut for zooming out + - Show URL when the mouse cursor is hovering over links #### Windows - Copying a links address and pasting it inside the app now works diff --git a/src/browser/components/HoveringURL.jsx b/src/browser/components/HoveringURL.jsx new file mode 100644 index 00000000..65bb3d67 --- /dev/null +++ b/src/browser/components/HoveringURL.jsx @@ -0,0 +1,18 @@ +const React = require('react'); + +class HoveringURL extends React.Component { + render() { + return ( +
+ {this.props.targetURL} +
+ ); + } +} + +HoveringURL.propTypes = { + style: React.PropTypes.object, + targetURL: React.PropTypes.string +}; + +module.exports = HoveringURL; diff --git a/src/browser/components/MainPage.jsx b/src/browser/components/MainPage.jsx index 059a69ad..cd58cad9 100644 --- a/src/browser/components/MainPage.jsx +++ b/src/browser/components/MainPage.jsx @@ -1,4 +1,5 @@ const React = require('react'); +const ReactCSSTransitionGroup = require('react-addons-css-transition-group'); const {Grid, Row} = require('react-bootstrap'); const {ipcRenderer, remote} = require('electron'); @@ -7,6 +8,29 @@ const url = require('url'); const LoginModal = require('./LoginModal.jsx'); const MattermostView = require('./MattermostView.jsx'); const TabBar = require('./TabBar.jsx'); +const HoveringURL = require('./HoveringURL.jsx'); + +// Todo: Need to consider better way to apply styles +const styles = { + hoveringURL: { + color: 'gray', + backgroundColor: 'whitesmoke', + maxWidth: '95%', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + position: 'absolute', + bottom: 0, + paddingLeft: 4, + paddingRight: 16, + paddingTop: 2, + paddingBottom: 2, + borderTopRightRadius: 4, + borderTop: 'solid thin lightgray', + borderRight: 'solid thin lightgray', + pointerEvents: 'none' + } +}; const MainPage = React.createClass({ propTypes: { @@ -22,7 +46,8 @@ const MainPage = React.createClass({ mentionCounts: new Array(this.props.teams.length), unreadAtActive: new Array(this.props.teams.length), mentionAtActiveCounts: new Array(this.props.teams.length), - loginQueue: [] + loginQueue: [], + targetURL: '' }; }, componentDidMount() { @@ -201,6 +226,17 @@ const MainPage = React.createClass({ loginQueue.shift(); this.setState({loginQueue}); }, + handleTargetURLChange(targetURL) { + clearTimeout(this.targetURLDisappearTimeout); + if (targetURL === '') { + // set delay to avoid momentary disappearance when hovering over multiple links + this.targetURLDisappearTimeout = setTimeout(() => { + this.setState({targetURL: ''}); + }, 500); + } else { + this.setState({targetURL}); + } + }, render() { var self = this; @@ -239,6 +275,7 @@ const MainPage = React.createClass({ src={team.url} name={team.name} disablewebsecurity={this.props.disablewebsecurity} + onTargetURLChange={self.handleTargetURLChange} onUnreadCountChange={handleUnreadCountChange} onNotificationClick={handleNotificationClick} ref={id} @@ -273,6 +310,19 @@ const MainPage = React.createClass({ { tabsRow } { viewsRow } + + { (this.state.targetURL === '') ? + null : + } + ); } diff --git a/src/browser/components/MattermostView.jsx b/src/browser/components/MattermostView.jsx index 7a7aec86..59243a6d 100644 --- a/src/browser/components/MattermostView.jsx +++ b/src/browser/components/MattermostView.jsx @@ -13,6 +13,7 @@ const MattermostView = React.createClass({ disablewebsecurity: React.PropTypes.bool, name: React.PropTypes.string, id: React.PropTypes.string, + onTargetURLChange: React.PropTypes.func, onUnreadCountChange: React.PropTypes.func, src: React.PropTypes.string, style: React.PropTypes.object @@ -108,6 +109,12 @@ const MattermostView = React.createClass({ }); }); + webview.addEventListener('update-target-url', (event) => { + if (self.props.onTargetURLChange) { + self.props.onTargetURLChange(event.url); + } + }); + webview.addEventListener('ipc-message', (event) => { switch (event.channel) { case 'onUnreadCountChange': diff --git a/src/browser/css/index.css b/src/browser/css/index.css new file mode 100644 index 00000000..b0c13b5b --- /dev/null +++ b/src/browser/css/index.css @@ -0,0 +1,18 @@ + +.hovering-enter { + opacity: 0.01; +} + +.hovering-enter.hovering-enter-active { + opacity: 1; + transition: opacity 300ms ease-in-out; +} + +.hovering-leave { + opacity: 1; +} + +.hovering-leave.hovering-leave-active { + opacity: 0.01; + transition: opacity 500ms ease-in-out; +} diff --git a/src/browser/index.html b/src/browser/index.html index 61900980..99cb3b8f 100644 --- a/src/browser/index.html +++ b/src/browser/index.html @@ -4,6 +4,7 @@ + diff --git a/src/package.json b/src/package.json index 33521b60..2e175f16 100644 --- a/src/package.json +++ b/src/package.json @@ -21,6 +21,7 @@ "electron-squirrel-startup": "^1.0.0", "os-locale": "^1.4.0", "react": "^15.3.0", + "react-addons-css-transition-group": "^15.3.0", "react-bootstrap": "~0.30.6", "react-dom": "^15.3.0", "yargs": "^3.32.0"