From ad873c2b60c1b7fead2b20975a66c6dc6cec06cc Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 28 Aug 2016 01:55:42 +0100 Subject: [PATCH] handle matrix.to links correctly. add partial support for #/user URLs --- src/HtmlUtils.js | 28 ++++++++--- src/components/structures/MatrixChat.js | 64 ++++++++++++++----------- src/linkify-matrix.js | 44 +++++++++++++---- 3 files changed, 92 insertions(+), 44 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index d309ce1950..d4a999a5ac 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -85,12 +85,28 @@ var sanitizeHtmlParams = { transformTags: { // custom to matrix // add blank targets to all hyperlinks except vector URLs 'a': function(tagName, attribs) { - var m = attribs.href ? attribs.href.match(linkifyMatrix.VECTOR_URL_PATTERN) : null; - if (m) { - delete attribs.target; - } - else { - attribs.target = '_blank'; + if (attribs.href) { + attribs.target = '_blank'; // by default + + var m; + // FIXME: horrible duplication with linkify-matrix + m = attribs.href.match(linkifyMatrix.VECTOR_URL_PATTERN); + if (m) { + attribs.href = m[1]; + delete attribs.target; + } + + m = attribs.href.match(linkifyMatrix.MATRIXTO_URL_PATTERN); + if (m) { + var entity = m[1]; + if (entity[0] === '@') { + attribs.href = '#'; // TODO + } + else if (entity[0] === '#') { + attribs.href = '#/room/' + entity; + } + delete attribs.target; + } } attribs.rel = 'noopener'; // https://mathiasbynens.github.io/rel-noopener/ return { tagName: tagName, attribs : attribs }; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 46cad9685b..743f30aa15 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -176,12 +176,12 @@ module.exports = React.createClass({ // this can technically be done anywhere but doing this here keeps all // the routing url path logic together. - if (this.onAliasClick) { - linkifyMatrix.onAliasClick = this.onAliasClick; - } - if (this.onUserClick) { - linkifyMatrix.onUserClick = this.onUserClick; - } + // if (this.onAliasClick) { + // linkifyMatrix.onAliasClick = this.onAliasClick; + // } + // if (this.onUserClick) { + // linkifyMatrix.onUserClick = this.onUserClick; + // } window.addEventListener('resize', this.handleResize); this.handleResize(); @@ -739,6 +739,16 @@ module.exports = React.createClass({ } else { dis.dispatch(payload); } + } else if (screen.indexOf('user/') == 0) { + var userId = screen.substring(5); + var member = new Matrix.RoomMember(null, userId); + if (member) { + // FIXME: this doesn't work yet + dis.dispatch({ + action: 'view_user', + member: member, + }); + } } else { console.info("Ignoring showScreen for '%s'", screen); @@ -751,31 +761,29 @@ module.exports = React.createClass({ } }, - onAliasClick: function(event, alias) { - event.preventDefault(); - dis.dispatch({action: 'view_room', room_alias: alias}); - }, + // onAliasClick: function(event, alias) { + // event.preventDefault(); + // dis.dispatch({action: 'view_room', room_alias: alias}); + // }, - onUserClick: function(event, userId) { - event.preventDefault(); + // onUserClick: function(event, userId) { + // event.preventDefault(); - /* - var MemberInfo = sdk.getComponent('rooms.MemberInfo'); - var member = new Matrix.RoomMember(null, userId); - ContextualMenu.createMenu(MemberInfo, { - member: member, - right: window.innerWidth - event.pageX, - top: event.pageY - }); - */ + // // var MemberInfo = sdk.getComponent('rooms.MemberInfo'); + // // var member = new Matrix.RoomMember(null, userId); + // // ContextualMenu.createMenu(MemberInfo, { + // // member: member, + // // right: window.innerWidth - event.pageX, + // // top: event.pageY + // // }); - var member = new Matrix.RoomMember(null, userId); - if (!member) { return; } - dis.dispatch({ - action: 'view_user', - member: member, - }); - }, + // var member = new Matrix.RoomMember(null, userId); + // if (!member) { return; } + // dis.dispatch({ + // action: 'view_user', + // member: member, + // }); + // }, onLogoutClick: function(event) { dis.dispatch({ diff --git a/src/linkify-matrix.js b/src/linkify-matrix.js index 99b7ee5c33..eaddbffebc 100644 --- a/src/linkify-matrix.js +++ b/src/linkify-matrix.js @@ -95,20 +95,25 @@ function matrixLinkify(linkify) { S_AT_NAME_COLON_DOMAIN_DOT.on(TT.TLD, S_USERID); } -matrixLinkify.onUserClick = function(e, userId) { e.preventDefault(); }; -matrixLinkify.onAliasClick = function(e, roomAlias) { e.preventDefault(); }; +// stubs, overwritten in MatrixChat's componentDidMount +// matrixLinkify.onUserClick = function(e, userId) { e.preventDefault(); }; +// matrixLinkify.onAliasClick = function(e, roomAlias) { e.preventDefault(); }; var escapeRegExp = function(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }; -// we only recognise URLs which match our current URL as being the same app -// as if someone explicitly links to vector.im/develop and we're on vector.im/beta -// they may well be trying to get us to explicitly go to develop. -// FIXME: intercept matrix.to URLs as well. -matrixLinkify.VECTOR_URL_PATTERN = "^(https?:\/\/)?" + escapeRegExp(window.location.host + window.location.pathname); +// Recognise URLs from both our local vector and official vector as vector. +// anyone else really should be using matrix.to. +matrixLinkify.VECTOR_URL_PATTERN = "^(?:https?:\/\/)?(?:" + + escapeRegExp(window.location.host + window.location.pathname) + "|" + + "(?:www\\.)?vector\\.im/(?:beta|staging|develop)/" + + ")(#.*)"; + +matrixLinkify.MATRIXTO_URL_PATTERN = "^(?:https?:\/\/)?(?:www\\.)?matrix\\.to/#/((#|@).*)"; matrixLinkify.options = { +/* events: function (href, type) { switch (type) { case "userid": @@ -125,14 +130,31 @@ matrixLinkify.options = { }; } }, - +*/ formatHref: function (href, type) { switch (type) { case 'roomalias': return '#/room/' + href; case 'userid': - return '#'; + return '#/user/' + href; default: + var m; + // FIXME: horrible duplication with HtmlUtils' transform tags + m = href.match(matrixLinkify.VECTOR_URL_PATTERN); + if (m) { + return m[1]; + } + m = href.match(matrixLinkify.MATRIXTO_URL_PATTERN); + if (m) { + var entity = m[1]; + if (entity[0] === '@') { + return '#'; // TODO + } + else if (entity[0] === '#') { + return '#/room/' + entity; + } + } + return href; } }, @@ -143,7 +165,9 @@ matrixLinkify.options = { target: function(href, type) { if (type === 'url') { - if (href.match(matrixLinkify.VECTOR_URL_PATTERN)) { + if (href.match(matrixLinkify.VECTOR_URL_PATTERN) || + href.match(matrixLinkify.MATRIXTO_URL_PATTERN)) + { return null; } else {