diff --git a/package.json b/package.json index 035ccbc1..caed363d 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "filesize": "^3.1.2", "flux": "~2.0.3", "gfm.css": "^1.1.1", - "highlight.js": "^8.9.1", "linkifyjs": "^2.0.0-beta.4", "matrix-js-sdk": "https://github.com/matrix-org/matrix-js-sdk.git#develop", "matrix-react-sdk": "https://github.com/matrix-org/matrix-react-sdk.git#develop", @@ -38,9 +37,7 @@ "react-dnd": "^2.0.2", "react-dnd-html5-backend": "^2.0.0", "react-dom": "^0.14.2", - "react-gemini-scrollbar": "^2.0.1", - "sanitize-html": "^1.0.0", - "velocity-animate": "^1.2.3" + "react-gemini-scrollbar": "^2.0.1" }, "devDependencies": { "babel": "^5.8.23", diff --git a/src/ContextualMenu.js b/src/ContextualMenu.js deleted file mode 100644 index a7b1849e..00000000 --- a/src/ContextualMenu.js +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - - -'use strict'; - -var React = require('react'); -var ReactDOM = require('react-dom'); - -// Shamelessly ripped off Modal.js. There's probably a better way -// of doing reusable widgets like dialog boxes & menus where we go and -// pass in a custom control as the actual body. - -module.exports = { - ContextualMenuContainerId: "mx_ContextualMenu_Container", - - getOrCreateContainer: function() { - var container = document.getElementById(this.ContextualMenuContainerId); - - if (!container) { - container = document.createElement("div"); - container.id = this.ContextualMenuContainerId; - document.body.appendChild(container); - } - - return container; - }, - - createMenu: function (Element, props) { - var self = this; - - var closeMenu = function() { - ReactDOM.unmountComponentAtNode(self.getOrCreateContainer()); - - if (props && props.onFinished) props.onFinished.apply(null, arguments); - }; - - var position = { - top: props.top - 20, - }; - - var chevron = null; - if (props.left) { - chevron = - position.left = props.left + 8; - } else { - chevron = - position.right = props.right + 8; - } - - var className = 'mx_ContextualMenu_wrapper'; - - // FIXME: If a menu uses getDefaultProps it clobbers the onFinished - // property set here so you can't close the menu from a button click! - var menu = ( -
-
- {chevron} - -
-
-
- ); - - ReactDOM.render(menu, this.getOrCreateContainer()); - - return {close: closeMenu}; - }, -}; diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js deleted file mode 100644 index 824f59ab..00000000 --- a/src/HtmlUtils.js +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var sanitizeHtml = require('sanitize-html'); -var highlight = require('highlight.js'); - -var sanitizeHtmlParams = { - allowedTags: [ - 'font', // custom to matrix. deliberately no h1/h2 to stop people shouting. - 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', - 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', - 'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre' - ], - allowedAttributes: { - // custom ones first: - font: [ 'color' ], // custom to matrix - a: [ 'href', 'name', 'target' ], // remote target: custom to matrix - // We don't currently allow img itself by default, but this - // would make sense if we did - img: [ 'src' ], - }, - // Lots of these won't come up by default because we don't allow them - selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ], - // URL schemes we permit - allowedSchemes: [ 'http', 'https', 'ftp', 'mailto' ], - allowedSchemesByTag: {}, - - transformTags: { // custom to matrix - // add blank targets to all hyperlinks - 'a': sanitizeHtml.simpleTransform('a', { target: '_blank'} ) - }, -}; - -module.exports = { - bodyToHtml: function(content, searchTerm) { - var originalBody = content.body; - var body; - - if (searchTerm) { - var lastOffset = 0; - var bodyList = []; - var k = 0; - var offset; - - // XXX: rather than searching for the search term in the body, - // we should be looking at the match delimiters returned by the FTS engine - if (content.format === "org.matrix.custom.html") { - - var safeBody = sanitizeHtml(content.formatted_body, sanitizeHtmlParams); - var safeSearchTerm = sanitizeHtml(searchTerm, sanitizeHtmlParams); - while ((offset = safeBody.indexOf(safeSearchTerm, lastOffset)) >= 0) { - // FIXME: we need to apply the search highlighting to only the text elements of HTML, which means - // hooking into the sanitizer parser rather than treating it as a string. Otherwise - // the act of highlighting a or whatever will break the HTML badly. - bodyList.push(); - bodyList.push(); - lastOffset = offset + safeSearchTerm.length; - } - bodyList.push(); - } - else { - while ((offset = originalBody.indexOf(searchTerm, lastOffset)) >= 0) { - bodyList.push({ originalBody.substring(lastOffset, offset) }); - bodyList.push({ searchTerm }); - lastOffset = offset + searchTerm.length; - } - bodyList.push({ originalBody.substring(lastOffset) }); - } - body = bodyList; - } - else { - if (content.format === "org.matrix.custom.html") { - var safeBody = sanitizeHtml(content.formatted_body, sanitizeHtmlParams); - body = ; - } - else { - body = originalBody; - } - } - - return body; - }, - - highlightDom: function(element) { - var blocks = element.getElementsByTagName("code"); - for (var i = 0; i < blocks.length; i++) { - highlight.highlightBlock(blocks[i]); - } - }, - -} - diff --git a/src/Velociraptor.js b/src/Velociraptor.js deleted file mode 100644 index d973a17f..00000000 --- a/src/Velociraptor.js +++ /dev/null @@ -1,113 +0,0 @@ -var React = require('react'); -var ReactDom = require('react-dom'); -var Velocity = require('velocity-animate'); - -/** - * The Velociraptor contains components and animates transitions with velocity. - * It will only pick up direct changes to properties ('left', currently), and so - * will not work for animating positional changes where the position is implicit - * from DOM order. This makes it a lot simpler and lighter: if you need fully - * automatic positional animation, look at react-shuffle or similar libraries. - */ -module.exports = React.createClass({ - displayName: 'Velociraptor', - - propTypes: { - children: React.PropTypes.array, - transition: React.PropTypes.object, - container: React.PropTypes.string - }, - - componentWillMount: function() { - this.children = {}; - this.nodes = {}; - var self = this; - React.Children.map(this.props.children, function(c) { - self.children[c.key] = c; - }); - }, - - componentWillReceiveProps: function(nextProps) { - var self = this; - var oldChildren = this.children; - this.children = {}; - React.Children.map(nextProps.children, function(c) { - if (oldChildren[c.key]) { - var old = oldChildren[c.key]; - var oldNode = ReactDom.findDOMNode(self.nodes[old.key]); - - if (oldNode.style.left != c.props.style.left) { - Velocity(oldNode, { left: c.props.style.left }, self.props.transition).then(function() { - // special case visibility because it's nonsensical to animate an invisible element - // so we always hidden->visible pre-transition and visible->hidden after - if (oldNode.style.visibility == 'visible' && c.props.style.visibility == 'hidden') { - oldNode.style.visibility = c.props.style.visibility; - } - }); - if (oldNode.style.visibility == 'hidden' && c.props.style.visibility == 'visible') { - oldNode.style.visibility = c.props.style.visibility; - } - //console.log("translation: "+oldNode.style.left+" -> "+c.props.style.left); - } - self.children[c.key] = old; - } else { - // new element. If it has a startStyle, use that as the style and go through - // the enter animations - var newProps = { - ref: self.collectNode.bind(self, c.key) - }; - if (c.props.startStyle && Object.keys(c.props.startStyle).length) { - var startStyle = c.props.startStyle; - if (Array.isArray(startStyle)) { - startStyle = startStyle[0]; - } - newProps._restingStyle = c.props.style; - newProps.style = startStyle; - //console.log("mounted@startstyle0: "+JSON.stringify(startStyle)); - // apply the enter animations once it's mounted - } - self.children[c.key] = React.cloneElement(c, newProps); - } - }); - }, - - collectNode: function(k, node) { - if ( - this.nodes[k] === undefined && - node.props.startStyle && - Object.keys(node.props.startStyle).length - ) { - var domNode = ReactDom.findDOMNode(node); - var startStyles = node.props.startStyle; - var transitionOpts = node.props.enterTransitionOpts; - if (!Array.isArray(startStyles)) { - startStyles = [ startStyles ]; - transitionOpts = [ transitionOpts ]; - } - // start from startStyle 1: 0 is the one we gave it - // to start with, so now we animate 1 etc. - for (var i = 1; i < startStyles.length; ++i) { - Velocity(domNode, startStyles[i], transitionOpts[i-1]); - //console.log("start: "+JSON.stringify(startStyles[i])); - } - // and then we animate to the resting state - Velocity(domNode, node.props._restingStyle, transitionOpts[i-1]); - //console.log("enter: "+JSON.stringify(node.props._restingStyle)); - } - this.nodes[k] = node; - }, - - render: function() { - var self = this; - var childList = Object.keys(this.children).map(function(k) { - return React.cloneElement(self.children[k], { - ref: self.collectNode.bind(self, self.children[k].key) - }); - }); - return ( - - {childList} - - ); - }, -}); diff --git a/src/VelocityBounce.js b/src/VelocityBounce.js deleted file mode 100644 index c85aa254..00000000 --- a/src/VelocityBounce.js +++ /dev/null @@ -1,15 +0,0 @@ -var Velocity = require('velocity-animate'); - -// courtesy of https://github.com/julianshapiro/velocity/issues/283 -// We only use easeOutBounce (easeInBounce is just sort of nonsensical) -function bounce( p ) { - var pow2, - bounce = 4; - - while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} - return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); -} - -Velocity.Easings.easeOutBounce = function(p) { - return 1 - bounce(1 - p); -} diff --git a/src/components/structures/login/PostRegistration.js b/src/components/structures/login/PostRegistration.js index 20a58f11..28fab4c1 100644 --- a/src/components/structures/login/PostRegistration.js +++ b/src/components/structures/login/PostRegistration.js @@ -57,8 +57,8 @@ module.exports = React.createClass({ }, render: function() { - var ChangeDisplayName = sdk.getComponent('molecules.ChangeDisplayName'); - var ChangeAvatar = sdk.getComponent('molecules.ChangeAvatar'); + var ChangeDisplayName = sdk.getComponent('settings.ChangeDisplayName'); + var ChangeAvatar = sdk.getComponent('settings.ChangeAvatar'); return (
diff --git a/src/skins/vector/views/molecules/RoomTile.js b/src/components/views/rooms/RoomDNDView.js similarity index 66% rename from src/skins/vector/views/molecules/RoomTile.js rename to src/components/views/rooms/RoomDNDView.js index ec7d48b4..2729e15b 100644 --- a/src/skins/vector/views/molecules/RoomTile.js +++ b/src/components/views/rooms/RoomDNDView.js @@ -21,11 +21,10 @@ var DragSource = require('react-dnd').DragSource; var DropTarget = require('react-dnd').DropTarget; var classNames = require('classnames'); -var RoomTileController = require('matrix-react-sdk/lib/controllers/molecules/RoomTile') - +var dis = require("matrix-react-sdk/lib/dispatcher"); var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); - -var sdk = require('matrix-react-sdk') +var sdk = require('matrix-react-sdk'); +var RoomTile = require('matrix-react-sdk/lib/components/views/rooms/RoomTile'); /** * Specifies the drag source contract. @@ -183,117 +182,6 @@ var roomTileTarget = { }, }; -var RoomTile = React.createClass({ - displayName: 'RoomTile', - mixins: [RoomTileController], - - propTypes: { - connectDragSource: React.PropTypes.func.isRequired, - connectDropTarget: React.PropTypes.func.isRequired, - isDragging: React.PropTypes.bool.isRequired, - room: React.PropTypes.object.isRequired, - collapsed: React.PropTypes.bool.isRequired, - selected: React.PropTypes.bool.isRequired, - unread: React.PropTypes.bool.isRequired, - highlight: React.PropTypes.bool.isRequired, - isInvite: React.PropTypes.bool.isRequired, - roomSubList: React.PropTypes.object.isRequired, - }, - - getInitialState: function() { - return( { hover : false }); - }, - - onMouseEnter: function() { - this.setState( { hover : true }); - }, - - onMouseLeave: function() { - this.setState( { hover : false }); - }, - - render: function() { - // if (this.props.clientOffset) { - // //console.log("room " + this.props.room.roomId + " has dropTarget clientOffset " + this.props.clientOffset.x + "," + this.props.clientOffset.y); - // } - -/* - if (this.props.room._dragging) { - var RoomDropTarget = sdk.getComponent("molecules.RoomDropTarget"); - return ; - } -*/ - - var myUserId = MatrixClientPeg.get().credentials.userId; - var me = this.props.room.currentState.members[myUserId]; - var classes = classNames({ - 'mx_RoomTile': true, - 'mx_RoomTile_selected': this.props.selected, - 'mx_RoomTile_unread': this.props.unread, - 'mx_RoomTile_highlight': this.props.highlight, - 'mx_RoomTile_invited': (me && me.membership == 'invite'), - }); - - var name; - if (this.props.isInvite) { - name = this.props.room.getMember(myUserId).events.member.getSender(); - } - else { - // XXX: We should never display raw room IDs, but sometimes the room name js sdk gives is undefined - name = this.props.room.name || this.props.room.roomId; - } - - name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon - var badge; - if (this.props.highlight) { - badge =
; - } - /* - if (this.props.highlight) { - badge =
!
; - } - else if (this.props.unread) { - badge =
1
; - } - var nameCell; - if (badge) { - nameCell =
{name}
{badge}
; - } - else { - nameCell =
{name}
; - } - */ - - var label; - if (!this.props.collapsed) { - var className = 'mx_RoomTile_name' + (this.props.isInvite ? ' mx_RoomTile_invite' : ''); - label =
{name}
; - } - else if (this.state.hover) { - var RoomTooltip = sdk.getComponent("molecules.RoomTooltip"); - label = ; - } - - var RoomAvatar = sdk.getComponent('avatars.RoomAvatar'); - - // These props are injected by React DnD, - // as defined by your `collect` function above: - var isDragging = this.props.isDragging; - var connectDragSource = this.props.connectDragSource; - var connectDropTarget = this.props.connectDropTarget; - - return connectDragSource(connectDropTarget( -
-
- - { badge } -
- { label } -
- )); - } -}); - // Export the wrapped version, inlining the 'collect' functions // to more closely resemble the ES7 module.exports = diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js index 7baab0e1..1fe7bd08 100644 --- a/src/controllers/organisms/RoomView.js +++ b/src/controllers/organisms/RoomView.js @@ -470,7 +470,7 @@ module.exports = { var ret = []; var count = 0; - var EventTile = sdk.getComponent('molecules.EventTile'); + var EventTile = sdk.getComponent('messages.Event'); if (this.state.searchResults) { // XXX: this dance is foul, due to the results API not returning sorted results diff --git a/src/skins/vector/skindex.js b/src/skins/vector/skindex.js index 94655c59..b4a8e119 100644 --- a/src/skins/vector/skindex.js +++ b/src/skins/vector/skindex.js @@ -27,53 +27,61 @@ var skin = {}; skin['elements.Spinner'] = require('../../components/views/elements/Spinner'); skin['elements.ImageView'] = require('../../components/views/elements/ImageView'); skin['messages.MessageTimestamp'] = require('../../components/views/messages/MessageTimestamp'); +skin['rooms.RoomTile'] = require('../../components/views/rooms/RoomDNDView'); // TODO: Fix this so matrix-react-sdk stuff is in react SDK skindex? skin['avatars.RoomAvatar'] = require('matrix-react-sdk/lib/components/views/avatars/RoomAvatar'); skin['avatars.MemberAvatar'] = require('matrix-react-sdk/lib/components/views/avatars/MemberAvatar'); + skin['settings.EnableNotificationsButton'] = require('matrix-react-sdk/lib/components/views/settings/EnableNotificationsButton'); +skin['settings.ChangeAvatar'] = require('matrix-react-sdk/lib/components/views/settings/ChangeAvatar'); +skin['settings.ChangeDisplayName'] = require('matrix-react-sdk/lib/components/views/settings/ChangeDisplayName'); +skin['settings.ChangePassword'] = require('matrix-react-sdk/lib/components/views/settings/ChangePassword'); + skin['elements.EditableText'] = require('matrix-react-sdk/lib/components/views/elements/EditableText'); -skin['voip.VideoFeed'] = require('matrix-react-sdk/lib/components/views/voip/VideoFeed'); +skin['elements.ProgressBar'] = require('matrix-react-sdk/lib/components/views/elements/ProgressBar'); +skin['elements.UserSelector'] = require('matrix-react-sdk/lib/components/views/elements/UserSelector'); + +skin['messages.MessageComposer'] = require('matrix-react-sdk/lib/components/views/messages/MessageComposer'); +skin['messages.TextualEvent'] = require('matrix-react-sdk/lib/components/views/messages/TextualEvent'); +skin['messages.MRoomMemberEvent'] = require('matrix-react-sdk/lib/components/views/messages/MRoomMemberEvent'); +skin['messages.Event'] = require('matrix-react-sdk/lib/components/views/messages/Event'); +skin['messages.Message'] = require('matrix-react-sdk/lib/components/views/messages/Message'); +skin['messages.MEmoteMessage'] = require('matrix-react-sdk/lib/components/views/messages/MEmoteMessage'); +skin['messages.MFileMessage'] = require('matrix-react-sdk/lib/components/views/messages/MFileMessage'); +skin['messages.MImageMessage'] = require('matrix-react-sdk/lib/components/views/messages/MImageMessage'); +skin['messages.MNoticeMessage'] = require('matrix-react-sdk/lib/components/views/messages/MNoticeMessage'); +skin['messages.MTextMessage'] = require('matrix-react-sdk/lib/components/views/messages/MTextMessage'); +skin['messages.MVideoMessage'] = require('matrix-react-sdk/lib/components/views/messages/MVideoMessage'); +skin['messages.UnknownMessage'] = require('matrix-react-sdk/lib/components/views/messages/UnknownMessage'); + +skin['rooms.MemberInfo'] = require('matrix-react-sdk/lib/components/views/rooms/MemberInfo'); +skin['rooms.RoomHeader'] = require('matrix-react-sdk/lib/components/views/rooms/RoomHeader'); +skin['rooms.RoomSettings'] = require('matrix-react-sdk/lib/components/views/rooms/RoomSettings'); +skin['rooms.MemberTile'] = require('matrix-react-sdk/lib/components/views/rooms/MemberTile'); + skin['create_room.CreateRoomButton'] = require('matrix-react-sdk/lib/components/views/create_room/CreateRoomButton'); skin['create_room.Presets'] = require('matrix-react-sdk/lib/components/views/create_room/Presets'); skin['create_room.RoomAlias'] = require('matrix-react-sdk/lib/components/views/create_room/RoomAlias'); + skin['voip.CallView'] = require('matrix-react-sdk/lib/components/views/voip/CallView'); skin['voip.IncomingCallBox'] = require('matrix-react-sdk/lib/components/views/voip/IncomingCallBox'); skin['voip.VideoView'] = require('matrix-react-sdk/lib/components/views/voip/VideoView'); +skin['voip.VideoFeed'] = require('matrix-react-sdk/lib/components/views/voip/VideoFeed'); + + // Old style stuff skin['molecules.BottomLeftMenu'] = require('./views/molecules/BottomLeftMenu'); skin['molecules.BottomLeftMenuTile'] = require('./views/molecules/BottomLeftMenuTile'); -skin['molecules.ChangeAvatar'] = require('./views/molecules/ChangeAvatar'); -skin['molecules.ChangeDisplayName'] = require('./views/molecules/ChangeDisplayName'); -skin['molecules.ChangePassword'] = require('./views/molecules/ChangePassword'); skin['molecules.DateSeparator'] = require('./views/molecules/DateSeparator'); -skin['molecules.EventAsTextTile'] = require('./views/molecules/EventAsTextTile'); -skin['molecules.EventTile'] = require('./views/molecules/EventTile'); -skin['molecules.MEmoteTile'] = require('./views/molecules/MEmoteTile'); -skin['molecules.MFileTile'] = require('./views/molecules/MFileTile'); -skin['molecules.MImageTile'] = require('./views/molecules/MImageTile'); -skin['molecules.MNoticeTile'] = require('./views/molecules/MNoticeTile'); -skin['molecules.MRoomMemberTile'] = require('./views/molecules/MRoomMemberTile'); -skin['molecules.MTextTile'] = require('./views/molecules/MTextTile'); -skin['molecules.MVideoTile'] = require('./views/molecules/MVideoTile'); skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar'); -skin['molecules.MemberInfo'] = require('./views/molecules/MemberInfo'); -skin['molecules.MemberTile'] = require('./views/molecules/MemberTile'); -skin['molecules.MessageComposer'] = require('./views/molecules/MessageComposer'); skin['molecules.MessageContextMenu'] = require('./views/molecules/MessageContextMenu'); -skin['molecules.MessageTile'] = require('./views/molecules/MessageTile'); -skin['molecules.ProgressBar'] = require('./views/molecules/ProgressBar'); skin['molecules.RoomCreate'] = require('./views/molecules/RoomCreate'); skin['molecules.RoomDropTarget'] = require('./views/molecules/RoomDropTarget'); -skin['molecules.RoomHeader'] = require('./views/molecules/RoomHeader'); -skin['molecules.RoomSettings'] = require('./views/molecules/RoomSettings'); -skin['molecules.RoomTile'] = require('./views/molecules/RoomTile'); skin['molecules.RoomTooltip'] = require('./views/molecules/RoomTooltip'); skin['molecules.SearchBar'] = require('./views/molecules/SearchBar'); skin['molecules.SenderProfile'] = require('./views/molecules/SenderProfile'); -skin['molecules.UnknownMessageTile'] = require('./views/molecules/UnknownMessageTile'); -skin['molecules.UserSelector'] = require('./views/molecules/UserSelector'); skin['organisms.CreateRoom'] = require('./views/organisms/CreateRoom'); skin['organisms.ErrorDialog'] = require('./views/organisms/ErrorDialog'); skin['organisms.LeftPanel'] = require('./views/organisms/LeftPanel'); diff --git a/src/skins/vector/views/molecules/ChangeAvatar.js b/src/skins/vector/views/molecules/ChangeAvatar.js deleted file mode 100644 index 735c7d28..00000000 --- a/src/skins/vector/views/molecules/ChangeAvatar.js +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var sdk = require('matrix-react-sdk') -var ChangeAvatarController = require('matrix-react-sdk/lib/controllers/molecules/ChangeAvatar') - -module.exports = React.createClass({ - displayName: 'ChangeAvatar', - mixins: [ChangeAvatarController], - - onFileSelected: function(ev) { - this.avatarSet = true; - this.setAvatarFromFile(ev.target.files[0]); - }, - - onError: function(error) { - this.setState({ - errorText: "Failed to upload profile picture!" - }); - }, - - render: function() { - var RoomAvatar = sdk.getComponent('avatars.RoomAvatar'); - var avatarImg; - // Having just set an avatar we just display that since it will take a little - // time to propagate through to the RoomAvatar. - if (this.props.room && !this.avatarSet) { - avatarImg = ; - } else { - var style = { - maxWidth: 320, - maxHeight: 240, - }; - avatarImg = ; - } - - switch (this.state.phase) { - case this.Phases.Display: - case this.Phases.Error: - return ( -
-
- {avatarImg} -
-
- Upload new: - - {this.state.errorText} -
-
- ); - case this.Phases.Uploading: - var Loader = sdk.getComponent("elements.Spinner"); - return ( - - ); - } - } -}); diff --git a/src/skins/vector/views/molecules/ChangeDisplayName.js b/src/skins/vector/views/molecules/ChangeDisplayName.js deleted file mode 100644 index 2798d6c1..00000000 --- a/src/skins/vector/views/molecules/ChangeDisplayName.js +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var sdk = require('matrix-react-sdk'); - -var ChangeDisplayNameController = require("matrix-react-sdk/lib/controllers/molecules/ChangeDisplayName"); - -module.exports = React.createClass({ - displayName: 'ChangeDisplayName', - mixins: [ChangeDisplayNameController], - - edit: function() { - this.refs.displayname_edit.edit() - }, - - onValueChanged: function(new_value, shouldSubmit) { - if (shouldSubmit) { - this.changeDisplayname(new_value); - } - }, - - render: function() { - if (this.state.busy) { - var Loader = sdk.getComponent("elements.Spinner"); - return ( - - ); - } else if (this.state.errorString) { - return ( -
{this.state.errorString}
- ); - } else { - var EditableText = sdk.getComponent('elements.EditableText'); - return ( - - ); - } - } -}); diff --git a/src/skins/vector/views/molecules/ChangePassword.js b/src/skins/vector/views/molecules/ChangePassword.js deleted file mode 100644 index 222442c1..00000000 --- a/src/skins/vector/views/molecules/ChangePassword.js +++ /dev/null @@ -1,84 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var ChangePasswordController = require('matrix-react-sdk/lib/controllers/molecules/ChangePassword') - -module.exports = React.createClass({ - displayName: 'ChangePassword', - mixins: [ChangePasswordController], - - onClickChange: function() { - var old_password = this.refs.old_input.value; - var new_password = this.refs.new_input.value; - var confirm_password = this.refs.confirm_input.value; - if (new_password != confirm_password) { - this.setState({ - state: this.Phases.Error, - errorString: "Passwords don't match" - }); - } else if (new_password == '' || old_password == '') { - this.setState({ - state: this.Phases.Error, - errorString: "Passwords can't be empty" - }); - } else { - this.changePassword(old_password, new_password); - } - }, - - render: function() { - switch (this.state.phase) { - case this.Phases.Edit: - case this.Phases.Error: - return ( -
-
-
{this.state.errorString}
-
-
-
-
-
- - -
-
- ); - case this.Phases.Uploading: - var Loader = sdk.getComponent("elements.Spinner"); - return ( -
- -
- ); - case this.Phases.Success: - return ( -
-
- Success! -
-
- -
-
- ) - } - } -}); diff --git a/src/skins/vector/views/molecules/EventAsTextTile.js b/src/skins/vector/views/molecules/EventAsTextTile.js deleted file mode 100644 index ec644a4e..00000000 --- a/src/skins/vector/views/molecules/EventAsTextTile.js +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var TextForEvent = require('matrix-react-sdk/lib/TextForEvent'); - -module.exports = React.createClass({ - displayName: 'EventAsTextTile', - - statics: { - needsSenderProfile: function() { - return false; - } - }, - - render: function() { - var text = TextForEvent.textForEvent(this.props.mxEvent); - if (text == null || text.length == 0) return null; - - return ( -
- {TextForEvent.textForEvent(this.props.mxEvent)} -
- ); - }, -}); - diff --git a/src/skins/vector/views/molecules/EventTile.js b/src/skins/vector/views/molecules/EventTile.js deleted file mode 100644 index db636788..00000000 --- a/src/skins/vector/views/molecules/EventTile.js +++ /dev/null @@ -1,274 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var ReactDom = require('react-dom'); -var classNames = require("classnames"); - -var sdk = require('matrix-react-sdk') -var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg') - -var EventTileController = require('matrix-react-sdk/lib/controllers/molecules/EventTile') -var ContextualMenu = require('../../../../ContextualMenu'); - -var TextForEvent = require('matrix-react-sdk/lib/TextForEvent'); - -var Velociraptor = require('../../../../Velociraptor'); -require('../../../../VelocityBounce'); - -var bounce = false; -try { - if (global.localStorage) { - bounce = global.localStorage.getItem('avatar_bounce') == 'true'; - } -} catch (e) { -} - -var eventTileTypes = { - 'm.room.message': 'molecules.MessageTile', - 'm.room.member' : 'molecules.EventAsTextTile', - 'm.call.invite' : 'molecules.EventAsTextTile', - 'm.call.answer' : 'molecules.EventAsTextTile', - 'm.call.hangup' : 'molecules.EventAsTextTile', - 'm.room.name' : 'molecules.EventAsTextTile', - 'm.room.topic' : 'molecules.EventAsTextTile', -}; - -var MAX_READ_AVATARS = 5; - -module.exports = React.createClass({ - displayName: 'EventTile', - mixins: [EventTileController], - - statics: { - haveTileForEvent: function(e) { - if (eventTileTypes[e.getType()] == undefined) return false; - if (eventTileTypes[e.getType()] == 'molecules.EventAsTextTile') { - return TextForEvent.textForEvent(e) !== ''; - } else { - return true; - } - } - }, - - getInitialState: function() { - return {menu: false, allReadAvatars: false}; - }, - - onEditClicked: function(e) { - var MessageContextMenu = sdk.getComponent('molecules.MessageContextMenu'); - var buttonRect = e.target.getBoundingClientRect() - var x = buttonRect.right; - var y = buttonRect.top + (e.target.height / 2); - var self = this; - ContextualMenu.createMenu(MessageContextMenu, { - mxEvent: this.props.mxEvent, - left: x, - top: y, - onFinished: function() { - self.setState({menu: false}); - } - }); - this.setState({menu: true}); - }, - - toggleAllReadAvatars: function() { - this.setState({ - allReadAvatars: !this.state.allReadAvatars - }); - }, - - getReadAvatars: function() { - var avatars = []; - - var room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); - - if (!room) return []; - - var myUserId = MatrixClientPeg.get().credentials.userId; - - // get list of read receipts, sorted most recent first - var receipts = room.getReceiptsForEvent(this.props.mxEvent).filter(function(r) { - return r.type === "m.read" && r.userId != myUserId; - }).sort(function(r1, r2) { - return r2.data.ts - r1.data.ts; - }); - - var MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); - - var left = 0; - - var reorderTransitionOpts = { - duration: 100, - easing: 'easeOut' - }; - - for (var i = 0; i < receipts.length; ++i) { - var member = room.getMember(receipts[i].userId); - - // Using react refs here would mean both getting Velociraptor to expose - // them and making them scoped to the whole RoomView. Not impossible, but - // getElementById seems simpler at least for a first cut. - var oldAvatarDomNode = document.getElementById('mx_readAvatar'+member.userId); - var startStyles = []; - var enterTransitionOpts = []; - var oldNodeTop = -15; // For avatars that weren't on screen, act as if they were just off the top - if (oldAvatarDomNode) { - oldNodeTop = oldAvatarDomNode.getBoundingClientRect().top; - } - - if (this.readAvatarNode) { - var topOffset = oldNodeTop - this.readAvatarNode.getBoundingClientRect().top; - - if (oldAvatarDomNode && oldAvatarDomNode.style.left !== '0px') { - var leftOffset = oldAvatarDomNode.style.left; - // start at the old height and in the old h pos - startStyles.push({ top: topOffset, left: leftOffset }); - enterTransitionOpts.push(reorderTransitionOpts); - } - - // then shift to the rightmost column, - // and then it will drop down to its resting position - startStyles.push({ top: topOffset, left: '0px' }); - enterTransitionOpts.push({ - duration: bounce ? Math.min(Math.log(Math.abs(topOffset)) * 200, 3000) : 300, - easing: bounce ? 'easeOutBounce' : 'easeOutCubic', - }); - } - - var style = { - left: left+'px', - top: '0px', - visibility: ((i < MAX_READ_AVATARS) || this.state.allReadAvatars) ? 'visible' : 'hidden' - }; - - //console.log("i = " + i + ", MAX_READ_AVATARS = " + MAX_READ_AVATARS + ", allReadAvatars = " + this.state.allReadAvatars + " visibility = " + style.visibility); - - // add to the start so the most recent is on the end (ie. ends up rightmost) - avatars.unshift( - - ); - // TODO: we keep the extra read avatars in the dom to make animation simpler - // we could optimise this to reduce the dom size. - if (i < MAX_READ_AVATARS - 1 || this.state.allReadAvatars) { // XXX: where does this -1 come from? is it to make the max'th avatar animate properly? - left -= 15; - } - } - var editButton; - if (!this.state.allReadAvatars) { - var remainder = receipts.length - MAX_READ_AVATARS; - var remText; - if (i >= MAX_READ_AVATARS - 1) left -= 15; - if (remainder > 0) { - remText = { remainder }+ - ; - left -= 15; - } - editButton = ( - - ); - } - - return - { editButton } - { remText } - - { avatars } - - ; - }, - - collectReadAvatarNode: function(node) { - this.readAvatarNode = ReactDom.findDOMNode(node); - }, - - render: function() { - var MessageTimestamp = sdk.getComponent('messages.MessageTimestamp'); - var SenderProfile = sdk.getComponent('molecules.SenderProfile'); - var MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); - - var content = this.props.mxEvent.getContent(); - var msgtype = content.msgtype; - - var EventTileType = sdk.getComponent(eventTileTypes[this.props.mxEvent.getType()]); - // This shouldn't happen: the caller should check we support this type - // before trying to instantiate us - if (!EventTileType) { - throw new Error("Event type not supported"); - } - - var classes = classNames({ - mx_EventTile: true, - mx_EventTile_sending: ['sending', 'queued'].indexOf( - this.props.mxEvent.status - ) !== -1, - mx_EventTile_notSent: this.props.mxEvent.status == 'not_sent', - mx_EventTile_highlight: this.shouldHighlight(), - mx_EventTile_continuation: this.props.continuation, - mx_EventTile_last: this.props.last, - mx_EventTile_contextual: this.props.contextual, - menu: this.state.menu, - }); - var timestamp = - - var aux = null; - if (msgtype === 'm.image') aux = "sent an image"; - else if (msgtype === 'm.video') aux = "sent a video"; - else if (msgtype === 'm.file') aux = "uploaded a file"; - - var readAvatars = this.getReadAvatars(); - - var avatar, sender; - if (!this.props.continuation) { - if (this.props.mxEvent.sender) { - avatar = ( -
- -
- ); - } - if (EventTileType.needsSenderProfile()) { - sender = ; - } - } - return ( -
-
- { timestamp } - { readAvatars } -
- { avatar } - { sender } -
- -
-
- ); - }, -}); diff --git a/src/skins/vector/views/molecules/MEmoteTile.js b/src/skins/vector/views/molecules/MEmoteTile.js deleted file mode 100644 index de2d9365..00000000 --- a/src/skins/vector/views/molecules/MEmoteTile.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var MEmoteTileController = require('matrix-react-sdk/lib/controllers/molecules/MEmoteTile') - -module.exports = React.createClass({ - displayName: 'MEmoteTile', - mixins: [MEmoteTileController], - - render: function() { - var mxEvent = this.props.mxEvent; - var content = mxEvent.getContent(); - var name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); - return ( - - * {name} {content.body} - - ); - }, -}); - diff --git a/src/skins/vector/views/molecules/MFileTile.js b/src/skins/vector/views/molecules/MFileTile.js deleted file mode 100644 index 9180bd6b..00000000 --- a/src/skins/vector/views/molecules/MFileTile.js +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var MFileTileController = require('matrix-react-sdk/lib/controllers/molecules/MFileTile') - -var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); - -module.exports = React.createClass({ - displayName: 'MFileTile', - mixins: [MFileTileController], - - render: function() { - var content = this.props.mxEvent.getContent(); - var cli = MatrixClientPeg.get(); - - var httpUrl = cli.mxcUrlToHttp(content.url); - var text = this.presentableTextForFile(content); - - if (httpUrl) { - return ( - - - - ); - } else { - var extra = text ? ': '+text : ''; - return - Invalid file{extra} - - } - }, -}); diff --git a/src/skins/vector/views/molecules/MImageTile.js b/src/skins/vector/views/molecules/MImageTile.js deleted file mode 100644 index 3aff8e64..00000000 --- a/src/skins/vector/views/molecules/MImageTile.js +++ /dev/null @@ -1,136 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var filesize = require('filesize'); - -var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); -var Modal = require('matrix-react-sdk/lib/Modal'); -var sdk = require('matrix-react-sdk') - -module.exports = React.createClass({ - displayName: 'MImageTile', - - thumbHeight: function(fullWidth, fullHeight, thumbWidth, thumbHeight) { - if (!fullWidth || !fullHeight) { - // Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even - // log this because it's spammy - return undefined; - } - if (fullWidth < thumbWidth && fullHeight < thumbHeight) { - // no scaling needs to be applied - return fullHeight; - } - var widthMulti = thumbWidth / fullWidth; - var heightMulti = thumbHeight / fullHeight; - if (widthMulti < heightMulti) { - // width is the dominant dimension so scaling will be fixed on that - return Math.floor(widthMulti * fullHeight); - } - else { - // height is the dominant dimension so scaling will be fixed on that - return Math.floor(heightMulti * fullHeight); - } - }, - - onClick: function(ev) { - if (ev.button == 0 && !ev.metaKey) { - ev.preventDefault(); - var content = this.props.mxEvent.getContent(); - var httpUrl = MatrixClientPeg.get().mxcUrlToHttp(content.url); - var ImageView = sdk.getComponent("elements.ImageView"); - Modal.createDialog(ImageView, { - src: httpUrl, - width: content.info.w, - height: content.info.h, - mxEvent: this.props.mxEvent, - }, "mx_Dialog_lightbox"); - } - }, - - _isGif: function() { - var content = this.props.mxEvent.getContent(); - return (content && content.info && content.info.mimetype === "image/gif"); - }, - - onImageEnter: function(e) { - if (!this._isGif()) { - return; - } - var imgElement = e.target; - imgElement.src = MatrixClientPeg.get().mxcUrlToHttp( - this.props.mxEvent.getContent().url - ); - }, - - onImageLeave: function(e) { - if (!this._isGif()) { - return; - } - var imgElement = e.target; - imgElement.src = this._getThumbUrl(); - }, - - _getThumbUrl: function() { - var content = this.props.mxEvent.getContent(); - return MatrixClientPeg.get().mxcUrlToHttp(content.url, 480, 360); - }, - - render: function() { - var content = this.props.mxEvent.getContent(); - var cli = MatrixClientPeg.get(); - - var thumbHeight = null; - if (content.info) thumbHeight = this.thumbHeight(content.info.w, content.info.h, 480, 360); - - var imgStyle = {}; - if (thumbHeight) imgStyle['height'] = thumbHeight; - - var thumbUrl = this._getThumbUrl(); - if (thumbUrl) { - return ( - - - {content.body} - - - - ); - } else if (content.body) { - return ( - - Image '{content.body}' cannot be displayed. - - ); - } else { - return ( - - This image cannot be displayed. - - ); - } - }, -}); diff --git a/src/skins/vector/views/molecules/MNoticeTile.js b/src/skins/vector/views/molecules/MNoticeTile.js deleted file mode 100644 index c905d3be..00000000 --- a/src/skins/vector/views/molecules/MNoticeTile.js +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var HtmlUtils = require('../../../../HtmlUtils'); - -var MNoticeTileController = require('matrix-react-sdk/lib/controllers/molecules/MNoticeTile') - -module.exports = React.createClass({ - displayName: 'MNoticeTile', - mixins: [MNoticeTileController], - - componentDidMount: function() { - if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") - HtmlUtils.highlightDom(this.getDOMNode()); - }, - - componentDidUpdate: function() { - if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") - HtmlUtils.highlightDom(this.getDOMNode()); - }, - - shouldComponentUpdate: function(nextProps) { - // exploit that events are immutable :) - return (nextProps.mxEvent.getId() !== this.props.mxEvent.getId() || - nextProps.searchTerm !== this.props.searchTerm); - }, - - // XXX: fix horrible duplication with MTextTile - render: function() { - var content = this.props.mxEvent.getContent(); - var body = HtmlUtils.bodyToHtml(content, this.props.searchTerm); - - return ( - - { body } - - ); - }, -}); - diff --git a/src/skins/vector/views/molecules/MRoomMemberTile.js b/src/skins/vector/views/molecules/MRoomMemberTile.js deleted file mode 100644 index 025fb6f0..00000000 --- a/src/skins/vector/views/molecules/MRoomMemberTile.js +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var sdk = require('matrix-react-sdk') -var TextForEvent = require('matrix-react-sdk/lib/TextForEvent'); - -module.exports = React.createClass({ - displayName: 'MRoomMemberTile', - - getMemberEventText: function() { - return TextForEvent.textForEvent(this.props.mxEvent); - }, - - render: function() { - // XXX: for now, just cheekily borrow the css from message tile... - var timestamp = this.props.last ? : null; - var text = this.getMemberEventText(); - if (!text) return
; - var MessageTimestamp = sdk.getComponent('messages.MessageTimestamp'); - var MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); - return ( -
-
- -
- { timestamp } - - - { text } - -
- ); - }, -}); - diff --git a/src/skins/vector/views/molecules/MTextTile.js b/src/skins/vector/views/molecules/MTextTile.js deleted file mode 100644 index 8352ae5c..00000000 --- a/src/skins/vector/views/molecules/MTextTile.js +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var HtmlUtils = require('../../../../HtmlUtils'); - -var MTextTileController = require('matrix-react-sdk/lib/controllers/molecules/MTextTile') - -module.exports = React.createClass({ - displayName: 'MTextTile', - mixins: [MTextTileController], - - componentDidMount: function() { - if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") - HtmlUtils.highlightDom(this.getDOMNode()); - }, - - componentDidUpdate: function() { - if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") - HtmlUtils.highlightDom(this.getDOMNode()); - }, - - shouldComponentUpdate: function(nextProps) { - // exploit that events are immutable :) - return (nextProps.mxEvent.getId() !== this.props.mxEvent.getId() || - nextProps.searchTerm !== this.props.searchTerm); - }, - - render: function() { - var content = this.props.mxEvent.getContent(); - var body = HtmlUtils.bodyToHtml(content, this.props.searchTerm); - - return ( - - { body } - - ); - }, -}); - diff --git a/src/skins/vector/views/molecules/MVideoTile.js b/src/skins/vector/views/molecules/MVideoTile.js deleted file mode 100644 index ec7ac6f8..00000000 --- a/src/skins/vector/views/molecules/MVideoTile.js +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var filesize = require('filesize'); - -var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); -var Modal = require('matrix-react-sdk/lib/Modal'); -var sdk = require('matrix-react-sdk') - -module.exports = React.createClass({ - displayName: 'MVideoTile', - - thumbScale: function(fullWidth, fullHeight, thumbWidth, thumbHeight) { - if (!fullWidth || !fullHeight) { - // Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even - // log this because it's spammy - return undefined; - } - if (fullWidth < thumbWidth && fullHeight < thumbHeight) { - // no scaling needs to be applied - return fullHeight; - } - var widthMulti = thumbWidth / fullWidth; - var heightMulti = thumbHeight / fullHeight; - if (widthMulti < heightMulti) { - // width is the dominant dimension so scaling will be fixed on that - return widthMulti; - } - else { - // height is the dominant dimension so scaling will be fixed on that - return heightMulti; - } - }, - - render: function() { - var content = this.props.mxEvent.getContent(); - var cli = MatrixClientPeg.get(); - - var height = null; - var width = null; - var poster = null; - var preload = "metadata"; - if (content.info) { - var scale = this.thumbScale(content.info.w, content.info.h, 480, 360); - if (scale) { - width = Math.floor(content.info.w * scale); - height = Math.floor(content.info.h * scale); - } - - if (content.info.thumbnail_url) { - poster = cli.mxcUrlToHttp(content.info.thumbnail_url); - preload = "none"; - } - } - - - - return ( - - - - ); - }, -}); diff --git a/src/skins/vector/views/molecules/MemberInfo.js b/src/skins/vector/views/molecules/MemberInfo.js deleted file mode 100644 index 5a35410c..00000000 --- a/src/skins/vector/views/molecules/MemberInfo.js +++ /dev/null @@ -1,101 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); -var sdk = require('matrix-react-sdk') -var dis = require('matrix-react-sdk/lib/dispatcher'); -var MemberInfoController = require('matrix-react-sdk/lib/controllers/molecules/MemberInfo') - -// FIXME: this should probably be an organism, to match with MemberList, not a molecule - -module.exports = React.createClass({ - displayName: 'MemberInfo', - mixins: [MemberInfoController], - - onCancel: function(e) { - dis.dispatch({ - action: "view_user", - member: null - }); - }, - - render: function() { - var interactButton, kickButton, banButton, muteButton, giveModButton, spinner; - if (this.props.member.userId === MatrixClientPeg.get().credentials.userId) { - interactButton =
Leave room
; - } - else { - interactButton =
Start chat
; - } - - if (this.state.creatingRoom) { - var Loader = sdk.getComponent("elements.Spinner"); - spinner = ; - } - - if (this.state.can.kick) { - kickButton =
- Kick -
; - } - if (this.state.can.ban) { - banButton =
- Ban -
; - } - if (this.state.can.mute) { - var muteLabel = this.state.muted ? "Unmute" : "Mute"; - muteButton =
- {muteLabel} -
; - } - if (this.state.can.modifyLevel) { - var giveOpLabel = this.state.isTargetMod ? "Revoke Mod" : "Make Mod"; - giveModButton =
- {giveOpLabel} -
- } - - var MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); - return ( -
- -
- -
-

{ this.props.member.name }

-
- { this.props.member.userId } -
-
- power: { this.props.member.powerLevelNorm }% -
-
- {interactButton} - {muteButton} - {kickButton} - {banButton} - {giveModButton} - {spinner} -
-
- ); - } -}); diff --git a/src/skins/vector/views/molecules/MemberTile.js b/src/skins/vector/views/molecules/MemberTile.js deleted file mode 100644 index d0a9f479..00000000 --- a/src/skins/vector/views/molecules/MemberTile.js +++ /dev/null @@ -1,180 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); -var sdk = require('matrix-react-sdk') -var dis = require('matrix-react-sdk/lib/dispatcher'); -var MemberTileController = require('matrix-react-sdk/lib/controllers/molecules/MemberTile') - -// The Lato WOFF doesn't include sensible combining diacritics, so Chrome chokes on rendering them. -// Revert to Arial when this happens, which on OSX works at least. -var zalgo = /[\u0300-\u036f\u1ab0-\u1aff\u1dc0-\u1dff\u20d0-\u20ff\ufe20-\ufe2f]/; - -module.exports = React.createClass({ - displayName: 'MemberTile', - mixins: [MemberTileController], - - shouldComponentUpdate: function(nextProps, nextState) { - if (this.state.hover !== nextState.hover) return true; - if ( - this.member_last_modified_time === undefined || - this.member_last_modified_time < nextProps.member.getLastModifiedTime() - ) { - return true - } - if ( - nextProps.member.user && - (this.user_last_modified_time === undefined || - this.user_last_modified_time < nextProps.member.user.getLastModifiedTime()) - ) { - return true - } - return false; - }, - - mouseEnter: function(e) { - this.setState({ 'hover': true }); - }, - - mouseLeave: function(e) { - this.setState({ 'hover': false }); - }, - - onClick: function(e) { - dis.dispatch({ - action: 'view_user', - member: this.props.member, - }); - }, - - getDuration: function(time) { - if (!time) return; - var t = parseInt(time / 1000); - var s = t % 60; - var m = parseInt(t / 60) % 60; - var h = parseInt(t / (60 * 60)) % 24; - var d = parseInt(t / (60 * 60 * 24)); - if (t < 60) { - if (t < 0) { - return "0s"; - } - return s + "s"; - } - if (t < 60 * 60) { - return m + "m"; - } - if (t < 24 * 60 * 60) { - return h + "h"; - } - return d + "d "; - }, - - getPrettyPresence: function(user) { - if (!user) return "Unknown"; - var presence = user.presence; - if (presence === "online") return "Online"; - if (presence === "unavailable") return "Idle"; // XXX: is this actually right? - if (presence === "offline") return "Offline"; - return "Unknown"; - }, - - getPowerLabel: function() { - var label = this.props.member.userId; - if (this.state.isTargetMod) { - label += " - Mod (" + this.props.member.powerLevelNorm + "%)"; - } - return label; - }, - - render: function() { - this.member_last_modified_time = this.props.member.getLastModifiedTime(); - if (this.props.member.user) { - this.user_last_modified_time = this.props.member.user.getLastModifiedTime(); - } - - var isMyUser = MatrixClientPeg.get().credentials.userId == this.props.member.userId; - - var power; - // if (this.props.member && this.props.member.powerLevelNorm > 0) { - // var img = "img/p/p" + Math.floor(20 * this.props.member.powerLevelNorm / 100) + ".png"; - // power = ; - // } - var presenceClass = "mx_MemberTile_offline"; - var mainClassName = "mx_MemberTile "; - if (this.props.member.user) { - if (this.props.member.user.presence === "online") { - presenceClass = "mx_MemberTile_online"; - } - else if (this.props.member.user.presence === "unavailable") { - presenceClass = "mx_MemberTile_unavailable"; - } - } - mainClassName += presenceClass; - if (this.state.hover) { - mainClassName += " mx_MemberTile_hover"; - } - - var name = this.props.member.name; - // if (isMyUser) name += " (me)"; // this does nothing other than introduce line wrapping and pain - //var leave = isMyUser ? : null; - - var nameClass = "mx_MemberTile_name"; - if (zalgo.test(name)) { - nameClass += " mx_MemberTile_zalgo"; - } - - var nameEl; - if (this.state.hover) { - var presence; - // FIXME: make presence data update whenever User.presence changes... - var active = this.props.member.user ? ((Date.now() - (this.props.member.user.lastPresenceTs - this.props.member.user.lastActiveAgo)) || -1) : -1; - if (active >= 0) { - presence =
{ this.getPrettyPresence(this.props.member.user) } { this.getDuration(active) } ago
; - } - else { - presence =
{ this.getPrettyPresence(this.props.member.user) }
; - } - - nameEl = -
- -
{ name }
- { presence } -
- } - else { - nameEl = -
- { name } -
- } - - var MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); - return ( -
-
- - { power } -
- { nameEl } -
- ); - } -}); diff --git a/src/skins/vector/views/molecules/MessageComposer.js b/src/skins/vector/views/molecules/MessageComposer.js deleted file mode 100644 index c613dac8..00000000 --- a/src/skins/vector/views/molecules/MessageComposer.js +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); -var MessageComposerController = require('matrix-react-sdk/lib/controllers/molecules/MessageComposer') - -var sdk = require('matrix-react-sdk') -var dis = require('matrix-react-sdk/lib/dispatcher') - -module.exports = React.createClass({ - displayName: 'MessageComposer', - mixins: [MessageComposerController], - - onInputClick: function(ev) { - this.refs.textarea.focus(); - }, - - onUploadClick: function(ev) { - this.refs.uploadInput.click(); - }, - - onUploadFileSelected: function(ev) { - var files = ev.target.files; - // MessageComposer shouldn't have to rely on it's parent passing in a callback to upload a file - if (files && files.length > 0) { - this.props.uploadFile(files[0]); - } - this.refs.uploadInput.value = null; - }, - - onCallClick: function(ev) { - dis.dispatch({ - action: 'place_call', - type: ev.shiftKey ? "screensharing" : "video", - room_id: this.props.room.roomId - }); - }, - - onVoiceCallClick: function(ev) { - dis.dispatch({ - action: 'place_call', - type: 'voice', - room_id: this.props.room.roomId - }); - }, - - render: function() { - var me = this.props.room.getMember(MatrixClientPeg.get().credentials.userId); - var uploadInputStyle = {display: 'none'}; - var MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); - return ( -
-
-
-
- -
-
-
- cancel_button =
Cancel
- save_button =
Save Changes
- } else { - // - name = -
-
{ this.props.room.name }
-
- -
-
- if (topic) topic_el =
{ topic.getContent().topic }
; - } - - var roomAvatar = null; - if (this.props.room) { - roomAvatar = ( - - ); - } - - var zoom_button, video_button, voice_button; - if (activeCall) { - if (activeCall.type == "video") { - zoom_button = ( -
- Fullscreen -
- ); - } - video_button = -
- Video call -
; - voice_button = -
- VoIP call -
; - } - - header = -
-
-
- { roomAvatar } -
-
- { name } - { topic_el } -
-
- {call_buttons} - {cancel_button} - {save_button} -
- { video_button } - { voice_button } - { zoom_button } -
- Search -
-
-
- } - - return ( -
- { header } -
- ); - }, -}); diff --git a/src/skins/vector/views/molecules/RoomSettings.js b/src/skins/vector/views/molecules/RoomSettings.js deleted file mode 100644 index 4fdd40d9..00000000 --- a/src/skins/vector/views/molecules/RoomSettings.js +++ /dev/null @@ -1,232 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); -var sdk = require('matrix-react-sdk'); - -var RoomSettingsController = require('matrix-react-sdk/lib/controllers/molecules/RoomSettings') - -module.exports = React.createClass({ - displayName: 'RoomSettings', - mixins: [RoomSettingsController], - - getTopic: function() { - return this.refs.topic.value; - }, - - getJoinRules: function() { - return this.refs.is_private.checked ? "invite" : "public"; - }, - - getHistoryVisibility: function() { - return this.refs.share_history.checked ? "shared" : "invited"; - }, - - getPowerLevels: function() { - if (!this.state.power_levels_changed) return undefined; - - var power_levels = this.props.room.currentState.getStateEvents('m.room.power_levels', ''); - power_levels = power_levels.getContent(); - - var new_power_levels = { - ban: parseInt(this.refs.ban.value), - kick: parseInt(this.refs.kick.value), - redact: parseInt(this.refs.redact.value), - invite: parseInt(this.refs.invite.value), - events_default: parseInt(this.refs.events_default.value), - state_default: parseInt(this.refs.state_default.value), - users_default: parseInt(this.refs.users_default.value), - users: power_levels.users, - events: power_levels.events, - }; - - return new_power_levels; - }, - - onPowerLevelsChanged: function() { - this.setState({ - power_levels_changed: true - }); - }, - - render: function() { - var ChangeAvatar = sdk.getComponent('molecules.ChangeAvatar'); - - var topic = this.props.room.currentState.getStateEvents('m.room.topic', ''); - if (topic) topic = topic.getContent().topic; - - var join_rule = this.props.room.currentState.getStateEvents('m.room.join_rules', ''); - if (join_rule) join_rule = join_rule.getContent().join_rule; - - var history_visibility = this.props.room.currentState.getStateEvents('m.room.history_visibility', ''); - if (history_visibility) history_visibility = history_visibility.getContent().history_visibility; - - var power_levels = this.props.room.currentState.getStateEvents('m.room.power_levels', ''); - - var events_levels = power_levels.events || {}; - - if (power_levels) { - power_levels = power_levels.getContent(); - - var ban_level = parseInt(power_levels.ban); - var kick_level = parseInt(power_levels.kick); - var redact_level = parseInt(power_levels.redact); - var invite_level = parseInt(power_levels.invite || 0); - var send_level = parseInt(power_levels.events_default || 0); - var state_level = parseInt(power_levels.state_default || 0); - var default_user_level = parseInt(power_levels.users_default || 0); - - if (power_levels.ban == undefined) ban_level = 50; - if (power_levels.kick == undefined) kick_level = 50; - if (power_levels.redact == undefined) redact_level = 50; - - var user_levels = power_levels.users || {}; - - var user_id = MatrixClientPeg.get().credentials.userId; - - var current_user_level = user_levels[user_id]; - if (current_user_level == undefined) current_user_level = default_user_level; - - var power_level_level = events_levels["m.room.power_levels"]; - if (power_level_level == undefined) { - power_level_level = state_level; - } - - var can_change_levels = current_user_level >= power_level_level; - } else { - var ban_level = 50; - var kick_level = 50; - var redact_level = 50; - var invite_level = 0; - var send_level = 0; - var state_level = 0; - var default_user_level = 0; - - var user_levels = []; - var events_levels = []; - - var current_user_level = 0; - - var power_level_level = 0; - - var can_change_levels = false; - } - - var room_avatar_level = parseInt(power_levels.state_default || 0); - if (events_levels['m.room.avatar'] !== undefined) { - room_avatar_level = events_levels['m.room.avatar']; - } - var can_set_room_avatar = current_user_level >= room_avatar_level; - - var change_avatar; - if (can_set_room_avatar) { - change_avatar =
-

Room Icon

- -
; - } - - var banned = this.props.room.getMembersWithMembership("ban"); - - return ( -
-