Merge branch 'develop'
							
								
								
									
										28
									
								
								README.md
									
									
									
									
									
								
							
							
						
						@ -22,18 +22,34 @@ into the `vector` directory and run your own server.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Development
 | 
					Development
 | 
				
			||||||
===========
 | 
					===========
 | 
				
			||||||
You can work on any of the source files within Vector with the setup above,
 | 
					 | 
				
			||||||
and your changes will cause an instant rebuild. If you also need to make
 | 
					 | 
				
			||||||
changes to the react sdk, you can:
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Link the react sdk package into the example:
 | 
					For simple tweaks, you can work on any of the source files within Vector with the
 | 
				
			||||||
 | 
					setup above, and your changes will cause an instant rebuild.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					However, all serious development on Vector happens on the `develop` branch.  This typically
 | 
				
			||||||
 | 
					depends on the `develop` snapshot versions of `matrix-react-sdk` and `matrix-js-sdk`
 | 
				
			||||||
 | 
					too, which isn't expressed in Vector's `package.json`.  To do this, check out
 | 
				
			||||||
 | 
					the `develop` branches of these libraries and then use `npm link` to tell Vector
 | 
				
			||||||
 | 
					about them:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. `git clone git@github.com:matrix-org/matrix-react-sdk.git`
 | 
				
			||||||
 | 
					2. `cd matrix-react-sdk`
 | 
				
			||||||
 | 
					3. `git checkout develop`
 | 
				
			||||||
 | 
					4. `npm install`
 | 
				
			||||||
 | 
					5. `npm start` (to start the dev rebuilder)
 | 
				
			||||||
 | 
					6. `cd ../vector-web`
 | 
				
			||||||
 | 
					7. Link the react sdk package into the example:
 | 
				
			||||||
   `npm link path/to/your/react/sdk`
 | 
					   `npm link path/to/your/react/sdk`
 | 
				
			||||||
2. Start the development rebuilder in your react SDK directory:
 | 
					
 | 
				
			||||||
   `npm start`
 | 
					Similarly, you may need to `npm link path/to/your/js/sdk` in your `matrix-react-sdk`
 | 
				
			||||||
 | 
					directory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you add or remove any components from the Vector skin, you will need to rebuild
 | 
					If you add or remove any components from the Vector skin, you will need to rebuild
 | 
				
			||||||
the skin's index by running, `npm run reskindex`.
 | 
					the skin's index by running, `npm run reskindex`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You may need to run `npm i source-map-loader` in matrix-js-sdk if you get errors
 | 
				
			||||||
 | 
					about "Cannot resolve module 'source-map-loader'" due to shortcomings in webpack.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Deployment
 | 
					Deployment
 | 
				
			||||||
==========
 | 
					==========
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -27,8 +27,8 @@
 | 
				
			|||||||
    "filesize": "^3.1.2",
 | 
					    "filesize": "^3.1.2",
 | 
				
			||||||
    "flux": "~2.0.3",
 | 
					    "flux": "~2.0.3",
 | 
				
			||||||
    "linkifyjs": "^2.0.0-beta.4",
 | 
					    "linkifyjs": "^2.0.0-beta.4",
 | 
				
			||||||
    "matrix-js-sdk": "^0.2.1",
 | 
					    "matrix-js-sdk": "^0.3.0",
 | 
				
			||||||
    "matrix-react-sdk": "^0.0.1",
 | 
					    "matrix-react-sdk": "^0.0.2",
 | 
				
			||||||
    "q": "^1.4.1",
 | 
					    "q": "^1.4.1",
 | 
				
			||||||
    "react": "^0.13.3",
 | 
					    "react": "^0.13.3",
 | 
				
			||||||
    "react-loader": "^1.4.0"
 | 
					    "react-loader": "^1.4.0"
 | 
				
			||||||
 | 
				
			|||||||
@ -20,14 +20,17 @@ var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    avatarUrlForMember: function(member, width, height, resizeMethod) {
 | 
					    avatarUrlForMember: function(member, width, height, resizeMethod) {
 | 
				
			||||||
        var url = MatrixClientPeg.get().getAvatarUrlForMember(
 | 
					        var url = member.getAvatarUrl(
 | 
				
			||||||
            member,
 | 
					            MatrixClientPeg.get().getHomeserverUrl(),
 | 
				
			||||||
            width,
 | 
					            width,
 | 
				
			||||||
            height,
 | 
					            height,
 | 
				
			||||||
            resizeMethod
 | 
					            resizeMethod
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        if (!url) {
 | 
					        if (!url) {
 | 
				
			||||||
            url = this.defaultAvatarUrlForString(member.userId);
 | 
					            // member can be null here currently since on invites, the JS SDK
 | 
				
			||||||
 | 
					            // does not have enough info to build a RoomMember object for
 | 
				
			||||||
 | 
					            // the inviter.
 | 
				
			||||||
 | 
					            url = this.defaultAvatarUrlForString(member ? member.userId : '');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return url;
 | 
					        return url;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
				
			|||||||
@ -49,15 +49,25 @@ module.exports = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        var position = {
 | 
					        var position = {
 | 
				
			||||||
            top: props.top - 20,
 | 
					            top: props.top - 20,
 | 
				
			||||||
            right: props.right + 8,
 | 
					 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var chevron = null;
 | 
				
			||||||
 | 
					        if (props.left) {
 | 
				
			||||||
 | 
					            chevron = <img className="mx_ContextualMenu_chevron_left" src="img/chevron-left.png" width="9" height="16" />
 | 
				
			||||||
 | 
					            position.left = props.left + 8;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            chevron = <img className="mx_ContextualMenu_chevron_right" src="img/chevron-right.png" width="9" height="16" />
 | 
				
			||||||
 | 
					            position.right = props.right + 8;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var className = 'mx_ContextualMenu_wrapper';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // FIXME: If a menu uses getDefaultProps it clobbers the onFinished
 | 
					        // FIXME: If a menu uses getDefaultProps it clobbers the onFinished
 | 
				
			||||||
        // property set here so you can't close the menu from a button click!
 | 
					        // property set here so you can't close the menu from a button click!
 | 
				
			||||||
        var menu = (
 | 
					        var menu = (
 | 
				
			||||||
            <div className="mx_ContextualMenu_wrapper">
 | 
					            <div className={className}>
 | 
				
			||||||
                <div className="mx_ContextualMenu" style={position}>
 | 
					                <div className="mx_ContextualMenu" style={position}>
 | 
				
			||||||
                    <img className="mx_ContextualMenu_chevron" src="img/chevron-right.png" width="9" height="16" />
 | 
					                    {chevron}
 | 
				
			||||||
                    <Element {...props} onFinished={closeMenu}/>
 | 
					                    <Element {...props} onFinished={closeMenu}/>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div className="mx_ContextualMenu_background" onClick={closeMenu}></div>
 | 
					                <div className="mx_ContextualMenu_background" onClick={closeMenu}></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -74,8 +74,10 @@ module.exports = {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
        if (call) {
 | 
					        if (call) {
 | 
				
			||||||
            call.setLocalVideoElement(this.getVideoView().getLocalVideoElement());
 | 
					            call.setLocalVideoElement(this.getVideoView().getLocalVideoElement());
 | 
				
			||||||
            // N.B. the remote video element is used for playback for audio for voice calls
 | 
					 | 
				
			||||||
            call.setRemoteVideoElement(this.getVideoView().getRemoteVideoElement());
 | 
					            call.setRemoteVideoElement(this.getVideoView().getRemoteVideoElement());
 | 
				
			||||||
 | 
					            // give a separate element for audio stream playback - both for voice calls
 | 
				
			||||||
 | 
					            // and for the voice stream of screen captures
 | 
				
			||||||
 | 
					            call.setRemoteAudioElement(this.getVideoView().getRemoteAudioElement());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (call && call.type === "video" && call.state !== 'ended') {
 | 
					        if (call && call.type === "video" && call.state !== 'ended') {
 | 
				
			||||||
            // if this call is a conf call, don't display local video as the
 | 
					            // if this call is a conf call, don't display local video as the
 | 
				
			||||||
@ -88,6 +90,7 @@ module.exports = {
 | 
				
			|||||||
        else {
 | 
					        else {
 | 
				
			||||||
            this.getVideoView().getLocalVideoElement().style.display = "none";
 | 
					            this.getVideoView().getLocalVideoElement().style.display = "none";
 | 
				
			||||||
            this.getVideoView().getRemoteVideoElement().style.display = "none";
 | 
					            this.getVideoView().getRemoteVideoElement().style.display = "none";
 | 
				
			||||||
 | 
					            dis.dispatch({action: 'video_fullscreen', fullscreen: false});
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,8 @@ module.exports = {
 | 
				
			|||||||
        cli.on("Room", this.onRoom);
 | 
					        cli.on("Room", this.onRoom);
 | 
				
			||||||
        cli.on("Room.timeline", this.onRoomTimeline);
 | 
					        cli.on("Room.timeline", this.onRoomTimeline);
 | 
				
			||||||
        cli.on("Room.name", this.onRoomName);
 | 
					        cli.on("Room.name", this.onRoomName);
 | 
				
			||||||
 | 
					        cli.on("RoomState.events", this.onRoomStateEvents);
 | 
				
			||||||
 | 
					        cli.on("RoomMember.name", this.onRoomMemberName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var rooms = this.getRoomList();
 | 
					        var rooms = this.getRoomList();
 | 
				
			||||||
        this.setState({
 | 
					        this.setState({
 | 
				
			||||||
@ -52,6 +54,11 @@ module.exports = {
 | 
				
			|||||||
            case 'call_state':
 | 
					            case 'call_state':
 | 
				
			||||||
                this._recheckCallElement(this.props.selectedRoom);
 | 
					                this._recheckCallElement(this.props.selectedRoom);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					            case 'view_tooltip':
 | 
				
			||||||
 | 
					                this.tooltip = payload.tooltip;
 | 
				
			||||||
 | 
					                this._repositionTooltip();
 | 
				
			||||||
 | 
					                if (this.tooltip) this.tooltip.style.display = 'block';
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -61,6 +68,7 @@ module.exports = {
 | 
				
			|||||||
            MatrixClientPeg.get().removeListener("Room", this.onRoom);
 | 
					            MatrixClientPeg.get().removeListener("Room", this.onRoom);
 | 
				
			||||||
            MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline);
 | 
					            MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline);
 | 
				
			||||||
            MatrixClientPeg.get().removeListener("Room.name", this.onRoomName);
 | 
					            MatrixClientPeg.get().removeListener("Room.name", this.onRoomName);
 | 
				
			||||||
 | 
					            MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -105,6 +113,15 @@ module.exports = {
 | 
				
			|||||||
        this.refreshRoomList();
 | 
					        this.refreshRoomList();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onRoomStateEvents: function(ev, state) {
 | 
				
			||||||
 | 
					        setTimeout(this.refreshRoomList, 0);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onRoomMemberName: function(ev, member) {
 | 
				
			||||||
 | 
					        setTimeout(this.refreshRoomList, 0);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    refreshRoomList: function() {
 | 
					    refreshRoomList: function() {
 | 
				
			||||||
        var rooms = this.getRoomList();
 | 
					        var rooms = this.getRoomList();
 | 
				
			||||||
        this.setState({
 | 
					        this.setState({
 | 
				
			||||||
@ -150,6 +167,13 @@ module.exports = {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _repositionTooltip: function(e) {
 | 
				
			||||||
 | 
					        if (this.tooltip && this.tooltip.parentElement) {
 | 
				
			||||||
 | 
					            var scroll = this.getDOMNode();
 | 
				
			||||||
 | 
					            this.tooltip.style.top = (scroll.parentElement.offsetTop + this.tooltip.parentElement.offsetTop - scroll.scrollTop) + "px"; 
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    makeRoomTiles: function() {
 | 
					    makeRoomTiles: function() {
 | 
				
			||||||
        var self = this;
 | 
					        var self = this;
 | 
				
			||||||
        var RoomTile = sdk.getComponent("molecules.RoomTile");
 | 
					        var RoomTile = sdk.getComponent("molecules.RoomTile");
 | 
				
			||||||
@ -159,6 +183,7 @@ module.exports = {
 | 
				
			|||||||
                <RoomTile
 | 
					                <RoomTile
 | 
				
			||||||
                    room={room}
 | 
					                    room={room}
 | 
				
			||||||
                    key={room.roomId}
 | 
					                    key={room.roomId}
 | 
				
			||||||
 | 
					                    collapsed={self.props.collapsed}
 | 
				
			||||||
                    selected={selected}
 | 
					                    selected={selected}
 | 
				
			||||||
                    unread={self.state.activityMap[room.roomId] === 1}
 | 
					                    unread={self.state.activityMap[room.roomId] === 1}
 | 
				
			||||||
                    highlight={self.state.activityMap[room.roomId] === 2}
 | 
					                    highlight={self.state.activityMap[room.roomId] === 2}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										503
									
								
								src/controllers/organisms/RoomView.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,503 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var MatrixClientPeg = require("matrix-react-sdk/lib/MatrixClientPeg");
 | 
				
			||||||
 | 
					var React = require("react");
 | 
				
			||||||
 | 
					var q = require("q");
 | 
				
			||||||
 | 
					var ContentMessages = require("matrix-react-sdk/lib//ContentMessages");
 | 
				
			||||||
 | 
					var WhoIsTyping = require("matrix-react-sdk/lib/WhoIsTyping");
 | 
				
			||||||
 | 
					var Modal = require("matrix-react-sdk/lib/Modal");
 | 
				
			||||||
 | 
					var sdk = require('matrix-react-sdk/lib/index');
 | 
				
			||||||
 | 
					var CallHandler = require('matrix-react-sdk/lib/CallHandler');
 | 
				
			||||||
 | 
					var VectorConferenceHandler = require('../../modules/VectorConferenceHandler');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var dis = require("matrix-react-sdk/lib/dispatcher");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var PAGINATE_SIZE = 20;
 | 
				
			||||||
 | 
					var INITIAL_SIZE = 20;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					    getInitialState: function() {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            room: this.props.roomId ? MatrixClientPeg.get().getRoom(this.props.roomId) : null,
 | 
				
			||||||
 | 
					            messageCap: INITIAL_SIZE,
 | 
				
			||||||
 | 
					            editingRoomSettings: false,
 | 
				
			||||||
 | 
					            uploadingRoomSettings: false,
 | 
				
			||||||
 | 
					            numUnreadMessages: 0,
 | 
				
			||||||
 | 
					            draggingFile: false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentWillMount: function() {
 | 
				
			||||||
 | 
					        this.dispatcherRef = dis.register(this.onAction);
 | 
				
			||||||
 | 
					        MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline);
 | 
				
			||||||
 | 
					        MatrixClientPeg.get().on("Room.name", this.onRoomName);
 | 
				
			||||||
 | 
					        MatrixClientPeg.get().on("RoomMember.typing", this.onRoomMemberTyping);
 | 
				
			||||||
 | 
					        MatrixClientPeg.get().on("RoomState.members", this.onRoomStateMember);
 | 
				
			||||||
 | 
					        this.atBottom = true;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentWillUnmount: function() {
 | 
				
			||||||
 | 
					        if (this.refs.messageWrapper) {
 | 
				
			||||||
 | 
					            var messageWrapper = this.refs.messageWrapper.getDOMNode();
 | 
				
			||||||
 | 
					            messageWrapper.removeEventListener('drop', this.onDrop);
 | 
				
			||||||
 | 
					            messageWrapper.removeEventListener('dragover', this.onDragOver);
 | 
				
			||||||
 | 
					            messageWrapper.removeEventListener('dragleave', this.onDragLeaveOrEnd);
 | 
				
			||||||
 | 
					            messageWrapper.removeEventListener('dragend', this.onDragLeaveOrEnd);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        dis.unregister(this.dispatcherRef);
 | 
				
			||||||
 | 
					        if (MatrixClientPeg.get()) {
 | 
				
			||||||
 | 
					            MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline);
 | 
				
			||||||
 | 
					            MatrixClientPeg.get().removeListener("Room.name", this.onRoomName);
 | 
				
			||||||
 | 
					            MatrixClientPeg.get().removeListener("RoomMember.typing", this.onRoomMemberTyping);
 | 
				
			||||||
 | 
					            MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onAction: function(payload) {
 | 
				
			||||||
 | 
					        switch (payload.action) {
 | 
				
			||||||
 | 
					            case 'message_send_failed':
 | 
				
			||||||
 | 
					            case 'message_sent':
 | 
				
			||||||
 | 
					            case 'message_resend_started':
 | 
				
			||||||
 | 
					                this.setState({
 | 
				
			||||||
 | 
					                    room: MatrixClientPeg.get().getRoom(this.props.roomId)
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					                this.forceUpdate();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 'notifier_enabled':
 | 
				
			||||||
 | 
					                this.forceUpdate();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 'call_state':
 | 
				
			||||||
 | 
					                if (CallHandler.getCallForRoom(this.props.roomId)) {
 | 
				
			||||||
 | 
					                    // Call state has changed so we may be loading video elements
 | 
				
			||||||
 | 
					                    // which will obscure the message log.
 | 
				
			||||||
 | 
					                    // scroll to bottom
 | 
				
			||||||
 | 
					                    var messageWrapper = this.refs.messageWrapper;
 | 
				
			||||||
 | 
					                    if (messageWrapper) {
 | 
				
			||||||
 | 
					                        messageWrapper = messageWrapper.getDOMNode();
 | 
				
			||||||
 | 
					                        messageWrapper.scrollTop = messageWrapper.scrollHeight;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // possibly remove the conf call notification if we're now in
 | 
				
			||||||
 | 
					                // the conf
 | 
				
			||||||
 | 
					                this._updateConfCallNotification();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // MatrixRoom still showing the messages from the old room?
 | 
				
			||||||
 | 
					    // Set the key to the room_id. Sadly you can no longer get at
 | 
				
			||||||
 | 
					    // the key from inside the component, or we'd check this in code.
 | 
				
			||||||
 | 
					    /*componentWillReceiveProps: function(props) {
 | 
				
			||||||
 | 
					    },*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onRoomTimeline: function(ev, room, toStartOfTimeline) {
 | 
				
			||||||
 | 
					        if (!this.isMounted()) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // ignore anything that comes in whilst pagingating: we get one
 | 
				
			||||||
 | 
					        // event for each new matrix event so this would cause a huge
 | 
				
			||||||
 | 
					        // number of UI updates. Just update the UI when the paginate
 | 
				
			||||||
 | 
					        // call returns.
 | 
				
			||||||
 | 
					        if (this.state.paginating) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // no point handling anything while we're waiting for the join to finish:
 | 
				
			||||||
 | 
					        // we'll only be showing a spinner.
 | 
				
			||||||
 | 
					        if (this.state.joining) return;
 | 
				
			||||||
 | 
					        if (room.roomId != this.props.roomId) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.refs.messageWrapper) {
 | 
				
			||||||
 | 
					            var messageWrapper = this.refs.messageWrapper.getDOMNode();
 | 
				
			||||||
 | 
					            this.atBottom = (
 | 
				
			||||||
 | 
					                messageWrapper.scrollHeight - messageWrapper.scrollTop <=
 | 
				
			||||||
 | 
					                (messageWrapper.clientHeight + 150)
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var currentUnread = this.state.numUnreadMessages;
 | 
				
			||||||
 | 
					        if (!toStartOfTimeline &&
 | 
				
			||||||
 | 
					                (ev.getSender() !== MatrixClientPeg.get().credentials.userId)) {
 | 
				
			||||||
 | 
					            // update unread count when scrolled up
 | 
				
			||||||
 | 
					            if (this.atBottom) {
 | 
				
			||||||
 | 
					                currentUnread = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                currentUnread += 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.setState({
 | 
				
			||||||
 | 
					            room: MatrixClientPeg.get().getRoom(this.props.roomId),
 | 
				
			||||||
 | 
					            numUnreadMessages: currentUnread
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (toStartOfTimeline && !this.state.paginating) {
 | 
				
			||||||
 | 
					            this.fillSpace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onRoomName: function(room) {
 | 
				
			||||||
 | 
					        if (room.roomId == this.props.roomId) {
 | 
				
			||||||
 | 
					            this.setState({
 | 
				
			||||||
 | 
					                room: room
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onRoomMemberTyping: function(ev, member) {
 | 
				
			||||||
 | 
					        this.forceUpdate();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onRoomStateMember: function(ev, state, member) {
 | 
				
			||||||
 | 
					        if (member.roomId !== this.props.roomId ||
 | 
				
			||||||
 | 
					                member.userId !== VectorConferenceHandler.getConferenceUserIdForRoom(member.roomId)) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this._updateConfCallNotification();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _updateConfCallNotification: function() {
 | 
				
			||||||
 | 
					        var room = MatrixClientPeg.get().getRoom(this.props.roomId);
 | 
				
			||||||
 | 
					        if (!room) return;
 | 
				
			||||||
 | 
					        var confMember = room.getMember(
 | 
				
			||||||
 | 
					            VectorConferenceHandler.getConferenceUserIdForRoom(this.props.roomId)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!confMember) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        var confCall = VectorConferenceHandler.getConferenceCallForRoom(confMember.roomId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // A conf call notification should be displayed if there is an ongoing
 | 
				
			||||||
 | 
					        // conf call but this cilent isn't a part of it.
 | 
				
			||||||
 | 
					        this.setState({
 | 
				
			||||||
 | 
					            displayConfCallNotification: (
 | 
				
			||||||
 | 
					                (!confCall || confCall.call_state === "ended") &&
 | 
				
			||||||
 | 
					                confMember.membership === "join"
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentDidMount: function() {
 | 
				
			||||||
 | 
					        if (this.refs.messageWrapper) {
 | 
				
			||||||
 | 
					            var messageWrapper = this.refs.messageWrapper.getDOMNode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            messageWrapper.addEventListener('drop', this.onDrop);
 | 
				
			||||||
 | 
					            messageWrapper.addEventListener('dragover', this.onDragOver);
 | 
				
			||||||
 | 
					            messageWrapper.addEventListener('dragleave', this.onDragLeaveOrEnd);
 | 
				
			||||||
 | 
					            messageWrapper.addEventListener('dragend', this.onDragLeaveOrEnd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            messageWrapper.scrollTop = messageWrapper.scrollHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.fillSpace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this._updateConfCallNotification();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentDidUpdate: function() {
 | 
				
			||||||
 | 
					        if (!this.refs.messageWrapper) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var messageWrapper = this.refs.messageWrapper.getDOMNode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.state.paginating && !this.waiting_for_paginate) {
 | 
				
			||||||
 | 
					            var heightGained = messageWrapper.scrollHeight - this.oldScrollHeight;
 | 
				
			||||||
 | 
					            messageWrapper.scrollTop += heightGained;
 | 
				
			||||||
 | 
					            this.oldScrollHeight = undefined;
 | 
				
			||||||
 | 
					            if (!this.fillSpace()) {
 | 
				
			||||||
 | 
					                this.setState({paginating: false});
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (this.atBottom) {
 | 
				
			||||||
 | 
					            messageWrapper.scrollTop = messageWrapper.scrollHeight;
 | 
				
			||||||
 | 
					            if (this.state.numUnreadMessages !== 0) {
 | 
				
			||||||
 | 
					                this.setState({numUnreadMessages: 0});
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fillSpace: function() {
 | 
				
			||||||
 | 
					        if (!this.refs.messageWrapper) return;
 | 
				
			||||||
 | 
					        var messageWrapper = this.refs.messageWrapper.getDOMNode();
 | 
				
			||||||
 | 
					        if (messageWrapper.scrollTop < messageWrapper.clientHeight && this.state.room.oldState.paginationToken) {
 | 
				
			||||||
 | 
					            this.setState({paginating: true});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.oldScrollHeight = messageWrapper.scrollHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (this.state.messageCap < this.state.room.timeline.length) {
 | 
				
			||||||
 | 
					                this.waiting_for_paginate = false;
 | 
				
			||||||
 | 
					                var cap = Math.min(this.state.messageCap + PAGINATE_SIZE, this.state.room.timeline.length);
 | 
				
			||||||
 | 
					                this.setState({messageCap: cap, paginating: true});
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                this.waiting_for_paginate = true;
 | 
				
			||||||
 | 
					                var cap = this.state.messageCap + PAGINATE_SIZE;
 | 
				
			||||||
 | 
					                this.setState({messageCap: cap, paginating: true});
 | 
				
			||||||
 | 
					                var self = this;
 | 
				
			||||||
 | 
					                MatrixClientPeg.get().scrollback(this.state.room, PAGINATE_SIZE).finally(function() {
 | 
				
			||||||
 | 
					                    self.waiting_for_paginate = false;
 | 
				
			||||||
 | 
					                    if (self.isMounted()) {
 | 
				
			||||||
 | 
					                        self.setState({
 | 
				
			||||||
 | 
					                            room: MatrixClientPeg.get().getRoom(self.props.roomId)
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    // wait and set paginating to false when the component updates
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onJoinButtonClicked: function(ev) {
 | 
				
			||||||
 | 
					        var self = this;
 | 
				
			||||||
 | 
					        MatrixClientPeg.get().joinRoom(this.props.roomId).then(function() {
 | 
				
			||||||
 | 
					            self.setState({
 | 
				
			||||||
 | 
					                joining: false,
 | 
				
			||||||
 | 
					                room: MatrixClientPeg.get().getRoom(self.props.roomId)
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }, function(error) {
 | 
				
			||||||
 | 
					            self.setState({
 | 
				
			||||||
 | 
					                joining: false,
 | 
				
			||||||
 | 
					                joinError: error
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        this.setState({
 | 
				
			||||||
 | 
					            joining: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onMessageListScroll: function(ev) {
 | 
				
			||||||
 | 
					        if (this.refs.messageWrapper) {
 | 
				
			||||||
 | 
					            var messageWrapper = this.refs.messageWrapper.getDOMNode();
 | 
				
			||||||
 | 
					            var wasAtBottom = this.atBottom;
 | 
				
			||||||
 | 
					            this.atBottom = messageWrapper.scrollHeight - messageWrapper.scrollTop <= messageWrapper.clientHeight;
 | 
				
			||||||
 | 
					            if (this.atBottom && !wasAtBottom) {
 | 
				
			||||||
 | 
					                this.forceUpdate(); // remove unread msg count
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!this.state.paginating) this.fillSpace();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onDragOver: function(ev) {
 | 
				
			||||||
 | 
					        ev.stopPropagation();
 | 
				
			||||||
 | 
					        ev.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ev.dataTransfer.dropEffect = 'none';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var items = ev.dataTransfer.items;
 | 
				
			||||||
 | 
					        if (items.length == 1) {
 | 
				
			||||||
 | 
					            if (items[0].kind == 'file') {
 | 
				
			||||||
 | 
					                this.setState({ draggingFile : true });
 | 
				
			||||||
 | 
					                ev.dataTransfer.dropEffect = 'copy';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onDrop: function(ev) {
 | 
				
			||||||
 | 
					        ev.stopPropagation();
 | 
				
			||||||
 | 
					        ev.preventDefault();
 | 
				
			||||||
 | 
					        this.setState({ draggingFile : false });
 | 
				
			||||||
 | 
					        var files = ev.dataTransfer.files;
 | 
				
			||||||
 | 
					        if (files.length == 1) {
 | 
				
			||||||
 | 
					            this.uploadFile(files[0]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onDragLeaveOrEnd: function(ev) {
 | 
				
			||||||
 | 
					        ev.stopPropagation();
 | 
				
			||||||
 | 
					        ev.preventDefault();
 | 
				
			||||||
 | 
					        this.setState({ draggingFile : false });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uploadFile: function(file) {
 | 
				
			||||||
 | 
					        this.setState({
 | 
				
			||||||
 | 
					            upload: {
 | 
				
			||||||
 | 
					                fileName: file.name,
 | 
				
			||||||
 | 
					                uploadedBytes: 0,
 | 
				
			||||||
 | 
					                totalBytes: file.size
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        var self = this;
 | 
				
			||||||
 | 
					        ContentMessages.sendContentToRoom(
 | 
				
			||||||
 | 
					            file, this.props.roomId, MatrixClientPeg.get()
 | 
				
			||||||
 | 
					        ).progress(function(ev) {
 | 
				
			||||||
 | 
					            //console.log("Upload: "+ev.loaded+" / "+ev.total);
 | 
				
			||||||
 | 
					            self.setState({
 | 
				
			||||||
 | 
					                upload: {
 | 
				
			||||||
 | 
					                    fileName: file.name,
 | 
				
			||||||
 | 
					                    uploadedBytes: ev.loaded,
 | 
				
			||||||
 | 
					                    totalBytes: ev.total
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }).finally(function() {
 | 
				
			||||||
 | 
					            self.setState({
 | 
				
			||||||
 | 
					                upload: undefined
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }).done(undefined, function() {
 | 
				
			||||||
 | 
					            // display error message
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getWhoIsTypingString: function() {
 | 
				
			||||||
 | 
					        return WhoIsTyping.whoIsTypingString(this.state.room);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getEventTiles: function() {
 | 
				
			||||||
 | 
					        var DateSeparator = sdk.getComponent('molecules.DateSeparator');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var ret = [];
 | 
				
			||||||
 | 
					        var count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var EventTile = sdk.getComponent('molecules.EventTile');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (var i = this.state.room.timeline.length-1; i >= 0 && count < this.state.messageCap; --i) {
 | 
				
			||||||
 | 
					            var mxEv = this.state.room.timeline[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!EventTile.supportsEventType(mxEv.getType())) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var continuation = false;
 | 
				
			||||||
 | 
					            var last = false;
 | 
				
			||||||
 | 
					            var dateSeparator = null;
 | 
				
			||||||
 | 
					            if (i == this.state.room.timeline.length - 1) {
 | 
				
			||||||
 | 
					                last = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (i > 0 && count < this.state.messageCap - 1) {
 | 
				
			||||||
 | 
					                if (this.state.room.timeline[i].sender &&
 | 
				
			||||||
 | 
					                    this.state.room.timeline[i - 1].sender &&
 | 
				
			||||||
 | 
					                    (this.state.room.timeline[i].sender.userId ===
 | 
				
			||||||
 | 
					                        this.state.room.timeline[i - 1].sender.userId) &&
 | 
				
			||||||
 | 
					                    (this.state.room.timeline[i].getType() ==
 | 
				
			||||||
 | 
					                        this.state.room.timeline[i - 1].getType())
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    continuation = true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                var ts0 = this.state.room.timeline[i - 1].getTs();
 | 
				
			||||||
 | 
					                var ts1 = this.state.room.timeline[i].getTs();
 | 
				
			||||||
 | 
					                if (new Date(ts0).toDateString() !== new Date(ts1).toDateString()) {
 | 
				
			||||||
 | 
					                    dateSeparator = <DateSeparator key={ts1} ts={ts1}/>;
 | 
				
			||||||
 | 
					                    continuation = false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (i === 1) { // n.b. 1, not 0, as the 0th event is an m.room.create and so doesn't show on the timeline
 | 
				
			||||||
 | 
					                var ts1 = this.state.room.timeline[i].getTs();
 | 
				
			||||||
 | 
					                dateSeparator = <li key={ts1}><DateSeparator ts={ts1}/></li>;
 | 
				
			||||||
 | 
					                continuation = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ret.unshift(
 | 
				
			||||||
 | 
					                <li key={mxEv.getId()}><EventTile mxEvent={mxEv} continuation={continuation} last={last}/></li>
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            if (dateSeparator) {
 | 
				
			||||||
 | 
					                ret.unshift(dateSeparator);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ++count;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uploadNewState: function(new_name, new_topic, new_join_rule, new_history_visibility, new_power_levels) {
 | 
				
			||||||
 | 
					        var old_name = this.state.room.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var old_topic = this.state.room.currentState.getStateEvents('m.room.topic', '');
 | 
				
			||||||
 | 
					        if (old_topic) {
 | 
				
			||||||
 | 
					            old_topic = old_topic.getContent().topic;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            old_topic = "";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var old_join_rule = this.state.room.currentState.getStateEvents('m.room.join_rules', '');
 | 
				
			||||||
 | 
					        if (old_join_rule) {
 | 
				
			||||||
 | 
					            old_join_rule = old_join_rule.getContent().join_rule;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            old_join_rule = "invite";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var old_history_visibility = this.state.room.currentState.getStateEvents('m.room.history_visibility', '');
 | 
				
			||||||
 | 
					        if (old_history_visibility) {
 | 
				
			||||||
 | 
					            old_history_visibility = old_history_visibility.getContent().history_visibility;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            old_history_visibility = "shared";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var deferreds = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (old_name != new_name && new_name != undefined && new_name) {
 | 
				
			||||||
 | 
					            deferreds.push(
 | 
				
			||||||
 | 
					                MatrixClientPeg.get().setRoomName(this.state.room.roomId, new_name)
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (old_topic != new_topic && new_topic != undefined) {
 | 
				
			||||||
 | 
					            deferreds.push(
 | 
				
			||||||
 | 
					                MatrixClientPeg.get().setRoomTopic(this.state.room.roomId, new_topic)
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (old_join_rule != new_join_rule && new_join_rule != undefined) {
 | 
				
			||||||
 | 
					            deferreds.push(
 | 
				
			||||||
 | 
					                MatrixClientPeg.get().sendStateEvent(
 | 
				
			||||||
 | 
					                    this.state.room.roomId, "m.room.join_rules", {
 | 
				
			||||||
 | 
					                        join_rule: new_join_rule,
 | 
				
			||||||
 | 
					                    }, ""
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (old_history_visibility != new_history_visibility && new_history_visibility != undefined) {
 | 
				
			||||||
 | 
					            deferreds.push(
 | 
				
			||||||
 | 
					                MatrixClientPeg.get().sendStateEvent(
 | 
				
			||||||
 | 
					                    this.state.room.roomId, "m.room.history_visibility", {
 | 
				
			||||||
 | 
					                        history_visibility: new_history_visibility,
 | 
				
			||||||
 | 
					                    }, ""
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (new_power_levels) {
 | 
				
			||||||
 | 
					            deferreds.push(
 | 
				
			||||||
 | 
					                MatrixClientPeg.get().sendStateEvent(
 | 
				
			||||||
 | 
					                    this.state.room.roomId, "m.room.power_levels", new_power_levels, ""
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (deferreds.length) {
 | 
				
			||||||
 | 
					            var self = this;
 | 
				
			||||||
 | 
					            q.all(deferreds).fail(function(err) {
 | 
				
			||||||
 | 
					                var ErrorDialog = sdk.getComponent("organisms.ErrorDialog");
 | 
				
			||||||
 | 
					                Modal.createDialog(ErrorDialog, {
 | 
				
			||||||
 | 
					                    title: "Failed to set state",
 | 
				
			||||||
 | 
					                    description: err.toString()
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }).finally(function() {
 | 
				
			||||||
 | 
					                self.setState({
 | 
				
			||||||
 | 
					                    uploadingRoomSettings: false,
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.setState({
 | 
				
			||||||
 | 
					                editingRoomSettings: false,
 | 
				
			||||||
 | 
					                uploadingRoomSettings: false,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										58
									
								
								src/controllers/templates/Register.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 extend = require('matrix-react-sdk/lib/extend');
 | 
				
			||||||
 | 
					var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
				
			||||||
 | 
					var BaseRegisterController = require('matrix-react-sdk/lib/controllers/templates/Register.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var RegisterController = {};
 | 
				
			||||||
 | 
					extend(RegisterController, BaseRegisterController);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RegisterController.onRegistered = function(user_id, access_token) {
 | 
				
			||||||
 | 
					    MatrixClientPeg.replaceUsingAccessToken(
 | 
				
			||||||
 | 
					        this.state.hs_url, this.state.is_url, user_id, access_token
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.setState({
 | 
				
			||||||
 | 
					        step: 'profile',
 | 
				
			||||||
 | 
					        busy: true
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var self = this;
 | 
				
			||||||
 | 
					    var cli = MatrixClientPeg.get();
 | 
				
			||||||
 | 
					    cli.getProfileInfo(cli.credentials.userId).done(function(result) {
 | 
				
			||||||
 | 
					        self.setState({
 | 
				
			||||||
 | 
					            avatarUrl: result.avatar_url,
 | 
				
			||||||
 | 
					            busy: false
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    function(err) {
 | 
				
			||||||
 | 
					        console.err(err);
 | 
				
			||||||
 | 
					        self.setState({
 | 
				
			||||||
 | 
					            busy: false
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RegisterController.onAccountReady = function() {
 | 
				
			||||||
 | 
					    if (this.props.onLoggedIn) {
 | 
				
			||||||
 | 
					        this.props.onLoggedIn();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = RegisterController;
 | 
				
			||||||
@ -14,6 +14,13 @@ See the License for the specific language governing permissions and
 | 
				
			|||||||
limitations under the License.
 | 
					limitations under the License.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					html {
 | 
				
			||||||
 | 
					    /* hack to stop overscroll bounce on OSX and iOS.
 | 
				
			||||||
 | 
					       N.B. Breaks things when we have legitimate horizontal overscroll */
 | 
				
			||||||
 | 
					    height: 100%;
 | 
				
			||||||
 | 
					    overflow: hidden;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
body {
 | 
					body {
 | 
				
			||||||
    font-family: 'Lato', Helvetica, Arial, Sans-Serif;
 | 
					    font-family: 'Lato', Helvetica, Arial, Sans-Serif;
 | 
				
			||||||
    font-size: 16px;
 | 
					    font-size: 16px;
 | 
				
			||||||
@ -34,6 +41,12 @@ h2 {
 | 
				
			|||||||
    margin-bottom: 16px;
 | 
					    margin-bottom: 16px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a:hover,
 | 
				
			||||||
 | 
					a:link,
 | 
				
			||||||
 | 
					a:visited {
 | 
				
			||||||
 | 
					    color: #80CEF4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_ContextualMenu_background {
 | 
					.mx_ContextualMenu_background {
 | 
				
			||||||
    position: fixed;
 | 
					    position: fixed;
 | 
				
			||||||
    top: 0;
 | 
					    top: 0;
 | 
				
			||||||
@ -54,18 +67,29 @@ h2 {
 | 
				
			|||||||
    padding: 6px;
 | 
					    padding: 6px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_ContextualMenu_chevron {
 | 
					.mx_ContextualMenu_chevron_right {
 | 
				
			||||||
    padding: 12px;
 | 
					    padding: 12px;
 | 
				
			||||||
    position: absolute;
 | 
					    position: absolute;
 | 
				
			||||||
    right: -21px;
 | 
					    right: -21px;
 | 
				
			||||||
    top: 0px;
 | 
					    top: 0px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_ContextualMenu_chevron_left {
 | 
				
			||||||
 | 
					    padding: 12px;
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    left: -21px;
 | 
				
			||||||
 | 
					    top: 0px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_ContextualMenu_field {
 | 
					.mx_ContextualMenu_field {
 | 
				
			||||||
    padding: 3px 6px 3px 6px;
 | 
					    padding: 3px 6px 3px 6px;
 | 
				
			||||||
    cursor: pointer;
 | 
					    cursor: pointer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_ContextualMenu_spinner {
 | 
				
			||||||
 | 
					    display: block;
 | 
				
			||||||
 | 
					    margin: 0 auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_Dialog_background {
 | 
					.mx_Dialog_background {
 | 
				
			||||||
    position: fixed;
 | 
					    position: fixed;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,6 @@
 | 
				
			|||||||
.mx_RoomDropTarget,
 | 
					.mx_RoomDropTarget,
 | 
				
			||||||
.mx_RoomList_favourites_label,
 | 
					.mx_RoomList_favourites_label,
 | 
				
			||||||
.mx_RoomList_archive_label,
 | 
					.mx_RoomList_archive_label,
 | 
				
			||||||
.mx_LeftPanel_hideButton,
 | 
					 | 
				
			||||||
.mx_RoomHeader_search,
 | 
					.mx_RoomHeader_search,
 | 
				
			||||||
.mx_RoomSettings_encrypt,
 | 
					.mx_RoomSettings_encrypt,
 | 
				
			||||||
.mx_CreateRoom_encrypt,
 | 
					.mx_CreateRoom_encrypt,
 | 
				
			||||||
 | 
				
			|||||||
@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
 | 
				
			|||||||
limitations under the License.
 | 
					limitations under the License.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile {
 | 
					.mx_EventTile {
 | 
				
			||||||
    max-width: 100%;
 | 
					    max-width: 100%;
 | 
				
			||||||
    clear: both;
 | 
					    clear: both;
 | 
				
			||||||
    margin-top: 32px;
 | 
					    margin-top: 32px;
 | 
				
			||||||
    margin-left: 56px;
 | 
					    margin-left: 56px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_avatar {
 | 
					.mx_EventTile_avatar {
 | 
				
			||||||
    padding-left: 12px;
 | 
					    padding-left: 12px;
 | 
				
			||||||
    padding-right: 12px;
 | 
					    padding-right: 12px;
 | 
				
			||||||
    margin-left: -64px;
 | 
					    margin-left: -64px;
 | 
				
			||||||
@ -29,17 +29,17 @@ limitations under the License.
 | 
				
			|||||||
    float: left;
 | 
					    float: left;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_avatar img {
 | 
					.mx_EventTile_avatar img {
 | 
				
			||||||
    background-color: #dbdbdb;
 | 
					    background-color: #dbdbdb;
 | 
				
			||||||
    border-radius: 20px;
 | 
					    border-radius: 20px;
 | 
				
			||||||
    border: 0px;
 | 
					    border: 0px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_continuation {
 | 
					.mx_EventTile_continuation {
 | 
				
			||||||
    margin-top: 8px ! important;
 | 
					    margin-top: 8px ! important;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile .mx_SenderProfile {
 | 
					.mx_EventTile .mx_SenderProfile {
 | 
				
			||||||
    color: #454545;
 | 
					    color: #454545;
 | 
				
			||||||
    opacity: 0.5;
 | 
					    opacity: 0.5;
 | 
				
			||||||
    font-size: 14px;
 | 
					    font-size: 14px;
 | 
				
			||||||
@ -47,35 +47,35 @@ limitations under the License.
 | 
				
			|||||||
    display: block;
 | 
					    display: block;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile .mx_MessageTimestamp {
 | 
					.mx_EventTile .mx_MessageTimestamp {
 | 
				
			||||||
    color: #454545;
 | 
					    color: #454545;
 | 
				
			||||||
    opacity: 0.5;
 | 
					    opacity: 0.5;
 | 
				
			||||||
    font-size: 14px;
 | 
					    font-size: 14px;
 | 
				
			||||||
    float: right;
 | 
					    float: right;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_content {
 | 
					.mx_EventTile_content {
 | 
				
			||||||
    padding-right: 100px;
 | 
					    padding-right: 100px;
 | 
				
			||||||
    display: block;
 | 
					    display: block;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_notice .mx_MessageTile_content {
 | 
					.mx_EventTile_notice .mx_MessageTile_content {
 | 
				
			||||||
    opacity: 0.5;
 | 
					    opacity: 0.5;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_sending {
 | 
					.mx_EventTile_sending {
 | 
				
			||||||
    color: #ddd;
 | 
					    color: #ddd;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_notSent {
 | 
					.mx_EventTile_notSent {
 | 
				
			||||||
    color: #f11;
 | 
					    color: #f11;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_highlight {
 | 
					.mx_EventTile_highlight {
 | 
				
			||||||
    color: #00f;
 | 
					    color: #FF0064;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_msgOption {
 | 
					.mx_EventTile_msgOption {
 | 
				
			||||||
    float: right;
 | 
					    float: right;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -83,10 +83,30 @@ limitations under the License.
 | 
				
			|||||||
    display: none;
 | 
					    display: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile_last .mx_MessageTimestamp {
 | 
					.mx_EventTile_last .mx_MessageTimestamp {
 | 
				
			||||||
    display: block;
 | 
					    display: block;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MessageTile:hover .mx_MessageTimestamp {
 | 
					.mx_EventTile:hover .mx_MessageTimestamp {
 | 
				
			||||||
    display: block;
 | 
					    display: block;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_EventTile_editButton {
 | 
				
			||||||
 | 
					    float: right;
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					    border: 0px;
 | 
				
			||||||
 | 
					    outline: none;
 | 
				
			||||||
 | 
					    margin-right: 3px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_EventTile:hover .mx_EventTile_editButton {
 | 
				
			||||||
 | 
					    display: inline-block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_EventTile.menu .mx_EventTile_editButton {
 | 
				
			||||||
 | 
					    display: inline-block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_EventTile.menu .mx_MessageTimestamp {
 | 
				
			||||||
 | 
					    display: inline-block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -15,7 +15,6 @@ limitations under the License.
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MatrixToolbar {
 | 
					.mx_MatrixToolbar {
 | 
				
			||||||
    width: 100%;
 | 
					 | 
				
			||||||
    text-align: center;
 | 
					    text-align: center;
 | 
				
			||||||
    background-color: #ff0064;
 | 
					    background-color: #ff0064;
 | 
				
			||||||
    color: #fff;
 | 
					    color: #fff;
 | 
				
			||||||
 | 
				
			|||||||
@ -128,3 +128,7 @@ limitations under the License.
 | 
				
			|||||||
.mx_MemberTile_zalgo {
 | 
					.mx_MemberTile_zalgo {
 | 
				
			||||||
    font-family: Helvetica, Arial, Sans-Serif;
 | 
					    font-family: Helvetica, Arial, Sans-Serif;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_MemberTile:hover .mx_MessageTimestamp {
 | 
				
			||||||
 | 
					    display: block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -116,13 +116,16 @@ limitations under the License.
 | 
				
			|||||||
    margin-top: -5px;
 | 
					    margin-top: -5px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_RoomHeader_nameInput {
 | 
					.mx_RoomHeader_name input, .mx_RoomHeader_nameInput {
 | 
				
			||||||
    border-radius: 3px;
 | 
					    border-radius: 3px;
 | 
				
			||||||
    width: 260px;
 | 
					    width: 260px;
 | 
				
			||||||
    border: 1px solid #c7c7c7;
 | 
					    border: 1px solid #c7c7c7;
 | 
				
			||||||
    font-weight: 300;
 | 
					    font-weight: 300;
 | 
				
			||||||
    font-size: 14px;
 | 
					    font-size: 14px;
 | 
				
			||||||
    padding: 9px;
 | 
					    padding: 9px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_RoomHeader_nameInput {
 | 
				
			||||||
    margin-top: 6px;
 | 
					    margin-top: 6px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -160,3 +163,11 @@ limitations under the License.
 | 
				
			|||||||
.mx_RoomHeader_button img {
 | 
					.mx_RoomHeader_button img {
 | 
				
			||||||
    cursor: pointer;
 | 
					    cursor: pointer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_RoomHeader_voipButton {
 | 
				
			||||||
 | 
					    display: table-cell;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_RoomHeader_voipButtons {
 | 
				
			||||||
 | 
					    margin-top: 18px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -22,13 +22,13 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.mx_RoomTile_avatar {
 | 
					.mx_RoomTile_avatar {
 | 
				
			||||||
    display: table-cell;
 | 
					    display: table-cell;
 | 
				
			||||||
    padding-right: 12px;
 | 
					    padding-right: 10px;
 | 
				
			||||||
    padding-top: 3px;
 | 
					    padding-top: 3px;
 | 
				
			||||||
    padding-bottom: 3px;
 | 
					    padding-bottom: 3px;
 | 
				
			||||||
    padding-left: 16px;
 | 
					    padding-left: 10px;
 | 
				
			||||||
    vertical-align: middle;
 | 
					    vertical-align: middle;
 | 
				
			||||||
    width: 40px;
 | 
					    width: 36px;
 | 
				
			||||||
    height: 40px;
 | 
					    height: 36px;
 | 
				
			||||||
    position: relative;
 | 
					    position: relative;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -45,6 +45,10 @@ limitations under the License.
 | 
				
			|||||||
    padding-right: 16px;    
 | 
					    padding-right: 16px;    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.collapsed .mx_RoomTile_name {
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
.mx_RoomTile_nameBadge {
 | 
					.mx_RoomTile_nameBadge {
 | 
				
			||||||
    display: table;
 | 
					    display: table;
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,20 @@ See the License for the specific language governing permissions and
 | 
				
			|||||||
limitations under the License.
 | 
					limitations under the License.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
'use strict';
 | 
					.mx_RoomTooltip {
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					    position: fixed;
 | 
				
			||||||
 | 
					    border: 1px solid #a9dbf4;
 | 
				
			||||||
 | 
					    border-radius: 8px;
 | 
				
			||||||
 | 
					    background-color: #fff;
 | 
				
			||||||
 | 
					    z-index: 1000;
 | 
				
			||||||
 | 
					    margin-top: 6px;
 | 
				
			||||||
 | 
					    left: 64px;
 | 
				
			||||||
 | 
					    padding: 6px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					.mx_RoomTooltip_chevron {
 | 
				
			||||||
};
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    left: -9px;
 | 
				
			||||||
 | 
					    top: 8px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -29,7 +29,9 @@ limitations under the License.
 | 
				
			|||||||
.mx_LeftPanel_hideButton {
 | 
					.mx_LeftPanel_hideButton {
 | 
				
			||||||
    position: absolute;
 | 
					    position: absolute;
 | 
				
			||||||
    top: 10px;
 | 
					    top: 10px;
 | 
				
			||||||
    right: 10px;
 | 
					    right: 0px;
 | 
				
			||||||
 | 
					    padding: 8px;
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_LeftPanel .mx_RoomList {
 | 
					.mx_LeftPanel .mx_RoomList {
 | 
				
			||||||
@ -39,7 +41,7 @@ limitations under the License.
 | 
				
			|||||||
    -webkit-order: 1;
 | 
					    -webkit-order: 1;
 | 
				
			||||||
    order: 1;
 | 
					    order: 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    overflow-y: scroll;
 | 
					    overflow-y: auto;
 | 
				
			||||||
    -webkit-flex: 1 1 0;
 | 
					    -webkit-flex: 1 1 0;
 | 
				
			||||||
    flex: 1 1 0;
 | 
					    flex: 1 1 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -61,10 +63,6 @@ limitations under the License.
 | 
				
			|||||||
    color: #378bb4;
 | 
					    color: #378bb4;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_LeftPanel .mx_BottomLeftMenu .mx_RoomTile_avatar {
 | 
					 | 
				
			||||||
    padding-left: 14px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.mx_LeftPanel .mx_BottomLeftMenu .mx_BottomLeftMenu_options {
 | 
					.mx_LeftPanel .mx_BottomLeftMenu .mx_BottomLeftMenu_options {
 | 
				
			||||||
    margin-top: 12px;
 | 
					    margin-top: 12px;
 | 
				
			||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
 | 
				
			|||||||
@ -57,7 +57,7 @@ limitations under the License.
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_RoomDirectory_tableWrapper {
 | 
					.mx_RoomDirectory_tableWrapper {
 | 
				
			||||||
    overflow-y: scroll;
 | 
					    overflow-y: auto;
 | 
				
			||||||
    -webkit-flex: 1 1 0;    
 | 
					    -webkit-flex: 1 1 0;    
 | 
				
			||||||
    flex: 1 1 0;
 | 
					    flex: 1 1 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -27,4 +27,5 @@ limitations under the License.
 | 
				
			|||||||
.mx_RoomList h2 {
 | 
					.mx_RoomList h2 {
 | 
				
			||||||
    padding-left: 16px;
 | 
					    padding-left: 16px;
 | 
				
			||||||
    padding-right: 16px;
 | 
					    padding-right: 16px;
 | 
				
			||||||
 | 
					    padding-bottom: 10px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -106,10 +106,8 @@ limitations under the License.
 | 
				
			|||||||
    flex: 1 1 0;
 | 
					    flex: 1 1 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
    margin-top: 18px;
 | 
					 | 
				
			||||||
    margin-bottom: 18px;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    overflow-y: scroll;
 | 
					    overflow-y: auto;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_RoomView_messageListWrapper {
 | 
					.mx_RoomView_messageListWrapper {
 | 
				
			||||||
@ -123,6 +121,10 @@ limitations under the License.
 | 
				
			|||||||
    padding: 0px;
 | 
					    padding: 0px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_RoomView_MessageList li {
 | 
				
			||||||
 | 
					    clear: both;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_RoomView_MessageList h2 {
 | 
					.mx_RoomView_MessageList h2 {
 | 
				
			||||||
    clear: both;
 | 
					    clear: both;
 | 
				
			||||||
    margin-top: 32px;
 | 
					    margin-top: 32px;
 | 
				
			||||||
@ -210,13 +212,37 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.mx_RoomView_uploadProgressOuter {
 | 
					.mx_RoomView_uploadProgressOuter {
 | 
				
			||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
    background-color: black;
 | 
					    background-color: rgba(169, 219, 244, 0.5);
 | 
				
			||||||
    height: 5px;
 | 
					    height: 4px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_RoomView_uploadProgressInner {
 | 
					.mx_RoomView_uploadProgressInner {
 | 
				
			||||||
    background-color: blue;
 | 
					    background-color: #80cef4;
 | 
				
			||||||
    height: 5px;
 | 
					    height: 4px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_RoomView_uploadFilename {
 | 
				
			||||||
 | 
					    margin-top: 15px;
 | 
				
			||||||
 | 
					    margin-left: 56px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_RoomView_uploadIcon {
 | 
				
			||||||
 | 
					    float: left;
 | 
				
			||||||
 | 
					    margin-top: 6px;
 | 
				
			||||||
 | 
					    margin-left: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_RoomView_uploadCancel {
 | 
				
			||||||
 | 
					    float: right;
 | 
				
			||||||
 | 
					    margin-top: 6px;
 | 
				
			||||||
 | 
					    margin-right: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_RoomView_uploadBytes {
 | 
				
			||||||
 | 
					    float: right;    
 | 
				
			||||||
 | 
					    opacity: 0.5;
 | 
				
			||||||
 | 
					    margin-top: 15px;
 | 
				
			||||||
 | 
					    margin-right: 10px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_RoomView_ongoingConfCallNotification {
 | 
					.mx_RoomView_ongoingConfCallNotification {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								src/skins/vector/css/organisms/ViewSource.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					.mx_ViewSource pre {
 | 
				
			||||||
 | 
					    text-align: left;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -73,6 +73,11 @@ limitations under the License.
 | 
				
			|||||||
    flex: 0 0 230px;
 | 
					    flex: 0 0 230px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_MatrixChat .mx_LeftPanel.collapsed {
 | 
				
			||||||
 | 
					    -webkit-flex: 0 0 60px;
 | 
				
			||||||
 | 
					    flex: 0 0 60px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mx_MatrixChat .mx_MatrixChat_middlePanel {
 | 
					.mx_MatrixChat .mx_MatrixChat_middlePanel {
 | 
				
			||||||
    -webkit-box-ordinal-group: 2;
 | 
					    -webkit-box-ordinal-group: 2;
 | 
				
			||||||
    -moz-box-ordinal-group: 2;
 | 
					    -moz-box-ordinal-group: 2;
 | 
				
			||||||
@ -83,7 +88,9 @@ limitations under the License.
 | 
				
			|||||||
    padding-left: 12px;
 | 
					    padding-left: 12px;
 | 
				
			||||||
    padding-right: 12px;
 | 
					    padding-right: 12px;
 | 
				
			||||||
    background-color: #f3f8fa;
 | 
					    background-color: #f3f8fa;
 | 
				
			||||||
    width: 100%;
 | 
					
 | 
				
			||||||
 | 
					    -webkit-flex: 1;
 | 
				
			||||||
 | 
					    flex: 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* XXX: Hack: apparently if you try to nest a flex-box
 | 
					    /* XXX: Hack: apparently if you try to nest a flex-box
 | 
				
			||||||
     * within a non-flex-box within a flex-box, the height
 | 
					     * within a non-flex-box within a flex-box, the height
 | 
				
			||||||
@ -111,3 +118,8 @@ limitations under the License.
 | 
				
			|||||||
    -webkit-flex: 0 0 230px;
 | 
					    -webkit-flex: 0 0 230px;
 | 
				
			||||||
    flex: 0 0 230px;
 | 
					    flex: 0 0 230px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mx_MatrixChat .mx_RightPanel.collapsed {
 | 
				
			||||||
 | 
					    -webkit-flex: 0 0 72px;
 | 
				
			||||||
 | 
					    flex: 0 0 72px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								src/skins/vector/img/50e2c2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 146 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/skins/vector/img/80cef4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 146 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/skins/vector/img/cancel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 999 B After Width: | Height: | Size: 15 KiB  | 
| 
		 Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 14 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/skins/vector/img/f4c371.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 146 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/skins/vector/img/fileicon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 415 B After Width: | Height: | Size: 1.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/skins/vector/img/menu.png
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 122 B  | 
| 
		 Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/skins/vector/img/spinner.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 34 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/skins/vector/img/zoom.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.3 KiB  | 
@ -23,6 +23,9 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var skin = {};
 | 
					var skin = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					skin['atoms.create_room.CreateRoomButton'] = require('./views/atoms/create_room/CreateRoomButton');
 | 
				
			||||||
 | 
					skin['atoms.create_room.Presets'] = require('./views/atoms/create_room/Presets');
 | 
				
			||||||
 | 
					skin['atoms.create_room.RoomAlias'] = require('./views/atoms/create_room/RoomAlias');
 | 
				
			||||||
skin['atoms.EditableText'] = require('./views/atoms/EditableText');
 | 
					skin['atoms.EditableText'] = require('./views/atoms/EditableText');
 | 
				
			||||||
skin['atoms.EnableNotificationsButton'] = require('./views/atoms/EnableNotificationsButton');
 | 
					skin['atoms.EnableNotificationsButton'] = require('./views/atoms/EnableNotificationsButton');
 | 
				
			||||||
skin['atoms.ImageView'] = require('./views/atoms/ImageView');
 | 
					skin['atoms.ImageView'] = require('./views/atoms/ImageView');
 | 
				
			||||||
@ -30,32 +33,34 @@ skin['atoms.LogoutButton'] = require('./views/atoms/LogoutButton');
 | 
				
			|||||||
skin['atoms.MemberAvatar'] = require('./views/atoms/MemberAvatar');
 | 
					skin['atoms.MemberAvatar'] = require('./views/atoms/MemberAvatar');
 | 
				
			||||||
skin['atoms.MessageTimestamp'] = require('./views/atoms/MessageTimestamp');
 | 
					skin['atoms.MessageTimestamp'] = require('./views/atoms/MessageTimestamp');
 | 
				
			||||||
skin['atoms.RoomAvatar'] = require('./views/atoms/RoomAvatar');
 | 
					skin['atoms.RoomAvatar'] = require('./views/atoms/RoomAvatar');
 | 
				
			||||||
skin['atoms.create_room.CreateRoomButton'] = require('./views/atoms/create_room/CreateRoomButton');
 | 
					 | 
				
			||||||
skin['atoms.create_room.Presets'] = require('./views/atoms/create_room/Presets');
 | 
					 | 
				
			||||||
skin['atoms.create_room.RoomAlias'] = require('./views/atoms/create_room/RoomAlias');
 | 
					 | 
				
			||||||
skin['atoms.voip.VideoFeed'] = require('./views/atoms/voip/VideoFeed');
 | 
					skin['atoms.voip.VideoFeed'] = require('./views/atoms/voip/VideoFeed');
 | 
				
			||||||
skin['molecules.BottomLeftMenu'] = require('./views/molecules/BottomLeftMenu');
 | 
					skin['molecules.BottomLeftMenu'] = require('./views/molecules/BottomLeftMenu');
 | 
				
			||||||
 | 
					skin['molecules.BottomLeftMenuTile'] = require('./views/molecules/BottomLeftMenuTile');
 | 
				
			||||||
skin['molecules.ChangeAvatar'] = require('./views/molecules/ChangeAvatar');
 | 
					skin['molecules.ChangeAvatar'] = require('./views/molecules/ChangeAvatar');
 | 
				
			||||||
 | 
					skin['molecules.ChangeDisplayName'] = require('./views/molecules/ChangeDisplayName');
 | 
				
			||||||
skin['molecules.ChangePassword'] = require('./views/molecules/ChangePassword');
 | 
					skin['molecules.ChangePassword'] = require('./views/molecules/ChangePassword');
 | 
				
			||||||
skin['molecules.DateSeparator'] = require('./views/molecules/DateSeparator');
 | 
					skin['molecules.DateSeparator'] = require('./views/molecules/DateSeparator');
 | 
				
			||||||
skin['molecules.EventAsTextTile'] = require('./views/molecules/EventAsTextTile');
 | 
					skin['molecules.EventAsTextTile'] = require('./views/molecules/EventAsTextTile');
 | 
				
			||||||
 | 
					skin['molecules.EventTile'] = require('./views/molecules/EventTile');
 | 
				
			||||||
 | 
					skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar');
 | 
				
			||||||
 | 
					skin['molecules.MemberInfo'] = require('./views/molecules/MemberInfo');
 | 
				
			||||||
 | 
					skin['molecules.MemberTile'] = require('./views/molecules/MemberTile');
 | 
				
			||||||
skin['molecules.MEmoteTile'] = require('./views/molecules/MEmoteTile');
 | 
					skin['molecules.MEmoteTile'] = require('./views/molecules/MEmoteTile');
 | 
				
			||||||
 | 
					skin['molecules.MessageComposer'] = require('./views/molecules/MessageComposer');
 | 
				
			||||||
 | 
					skin['molecules.MessageContextMenu'] = require('./views/molecules/MessageContextMenu');
 | 
				
			||||||
 | 
					skin['molecules.MessageTile'] = require('./views/molecules/MessageTile');
 | 
				
			||||||
skin['molecules.MFileTile'] = require('./views/molecules/MFileTile');
 | 
					skin['molecules.MFileTile'] = require('./views/molecules/MFileTile');
 | 
				
			||||||
skin['molecules.MImageTile'] = require('./views/molecules/MImageTile');
 | 
					skin['molecules.MImageTile'] = require('./views/molecules/MImageTile');
 | 
				
			||||||
skin['molecules.MNoticeTile'] = require('./views/molecules/MNoticeTile');
 | 
					skin['molecules.MNoticeTile'] = require('./views/molecules/MNoticeTile');
 | 
				
			||||||
skin['molecules.MRoomMemberTile'] = require('./views/molecules/MRoomMemberTile');
 | 
					skin['molecules.MRoomMemberTile'] = require('./views/molecules/MRoomMemberTile');
 | 
				
			||||||
skin['molecules.MTextTile'] = require('./views/molecules/MTextTile');
 | 
					skin['molecules.MTextTile'] = require('./views/molecules/MTextTile');
 | 
				
			||||||
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.MessageTile'] = require('./views/molecules/MessageTile');
 | 
					 | 
				
			||||||
skin['molecules.ProgressBar'] = require('./views/molecules/ProgressBar');
 | 
					skin['molecules.ProgressBar'] = require('./views/molecules/ProgressBar');
 | 
				
			||||||
skin['molecules.RoomCreate'] = require('./views/molecules/RoomCreate');
 | 
					skin['molecules.RoomCreate'] = require('./views/molecules/RoomCreate');
 | 
				
			||||||
skin['molecules.RoomDropTarget'] = require('./views/molecules/RoomDropTarget');
 | 
					skin['molecules.RoomDropTarget'] = require('./views/molecules/RoomDropTarget');
 | 
				
			||||||
skin['molecules.RoomHeader'] = require('./views/molecules/RoomHeader');
 | 
					skin['molecules.RoomHeader'] = require('./views/molecules/RoomHeader');
 | 
				
			||||||
skin['molecules.RoomSettings'] = require('./views/molecules/RoomSettings');
 | 
					skin['molecules.RoomSettings'] = require('./views/molecules/RoomSettings');
 | 
				
			||||||
skin['molecules.RoomTile'] = require('./views/molecules/RoomTile');
 | 
					skin['molecules.RoomTile'] = require('./views/molecules/RoomTile');
 | 
				
			||||||
 | 
					skin['molecules.RoomTooltip'] = require('./views/molecules/RoomTooltip');
 | 
				
			||||||
skin['molecules.SenderProfile'] = require('./views/molecules/SenderProfile');
 | 
					skin['molecules.SenderProfile'] = require('./views/molecules/SenderProfile');
 | 
				
			||||||
skin['molecules.ServerConfig'] = require('./views/molecules/ServerConfig');
 | 
					skin['molecules.ServerConfig'] = require('./views/molecules/ServerConfig');
 | 
				
			||||||
skin['molecules.UnknownMessageTile'] = require('./views/molecules/UnknownMessageTile');
 | 
					skin['molecules.UnknownMessageTile'] = require('./views/molecules/UnknownMessageTile');
 | 
				
			||||||
@ -63,6 +68,7 @@ skin['molecules.UserSelector'] = require('./views/molecules/UserSelector');
 | 
				
			|||||||
skin['molecules.voip.CallView'] = require('./views/molecules/voip/CallView');
 | 
					skin['molecules.voip.CallView'] = require('./views/molecules/voip/CallView');
 | 
				
			||||||
skin['molecules.voip.IncomingCallBox'] = require('./views/molecules/voip/IncomingCallBox');
 | 
					skin['molecules.voip.IncomingCallBox'] = require('./views/molecules/voip/IncomingCallBox');
 | 
				
			||||||
skin['molecules.voip.VideoView'] = require('./views/molecules/voip/VideoView');
 | 
					skin['molecules.voip.VideoView'] = require('./views/molecules/voip/VideoView');
 | 
				
			||||||
 | 
					skin['organisms.CasLogin'] = require('./views/organisms/CasLogin');
 | 
				
			||||||
skin['organisms.CreateRoom'] = require('./views/organisms/CreateRoom');
 | 
					skin['organisms.CreateRoom'] = require('./views/organisms/CreateRoom');
 | 
				
			||||||
skin['organisms.ErrorDialog'] = require('./views/organisms/ErrorDialog');
 | 
					skin['organisms.ErrorDialog'] = require('./views/organisms/ErrorDialog');
 | 
				
			||||||
skin['organisms.LeftPanel'] = require('./views/organisms/LeftPanel');
 | 
					skin['organisms.LeftPanel'] = require('./views/organisms/LeftPanel');
 | 
				
			||||||
@ -75,6 +81,7 @@ skin['organisms.RoomDirectory'] = require('./views/organisms/RoomDirectory');
 | 
				
			|||||||
skin['organisms.RoomList'] = require('./views/organisms/RoomList');
 | 
					skin['organisms.RoomList'] = require('./views/organisms/RoomList');
 | 
				
			||||||
skin['organisms.RoomView'] = require('./views/organisms/RoomView');
 | 
					skin['organisms.RoomView'] = require('./views/organisms/RoomView');
 | 
				
			||||||
skin['organisms.UserSettings'] = require('./views/organisms/UserSettings');
 | 
					skin['organisms.UserSettings'] = require('./views/organisms/UserSettings');
 | 
				
			||||||
 | 
					skin['organisms.ViewSource'] = require('./views/organisms/ViewSource');
 | 
				
			||||||
skin['pages.MatrixChat'] = require('./views/pages/MatrixChat');
 | 
					skin['pages.MatrixChat'] = require('./views/pages/MatrixChat');
 | 
				
			||||||
skin['templates.Login'] = require('./views/templates/Login');
 | 
					skin['templates.Login'] = require('./views/templates/Login');
 | 
				
			||||||
skin['templates.Register'] = require('./views/templates/Register');
 | 
					skin['templates.Register'] = require('./views/templates/Register');
 | 
				
			||||||
 | 
				
			|||||||
@ -18,11 +18,8 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ImageViewController = require('../../../../controllers/atoms/ImageView')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'ImageView',
 | 
					    displayName: 'ImageView',
 | 
				
			||||||
    mixins: [ImageViewController],
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // XXX: keyboard shortcuts for managing dialogs should be done by the modal dialog base class omehow, surely...
 | 
					    // XXX: keyboard shortcuts for managing dialogs should be done by the modal dialog base class omehow, surely...
 | 
				
			||||||
    componentDidMount: function() {
 | 
					    componentDidMount: function() {
 | 
				
			||||||
 | 
				
			|||||||
@ -18,17 +18,39 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var MessageTimestampController = require('matrix-react-sdk/lib/controllers/atoms/MessageTimestamp')
 | 
					var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
 | 
				
			||||||
 | 
					var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'MessageTimestamp',
 | 
					    displayName: 'MessageTimestamp',
 | 
				
			||||||
    mixins: [MessageTimestampController],
 | 
					
 | 
				
			||||||
 | 
					    formatDate: function(date) {
 | 
				
			||||||
 | 
					        // date.toLocaleTimeString is completely system dependent.
 | 
				
			||||||
 | 
					        // just go 24h for now
 | 
				
			||||||
 | 
					        function pad(n) {
 | 
				
			||||||
 | 
					            return (n < 10 ? '0' : '') + n;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var now = new Date();
 | 
				
			||||||
 | 
					        if (date.toDateString() === now.toDateString()) {
 | 
				
			||||||
 | 
					            return pad(date.getHours()) + ':' + pad(date.getMinutes());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (now.getTime() - date.getTime() < 6 * 24 * 60 * 60 * 1000) {
 | 
				
			||||||
 | 
					            return days[date.getDay()] + " " + pad(date.getHours()) + ':' + pad(date.getMinutes());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (now.getFullYear() === date.getFullYear()) {
 | 
				
			||||||
 | 
					            return days[date.getDay()] + ", " + months[date.getMonth()] + " " + (date.getDay()+1) + " " + pad(date.getHours()) + ':' + pad(date.getMinutes());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            return days[date.getDay()] + ", " + months[date.getMonth()] + " " + (date.getDay()+1) + " " + date.getFullYear() + " " + pad(date.getHours()) + ':' + pad(date.getMinutes());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var date = new Date(this.props.ts);
 | 
					        var date = new Date(this.props.ts);
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <span className="mx_MessageTimestamp">
 | 
					            <span className="mx_MessageTimestamp">
 | 
				
			||||||
                {date.toLocaleTimeString()}
 | 
					                { this.formatDate(date) }
 | 
				
			||||||
            </span>
 | 
					            </span>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
				
			|||||||
@ -24,10 +24,31 @@ module.exports = React.createClass({
 | 
				
			|||||||
    displayName: 'RoomAvatar',
 | 
					    displayName: 'RoomAvatar',
 | 
				
			||||||
    mixins: [RoomAvatarController],
 | 
					    mixins: [RoomAvatarController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getUrlList: function() {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            this.roomAvatarUrl(),
 | 
				
			||||||
 | 
					            this.getOneToOneAvatar(),
 | 
				
			||||||
 | 
					            this.getFallbackAvatar()
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getFallbackAvatar: function() {
 | 
				
			||||||
 | 
					        var images = [ '80cef4', '50e2c2', 'f4c371' ];
 | 
				
			||||||
 | 
					        var total = 0;
 | 
				
			||||||
 | 
					        for (var i = 0; i < this.props.room.roomId.length; ++i) {
 | 
				
			||||||
 | 
					            total += this.props.room.roomId.charCodeAt(i);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return 'img/' + images[total % images.length] + '.png';
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var style = {
 | 
				
			||||||
 | 
					            maxWidth: this.props.width,
 | 
				
			||||||
 | 
					            maxHeight: this.props.height,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <img className="mx_RoomAvatar" src={this.state.imageUrl} onError={this.onError}
 | 
					            <img className="mx_RoomAvatar" src={this.state.imageUrl} onError={this.onError}
 | 
				
			||||||
                width={this.props.width} height={this.props.height}
 | 
					                style={style}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										34
									
								
								src/skins/vector/views/atoms/Spinner.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
					    displayName: 'Spinner',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var w = this.props.w || 32;
 | 
				
			||||||
 | 
					        var h = this.props.h || 32;
 | 
				
			||||||
 | 
					        var imgClass = this.props.imgClassName || "";
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                <img src="img/spinner.gif" width={w} height={h} className={imgClass}/>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -18,11 +18,8 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var VideoFeedController = require('matrix-react-sdk/lib/controllers/atoms/voip/VideoFeed')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'VideoFeed',
 | 
					    displayName: 'VideoFeed',
 | 
				
			||||||
    mixins: [VideoFeedController],
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ limitations under the License.
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
var dis = require('matrix-react-sdk/lib/dispatcher');
 | 
					var dis = require('matrix-react-sdk/lib/dispatcher');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
@ -35,28 +35,24 @@ module.exports = React.createClass({
 | 
				
			|||||||
        dis.dispatch({action: 'view_create_room'});
 | 
					        dis.dispatch({action: 'view_create_room'});
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getLabel: function(name) {
 | 
				
			||||||
 | 
					        if (!this.props.collapsed) {
 | 
				
			||||||
 | 
					            return <div className="mx_RoomTile_name">{name}</div>
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (this.state.hover) {
 | 
				
			||||||
 | 
					            var RoomTooltip = sdk.getComponent("molecules.RoomTooltip");
 | 
				
			||||||
 | 
					            return <RoomTooltip name={name}/>;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var BottomLeftMenuTile = sdk.getComponent('molecules.BottomLeftMenuTile');
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className="mx_BottomLeftMenu">
 | 
					            <div className="mx_BottomLeftMenu">
 | 
				
			||||||
                <div className="mx_BottomLeftMenu_options">
 | 
					                <div className="mx_BottomLeftMenu_options">
 | 
				
			||||||
                    <div className="mx_RoomTile" onClick={this.onCreateRoomClick}>
 | 
					                    <BottomLeftMenuTile collapsed={ this.props.collapsed } img="img/create-big.png" label="Create new room" onClick={ this.onCreateRoomClick }/>
 | 
				
			||||||
                        <div className="mx_RoomTile_avatar">
 | 
					                    <BottomLeftMenuTile collapsed={ this.props.collapsed } img="img/directory-big.png" label="Directory" onClick={ this.onRoomDirectoryClick }/>
 | 
				
			||||||
                            <img src="img/create-big.png" alt="Create new room" title="Create new room" width="42" height="42"/>
 | 
					                    <BottomLeftMenuTile collapsed={ this.props.collapsed } img="img/settings-big.png" label="Settings" onClick={ this.onSettingsClick }/>
 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        <div className="mx_RoomTile_name">Create new room</div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div className="mx_RoomTile" onClick={this.onRoomDirectoryClick}>
 | 
					 | 
				
			||||||
                        <div className="mx_RoomTile_avatar">
 | 
					 | 
				
			||||||
                            <img src="img/directory-big.png" alt="Directory" title="Directory" width="42" height="42"/>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        <div className="mx_RoomTile_name">Directory</div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div className="mx_RoomTile" onClick={this.onSettingsClick}>
 | 
					 | 
				
			||||||
                        <div className="mx_RoomTile_avatar">
 | 
					 | 
				
			||||||
                            <img src="img/settings-big.png" alt="Settings" title="Settings" width="42" height="42"/>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        <div className="mx_RoomTile_name">Settings</div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										57
									
								
								src/skins/vector/views/molecules/BottomLeftMenuTile.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
					    displayName: 'BottomLeftMenuTile',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getInitialState: function() {
 | 
				
			||||||
 | 
					        return( { hover : false });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onMouseEnter: function() {
 | 
				
			||||||
 | 
					        this.setState( { hover : true });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onMouseLeave: function() {
 | 
				
			||||||
 | 
					        this.setState( { hover : false });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var label;
 | 
				
			||||||
 | 
					        if (!this.props.collapsed) {
 | 
				
			||||||
 | 
					            label = <div className="mx_RoomTile_name">{ this.props.label }</div>;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (this.state.hover) {
 | 
				
			||||||
 | 
					            var RoomTooltip = sdk.getComponent("molecules.RoomTooltip");
 | 
				
			||||||
 | 
					            label = <RoomTooltip bottom={ true } label={ this.props.label }/>;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div className="mx_RoomTile" onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} onClick={this.props.onClick}>
 | 
				
			||||||
 | 
					                <div className="mx_RoomTile_avatar">
 | 
				
			||||||
 | 
					                    <img src={ this.props.img } width="36" height="36"/>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                { label }
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -18,6 +18,7 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
var ChangeAvatarController = require('matrix-react-sdk/lib/controllers/molecules/ChangeAvatar')
 | 
					var ChangeAvatarController = require('matrix-react-sdk/lib/controllers/molecules/ChangeAvatar')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var Loader = require("react-loader");
 | 
					var Loader = require("react-loader");
 | 
				
			||||||
@ -28,6 +29,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
    mixins: [ChangeAvatarController],
 | 
					    mixins: [ChangeAvatarController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onFileSelected: function(ev) {
 | 
					    onFileSelected: function(ev) {
 | 
				
			||||||
 | 
					        this.avatarSet = true;
 | 
				
			||||||
        this.setAvatarFromFile(ev.target.files[0]);
 | 
					        this.setAvatarFromFile(ev.target.files[0]);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -38,22 +40,33 @@ module.exports = React.createClass({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var RoomAvatar = sdk.getComponent('atoms.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 = <RoomAvatar room={this.props.room} width='320' height='240' resizeMethod='scale' />;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            var style = {
 | 
				
			||||||
 | 
					                maxWidth: 320,
 | 
				
			||||||
 | 
					                maxHeight: 240,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            avatarImg = <img src={this.state.avatarUrl} style={style} />;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        switch (this.state.phase) {
 | 
					        switch (this.state.phase) {
 | 
				
			||||||
            case this.Phases.Display:
 | 
					            case this.Phases.Display:
 | 
				
			||||||
            case this.Phases.Error:
 | 
					            case this.Phases.Error:
 | 
				
			||||||
                return (
 | 
					                return (
 | 
				
			||||||
                    <div>
 | 
					                    <div>
 | 
				
			||||||
                        <div className="mx_Dialog_content">
 | 
					                        <div className="mx_Dialog_content">
 | 
				
			||||||
                            <img src={this.state.avatarUrl}/>
 | 
					                            {avatarImg}
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div className="mx_Dialog_content">
 | 
					                        <div className="mx_Dialog_content">
 | 
				
			||||||
                            Upload new:
 | 
					                            Upload new:
 | 
				
			||||||
                            <input type="file" onChange={this.onFileSelected}/>
 | 
					                            <input type="file" onChange={this.onFileSelected}/>
 | 
				
			||||||
                            {this.state.errorText}
 | 
					                            {this.state.errorText}
 | 
				
			||||||
                        </div>    
 | 
					                        </div>    
 | 
				
			||||||
                        <div className="mx_Dialog_buttons">
 | 
					 | 
				
			||||||
                            <button onClick={this.props.onFinished}>Cancel</button>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            case this.Phases.Uploading:
 | 
					            case this.Phases.Uploading:
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										56
									
								
								src/skins/vector/views/molecules/ChangeDisplayName.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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");
 | 
				
			||||||
 | 
					var Loader = require("react-loader");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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) {
 | 
				
			||||||
 | 
					            return (
 | 
				
			||||||
 | 
					                <Loader />
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        } else if (this.state.errorString) {
 | 
				
			||||||
 | 
					            return (
 | 
				
			||||||
 | 
					                <div className="error">{this.state.errorString}</div>
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            var EditableText = sdk.getComponent('atoms.EditableText');
 | 
				
			||||||
 | 
					            return (
 | 
				
			||||||
 | 
					                <EditableText ref="displayname_edit" initialValue={this.state.displayName} label="Click to set display name." onValueChanged={this.onValueChanged}/>
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -18,33 +18,24 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var EventAsTextTileController = require('matrix-react-sdk/lib/controllers/molecules/EventAsTextTile')
 | 
					 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					 | 
				
			||||||
var TextForEvent = require('matrix-react-sdk/lib/TextForEvent');
 | 
					var TextForEvent = require('matrix-react-sdk/lib/TextForEvent');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'EventAsTextTile',
 | 
					    displayName: 'EventAsTextTile',
 | 
				
			||||||
    mixins: [EventAsTextTileController],
 | 
					
 | 
				
			||||||
 | 
					    statics: {
 | 
				
			||||||
 | 
					        needsSenderProfile: function() {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var MessageTimestamp = sdk.getComponent('atoms.MessageTimestamp');
 | 
					 | 
				
			||||||
        var MemberAvatar = sdk.getComponent('atoms.MemberAvatar');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var text = TextForEvent.textForEvent(this.props.mxEvent);
 | 
					        var text = TextForEvent.textForEvent(this.props.mxEvent);
 | 
				
			||||||
        if (text == null || text.length == 0) return null;
 | 
					        if (text == null || text.length == 0) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var timestamp = this.props.last ? <MessageTimestamp ts={this.props.mxEvent.getTs()} /> : null;
 | 
					 | 
				
			||||||
        var avatar = this.props.mxEvent.sender ? <MemberAvatar member={this.props.mxEvent.sender} /> : null;
 | 
					 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className="mx_MessageTile mx_MessageTile_notice">
 | 
					            <div className="mx_EventAsTextTile">
 | 
				
			||||||
                <div className="mx_MessageTile_avatar">
 | 
					 | 
				
			||||||
                    { avatar }
 | 
					 | 
				
			||||||
                </div>            
 | 
					 | 
				
			||||||
                { timestamp }
 | 
					 | 
				
			||||||
                <span className="mx_SenderProfile"></span>
 | 
					 | 
				
			||||||
                <span className="mx_MessageTile_content">
 | 
					 | 
				
			||||||
                {TextForEvent.textForEvent(this.props.mxEvent)}
 | 
					                {TextForEvent.textForEvent(this.props.mxEvent)}
 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										131
									
								
								src/skins/vector/views/molecules/EventTile.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 classNames = require("classnames");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var EventTileController = require('matrix-react-sdk/lib/controllers/molecules/EventTile')
 | 
				
			||||||
 | 
					var ContextualMenu = require('../../../../ContextualMenu');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.topic'  : 'molecules.EventAsTextTile',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
					    displayName: 'EventTile',
 | 
				
			||||||
 | 
					    mixins: [EventTileController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    statics: {
 | 
				
			||||||
 | 
					        supportsEventType: function(et) {
 | 
				
			||||||
 | 
					            return eventTileTypes[et] !== undefined;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getInitialState: function() {
 | 
				
			||||||
 | 
					        return {menu: 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});
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var MessageTimestamp = sdk.getComponent('atoms.MessageTimestamp');
 | 
				
			||||||
 | 
					        var SenderProfile = sdk.getComponent('molecules.SenderProfile');
 | 
				
			||||||
 | 
					        var MemberAvatar = sdk.getComponent('atoms.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) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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,
 | 
				
			||||||
 | 
					            menu: this.state.menu
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        var timestamp = <MessageTimestamp ts={this.props.mxEvent.getTs()} />
 | 
				
			||||||
 | 
					        var editButton = (
 | 
				
			||||||
 | 
					            <input
 | 
				
			||||||
 | 
					                type="image" src="img/edit.png" alt="Edit"
 | 
				
			||||||
 | 
					                className="mx_EventTile_editButton" onClick={this.onEditClicked}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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 avatar, sender;
 | 
				
			||||||
 | 
					        if (!this.props.continuation) {
 | 
				
			||||||
 | 
					            if (this.props.mxEvent.sender) {
 | 
				
			||||||
 | 
					                avatar = (
 | 
				
			||||||
 | 
					                    <div className="mx_EventTile_avatar">
 | 
				
			||||||
 | 
					                        <MemberAvatar member={this.props.mxEvent.sender} />
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (EventTileType.needsSenderProfile()) {
 | 
				
			||||||
 | 
					                sender = <SenderProfile mxEvent={this.props.mxEvent} aux={aux} />;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div className={classes}>
 | 
				
			||||||
 | 
					                { avatar }
 | 
				
			||||||
 | 
					                { sender }
 | 
				
			||||||
 | 
					                <div>
 | 
				
			||||||
 | 
					                    { timestamp }
 | 
				
			||||||
 | 
					                    { editButton }
 | 
				
			||||||
 | 
					                    <EventTileType mxEvent={this.props.mxEvent} />
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -19,15 +19,12 @@ limitations under the License.
 | 
				
			|||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
var filesize = require('filesize');
 | 
					var filesize = require('filesize');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var MImageTileController = require('matrix-react-sdk/lib/controllers/molecules/MImageTile')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
					var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
				
			||||||
var Modal = require('matrix-react-sdk/lib/Modal');
 | 
					var Modal = require('matrix-react-sdk/lib/Modal');
 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'MImageTile',
 | 
					    displayName: 'MImageTile',
 | 
				
			||||||
    mixins: [MImageTileController],
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    thumbHeight: function(fullWidth, fullHeight, thumbWidth, thumbHeight) {
 | 
					    thumbHeight: function(fullWidth, fullHeight, thumbWidth, thumbHeight) {
 | 
				
			||||||
        if (!fullWidth || !fullHeight) {
 | 
					        if (!fullWidth || !fullHeight) {
 | 
				
			||||||
 | 
				
			|||||||
@ -18,14 +18,11 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var MRoomMemberTileController = require('matrix-react-sdk/lib/controllers/molecules/MRoomMemberTile')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
var TextForEvent = require('matrix-react-sdk/lib/TextForEvent');
 | 
					var TextForEvent = require('matrix-react-sdk/lib/TextForEvent');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'MRoomMemberTile',
 | 
					    displayName: 'MRoomMemberTile',
 | 
				
			||||||
    mixins: [MRoomMemberTileController],
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getMemberEventText: function() {
 | 
					    getMemberEventText: function() {
 | 
				
			||||||
        return TextForEvent.textForEvent(this.props.mxEvent);
 | 
					        return TextForEvent.textForEvent(this.props.mxEvent);
 | 
				
			||||||
 | 
				
			|||||||
@ -20,11 +20,8 @@ var React = require('react');
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var MatrixToolbarController = require('matrix-react-sdk/lib/controllers/molecules/MatrixToolbar')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'MatrixToolbar',
 | 
					    displayName: 'MatrixToolbar',
 | 
				
			||||||
    mixins: [MatrixToolbarController],
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hideToolbar: function() {
 | 
					    hideToolbar: function() {
 | 
				
			||||||
        var Notifier = sdk.getComponent('organisms.Notifier');
 | 
					        var Notifier = sdk.getComponent('organisms.Notifier');
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,7 @@ limitations under the License.
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					var Loader = require("../atoms/Spinner");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
					var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
				
			||||||
var MemberInfoController = require('matrix-react-sdk/lib/controllers/molecules/MemberInfo')
 | 
					var MemberInfoController = require('matrix-react-sdk/lib/controllers/molecules/MemberInfo')
 | 
				
			||||||
@ -26,7 +27,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
    mixins: [MemberInfoController],
 | 
					    mixins: [MemberInfoController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var interactButton, kickButton, banButton, muteButton, giveModButton;
 | 
					        var interactButton, kickButton, banButton, muteButton, giveModButton, spinner;
 | 
				
			||||||
        if (this.props.member.userId === MatrixClientPeg.get().credentials.userId) {
 | 
					        if (this.props.member.userId === MatrixClientPeg.get().credentials.userId) {
 | 
				
			||||||
            interactButton = <div className="mx_ContextualMenu_field" onClick={this.onLeaveClick}>Leave room</div>;
 | 
					            interactButton = <div className="mx_ContextualMenu_field" onClick={this.onLeaveClick}>Leave room</div>;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -34,6 +35,10 @@ module.exports = React.createClass({
 | 
				
			|||||||
            interactButton = <div className="mx_ContextualMenu_field" onClick={this.onChatClick}>Start chat</div>;
 | 
					            interactButton = <div className="mx_ContextualMenu_field" onClick={this.onChatClick}>Start chat</div>;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.state.creatingRoom) {
 | 
				
			||||||
 | 
					            spinner = <Loader imgClassName="mx_ContextualMenu_spinner"/>;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.state.can.kick) {
 | 
					        if (this.state.can.kick) {
 | 
				
			||||||
            kickButton = <div className="mx_ContextualMenu_field" onClick={this.onKick}>
 | 
					            kickButton = <div className="mx_ContextualMenu_field" onClick={this.onKick}>
 | 
				
			||||||
                Kick
 | 
					                Kick
 | 
				
			||||||
@ -64,6 +69,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
                {kickButton}
 | 
					                {kickButton}
 | 
				
			||||||
                {banButton}
 | 
					                {banButton}
 | 
				
			||||||
                {giveModButton}
 | 
					                {giveModButton}
 | 
				
			||||||
 | 
					                {spinner}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -31,6 +31,24 @@ module.exports = React.createClass({
 | 
				
			|||||||
    displayName: 'MemberTile',
 | 
					    displayName: 'MemberTile',
 | 
				
			||||||
    mixins: [MemberTileController],
 | 
					    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) {
 | 
					    mouseEnter: function(e) {
 | 
				
			||||||
        this.setState({ 'hover': true });
 | 
					        this.setState({ 'hover': true });
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -93,6 +111,11 @@ module.exports = React.createClass({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    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 isMyUser = MatrixClientPeg.get().credentials.userId == this.props.member.userId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var power;
 | 
					        var power;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										105
									
								
								src/skins/vector/views/molecules/MessageContextMenu.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 dis = require('matrix-react-sdk/lib/dispatcher');
 | 
				
			||||||
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					var Modal = require('matrix-react-sdk/lib/Modal');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
					    displayName: 'MessageContextMenu',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onResendClick: function() {
 | 
				
			||||||
 | 
					        MatrixClientPeg.get().resendEvent(
 | 
				
			||||||
 | 
					            this.props.mxEvent, MatrixClientPeg.get().getRoom(
 | 
				
			||||||
 | 
					                this.props.mxEvent.getRoomId()
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        ).done(function() {
 | 
				
			||||||
 | 
					            dis.dispatch({
 | 
				
			||||||
 | 
					                action: 'message_sent'
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }, function() {
 | 
				
			||||||
 | 
					            dis.dispatch({
 | 
				
			||||||
 | 
					                action: 'message_send_failed'
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        dis.dispatch({action: 'message_resend_started'});
 | 
				
			||||||
 | 
					        if (this.props.onFinished) this.props.onFinished();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onViewSourceClick: function() {
 | 
				
			||||||
 | 
					        var ViewSource = sdk.getComponent('organisms.ViewSource');
 | 
				
			||||||
 | 
					        Modal.createDialog(ViewSource, {
 | 
				
			||||||
 | 
					            mxEvent: this.props.mxEvent
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        if (this.props.onFinished) this.props.onFinished();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onRedactClick: function() {
 | 
				
			||||||
 | 
					        MatrixClientPeg.get().redactEvent(
 | 
				
			||||||
 | 
					            this.props.mxEvent.getRoomId(), this.props.mxEvent.getId()
 | 
				
			||||||
 | 
					        ).done(function() {
 | 
				
			||||||
 | 
					            // message should disappear by itself
 | 
				
			||||||
 | 
					        }, function(e) {
 | 
				
			||||||
 | 
					            var ErrorDialog = sdk.getComponent("organisms.ErrorDialog");
 | 
				
			||||||
 | 
					            // display error message stating you couldn't delete this.
 | 
				
			||||||
 | 
					            var code = e.errcode || e.statusCode;
 | 
				
			||||||
 | 
					            Modal.createDialog(ErrorDialog, {
 | 
				
			||||||
 | 
					                title: "Error",
 | 
				
			||||||
 | 
					                description: "You cannot delete this message. (" + code + ")"
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        if (this.props.onFinished) this.props.onFinished();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var resendButton;
 | 
				
			||||||
 | 
					        var viewSourceButton;
 | 
				
			||||||
 | 
					        var redactButton;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.props.mxEvent.status == 'not_sent') {
 | 
				
			||||||
 | 
					            resendButton = (
 | 
				
			||||||
 | 
					                <div className="mx_ContextualMenu_field" onClick={this.onResendClick}>
 | 
				
			||||||
 | 
					                    Resend
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            redactButton = (
 | 
				
			||||||
 | 
					                <div className="mx_ContextualMenu_field" onClick={this.onRedactClick}>
 | 
				
			||||||
 | 
					                    Delete
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        viewSourceButton = (
 | 
				
			||||||
 | 
					            <div className="mx_ContextualMenu_field" onClick={this.onViewSourceClick}>
 | 
				
			||||||
 | 
					                View Source
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                {resendButton}
 | 
				
			||||||
 | 
					                {redactButton}
 | 
				
			||||||
 | 
					                {viewSourceButton}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -18,8 +18,6 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var classNames = require("classnames");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var MessageTileController = require('matrix-react-sdk/lib/controllers/molecules/MessageTile')
 | 
					var MessageTileController = require('matrix-react-sdk/lib/controllers/molecules/MessageTile')
 | 
				
			||||||
@ -28,11 +26,13 @@ module.exports = React.createClass({
 | 
				
			|||||||
    displayName: 'MessageTile',
 | 
					    displayName: 'MessageTile',
 | 
				
			||||||
    mixins: [MessageTileController],
 | 
					    mixins: [MessageTileController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    statics: {
 | 
				
			||||||
        var MessageTimestamp = sdk.getComponent('atoms.MessageTimestamp');
 | 
					        needsSenderProfile: function() {
 | 
				
			||||||
        var SenderProfile = sdk.getComponent('molecules.SenderProfile');
 | 
					            return true;
 | 
				
			||||||
        var MemberAvatar = sdk.getComponent('atoms.MemberAvatar');
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render: function() {
 | 
				
			||||||
        var UnknownMessageTile = sdk.getComponent('molecules.UnknownMessageTile');
 | 
					        var UnknownMessageTile = sdk.getComponent('molecules.UnknownMessageTile');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var tileTypes = {
 | 
					        var tileTypes = {
 | 
				
			||||||
@ -49,47 +49,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
        if (msgtype && tileTypes[msgtype]) {
 | 
					        if (msgtype && tileTypes[msgtype]) {
 | 
				
			||||||
            TileType = tileTypes[msgtype];
 | 
					            TileType = tileTypes[msgtype];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        var classes = classNames({
 | 
					 | 
				
			||||||
            mx_MessageTile: true,
 | 
					 | 
				
			||||||
            mx_MessageTile_sending: ['sending', 'queued'].indexOf(
 | 
					 | 
				
			||||||
                this.props.mxEvent.status
 | 
					 | 
				
			||||||
            ) !== -1,
 | 
					 | 
				
			||||||
            mx_MessageTile_notSent: this.props.mxEvent.status == 'not_sent',
 | 
					 | 
				
			||||||
            mx_MessageTile_highlight: this.shouldHighlight(),
 | 
					 | 
				
			||||||
            mx_MessageTile_continuation: this.props.continuation,
 | 
					 | 
				
			||||||
            mx_MessageTile_last: this.props.last,
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        var timestamp = <MessageTimestamp ts={this.props.mxEvent.getTs()} />
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var aux = null;
 | 
					        return <TileType mxEvent={this.props.mxEvent} />;
 | 
				
			||||||
        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 avatar, sender, resend;
 | 
					 | 
				
			||||||
        if (!this.props.continuation) {
 | 
					 | 
				
			||||||
            if (this.props.mxEvent.sender) {
 | 
					 | 
				
			||||||
                avatar = (
 | 
					 | 
				
			||||||
                    <div className="mx_MessageTile_avatar">
 | 
					 | 
				
			||||||
                        <MemberAvatar member={this.props.mxEvent.sender} />
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            sender = <SenderProfile mxEvent={this.props.mxEvent} aux={aux} />;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (this.props.mxEvent.status === "not_sent" && !this.state.resending) {
 | 
					 | 
				
			||||||
            resend = <button className="mx_MessageTile_msgOption" onClick={this.onResend}>
 | 
					 | 
				
			||||||
                Resend
 | 
					 | 
				
			||||||
            </button>;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return (
 | 
					 | 
				
			||||||
            <div className={classes}>
 | 
					 | 
				
			||||||
                { avatar }
 | 
					 | 
				
			||||||
                { timestamp }
 | 
					 | 
				
			||||||
                { resend }
 | 
					 | 
				
			||||||
                { sender }
 | 
					 | 
				
			||||||
                <TileType mxEvent={this.props.mxEvent} />
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,9 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					var dis = require('matrix-react-sdk/lib/dispatcher')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var CallHandler = require('matrix-react-sdk/lib/CallHandler');
 | 
				
			||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
					var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
				
			||||||
var RoomHeaderController = require('matrix-react-sdk/lib/controllers/molecules/RoomHeader')
 | 
					var RoomHeaderController = require('matrix-react-sdk/lib/controllers/molecules/RoomHeader')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,6 +38,10 @@ module.exports = React.createClass({
 | 
				
			|||||||
        return this.refs.name_edit.getDOMNode().value;
 | 
					        return this.refs.name_edit.getDOMNode().value;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onFullscreenClick: function() {
 | 
				
			||||||
 | 
					        dis.dispatch({action: 'video_fullscreen', fullscreen: true}, true);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var EditableText = sdk.getComponent("atoms.EditableText");
 | 
					        var EditableText = sdk.getComponent("atoms.EditableText");
 | 
				
			||||||
        var RoomAvatar = sdk.getComponent('atoms.RoomAvatar');
 | 
					        var RoomAvatar = sdk.getComponent('atoms.RoomAvatar');
 | 
				
			||||||
@ -52,18 +58,41 @@ module.exports = React.createClass({
 | 
				
			|||||||
        else {
 | 
					        else {
 | 
				
			||||||
            var topic = this.props.room.currentState.getStateEvents('m.room.topic', '');
 | 
					            var topic = this.props.room.currentState.getStateEvents('m.room.topic', '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var callButtons;
 | 
					            var call_buttons;
 | 
				
			||||||
            if (this.state) {
 | 
					            var zoom_button;
 | 
				
			||||||
                switch (this.state.call_state) {
 | 
					            if (this.state && this.state.call_state != 'ended') {
 | 
				
			||||||
                    case "ringback":
 | 
					                //var muteVideoButton;
 | 
				
			||||||
                    case "connected":
 | 
					                var activeCall = (
 | 
				
			||||||
                        callButtons = (
 | 
					                    CallHandler.getCallForRoom(this.props.room.roomId)
 | 
				
			||||||
                            <div className="mx_RoomHeader_textButton" onClick={this.onHangupClick}>
 | 
					                );
 | 
				
			||||||
 | 
					/*                
 | 
				
			||||||
 | 
					                if (activeCall && activeCall.type === "video") {
 | 
				
			||||||
 | 
					                    muteVideoButton = (
 | 
				
			||||||
 | 
					                        <div className="mx_RoomHeader_textButton mx_RoomHeader_voipButton"
 | 
				
			||||||
 | 
					                                onClick={this.onMuteVideoClick}>
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                (activeCall.isLocalVideoMuted() ?
 | 
				
			||||||
 | 
					                                    "Unmute" : "Mute") + " video"
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                        {muteVideoButton}
 | 
				
			||||||
 | 
					                        <div className="mx_RoomHeader_textButton mx_RoomHeader_voipButton"
 | 
				
			||||||
 | 
					                                onClick={this.onMuteAudioClick}>
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                (activeCall && activeCall.isMicrophoneMuted() ?
 | 
				
			||||||
 | 
					                                    "Unmute" : "Mute") + " audio"
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					*/                
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                call_buttons = (
 | 
				
			||||||
 | 
					                    <div className="mx_RoomHeader_textButton"
 | 
				
			||||||
 | 
					                            onClick={this.onHangupClick}>
 | 
				
			||||||
                        End call
 | 
					                        End call
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var name = null;
 | 
					            var name = null;
 | 
				
			||||||
@ -97,7 +126,15 @@ module.exports = React.createClass({
 | 
				
			|||||||
            var roomAvatar = null;
 | 
					            var roomAvatar = null;
 | 
				
			||||||
            if (this.props.room) {
 | 
					            if (this.props.room) {
 | 
				
			||||||
                roomAvatar = (
 | 
					                roomAvatar = (
 | 
				
			||||||
                    <RoomAvatar room={this.props.room} />
 | 
					                    <RoomAvatar room={this.props.room} width="48" height="48" />
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (activeCall && activeCall.type == "video") {
 | 
				
			||||||
 | 
					                zoom_button = (
 | 
				
			||||||
 | 
					                    <div className="mx_RoomHeader_button" onClick={this.onFullscreenClick}>
 | 
				
			||||||
 | 
					                        <img src="img/zoom.png" title="Fullscreen" alt="Fullscreen" width="32" height="32" style={{ 'marginTop': '3px' }}/>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -112,18 +149,19 @@ module.exports = React.createClass({
 | 
				
			|||||||
                            { topic_el }
 | 
					                            { topic_el }
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    {callButtons}
 | 
					                    {call_buttons}
 | 
				
			||||||
                    {cancel_button}
 | 
					                    {cancel_button}
 | 
				
			||||||
                    {save_button}
 | 
					                    {save_button}
 | 
				
			||||||
                    <div className="mx_RoomHeader_rightRow">
 | 
					                    <div className="mx_RoomHeader_rightRow">
 | 
				
			||||||
                        { settings_button }
 | 
					                        { settings_button }
 | 
				
			||||||
 | 
					                        { zoom_button }
 | 
				
			||||||
                        <div className="mx_RoomHeader_button mx_RoomHeader_search">
 | 
					                        <div className="mx_RoomHeader_button mx_RoomHeader_search">
 | 
				
			||||||
                            <img src="img/search.png" title="Search" alt="Search" width="32" height="32"/>
 | 
					                            <img src="img/search.png" title="Search" alt="Search" width="32" height="32"/>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div className="mx_RoomHeader_button mx_RoomHeader_video" onClick={this.onVideoClick}>
 | 
					                        <div className="mx_RoomHeader_button mx_RoomHeader_video" onClick={activeCall && activeCall.type === "video" ? this.onMuteVideoClick : this.onVideoClick}>
 | 
				
			||||||
                            <img src="img/video.png" title="Video call" alt="Video call" width="32" height="32"/>
 | 
					                            <img src="img/video.png" title="Video call" alt="Video call" width="32" height="32"/>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div className="mx_RoomHeader_button mx_RoomHeader_voice" onClick={this.onVoiceClick}>
 | 
					                        <div className="mx_RoomHeader_button mx_RoomHeader_voice" onClick={activeCall ? this.onMuteAudioClick : this.onVoiceClick}>
 | 
				
			||||||
                            <img src="img/voip.png" title="VoIP call" alt="VoIP call" width="32" height="32"/>
 | 
					                            <img src="img/voip.png" title="VoIP call" alt="VoIP call" width="32" height="32"/>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,7 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
					var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
				
			||||||
 | 
					var sdk = require('matrix-react-sdk');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var RoomSettingsController = require('matrix-react-sdk/lib/controllers/molecules/RoomSettings')
 | 
					var RoomSettingsController = require('matrix-react-sdk/lib/controllers/molecules/RoomSettings')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,6 +66,8 @@ module.exports = React.createClass({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var ChangeAvatar = sdk.getComponent('molecules.ChangeAvatar');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var topic = this.props.room.currentState.getStateEvents('m.room.topic', '');
 | 
					        var topic = this.props.room.currentState.getStateEvents('m.room.topic', '');
 | 
				
			||||||
        if (topic) topic = topic.getContent().topic;
 | 
					        if (topic) topic = topic.getContent().topic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -76,6 +79,8 @@ module.exports = React.createClass({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        var power_levels = this.props.room.currentState.getStateEvents('m.room.power_levels', '');
 | 
					        var power_levels = this.props.room.currentState.getStateEvents('m.room.power_levels', '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var events_levels = power_levels.events || {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (power_levels) {
 | 
					        if (power_levels) {
 | 
				
			||||||
            power_levels = power_levels.getContent();
 | 
					            power_levels = power_levels.getContent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -91,8 +96,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
            if (power_levels.kick == undefined) kick_level = 50;
 | 
					            if (power_levels.kick == undefined) kick_level = 50;
 | 
				
			||||||
            if (power_levels.redact == undefined) redact_level = 50;
 | 
					            if (power_levels.redact == undefined) redact_level = 50;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var user_levels = power_levels.users || [];
 | 
					            var user_levels = power_levels.users || {};
 | 
				
			||||||
            var events_levels = power_levels.events || [];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var user_id = MatrixClientPeg.get().credentials.userId;
 | 
					            var user_id = MatrixClientPeg.get().credentials.userId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -124,7 +128,21 @@ module.exports = React.createClass({
 | 
				
			|||||||
            var can_change_levels = false;
 | 
					            var can_change_levels = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var banned = this.props.room.getMembersWithMemership("ban");
 | 
					        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 = <div>
 | 
				
			||||||
 | 
					                <h3>Room Icon</h3>
 | 
				
			||||||
 | 
					                <ChangeAvatar room={this.props.room} />
 | 
				
			||||||
 | 
					            </div>;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var banned = this.props.room.getMembersWithMembership("ban");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className="mx_RoomSettings">
 | 
					            <div className="mx_RoomSettings">
 | 
				
			||||||
@ -207,6 +225,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
                        );
 | 
					                        );
 | 
				
			||||||
                    })}
 | 
					                    })}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					                {change_avatar}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,19 @@ var sdk = require('matrix-react-sdk')
 | 
				
			|||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'RoomTile',
 | 
					    displayName: 'RoomTile',
 | 
				
			||||||
    mixins: [RoomTileController],
 | 
					    mixins: [RoomTileController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getInitialState: function() {
 | 
				
			||||||
 | 
					        return( { hover : false });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onMouseEnter: function() {
 | 
				
			||||||
 | 
					        this.setState( { hover : true });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onMouseLeave: function() {
 | 
				
			||||||
 | 
					        this.setState( { hover : false });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var myUserId = MatrixClientPeg.get().credentials.userId;
 | 
					        var myUserId = MatrixClientPeg.get().credentials.userId;
 | 
				
			||||||
        var classes = classNames({
 | 
					        var classes = classNames({
 | 
				
			||||||
@ -57,14 +70,24 @@ module.exports = React.createClass({
 | 
				
			|||||||
            nameCell = <div className="mx_RoomTile_name">{name}</div>;
 | 
					            nameCell = <div className="mx_RoomTile_name">{name}</div>;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        */
 | 
					        */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var label;
 | 
				
			||||||
 | 
					        if (!this.props.collapsed) {
 | 
				
			||||||
 | 
					            label = <div className="mx_RoomTile_name">{name}</div>;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (this.state.hover) {
 | 
				
			||||||
 | 
					            var RoomTooltip = sdk.getComponent("molecules.RoomTooltip");
 | 
				
			||||||
 | 
					            label = <RoomTooltip room={this.props.room}/>;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var RoomAvatar = sdk.getComponent('atoms.RoomAvatar');
 | 
					        var RoomAvatar = sdk.getComponent('atoms.RoomAvatar');
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className={classes} onClick={this.onClick}>
 | 
					            <div className={classes} onClick={this.onClick} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
 | 
				
			||||||
                <div className="mx_RoomTile_avatar">
 | 
					                <div className="mx_RoomTile_avatar">
 | 
				
			||||||
                    <RoomAvatar room={this.props.room} />
 | 
					                    <RoomAvatar room={this.props.room} />
 | 
				
			||||||
                    { badge }
 | 
					                    { badge }
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div className="mx_RoomTile_name">{name}</div>
 | 
					                { label }
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										59
									
								
								src/skins/vector/views/molecules/RoomTooltip.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 dis = require('matrix-react-sdk/lib/dispatcher');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
					    displayName: 'RoomTooltip',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentDidMount: function() {
 | 
				
			||||||
 | 
					        if (!this.props.bottom) {
 | 
				
			||||||
 | 
					            // tell the roomlist about us so it can position us
 | 
				
			||||||
 | 
					            dis.dispatch({
 | 
				
			||||||
 | 
					                action: 'view_tooltip',
 | 
				
			||||||
 | 
					                tooltip: this.getDOMNode(),
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            var tooltip = this.getDOMNode();
 | 
				
			||||||
 | 
					            tooltip.style.top = tooltip.parentElement.getBoundingClientRect().top + "px"; 
 | 
				
			||||||
 | 
					            tooltip.style.display = "block";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentDidUnmount: function() {
 | 
				
			||||||
 | 
					        if (!this.props.bottom) {
 | 
				
			||||||
 | 
					            dis.dispatch({
 | 
				
			||||||
 | 
					                action: 'view_tooltip',
 | 
				
			||||||
 | 
					                tooltip: null,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var label = this.props.room ? this.props.room.name : this.props.label;
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div className="mx_RoomTooltip">
 | 
				
			||||||
 | 
					                 <img className="mx_RoomTooltip_chevron" src="img/chevron-left.png" width="9" height="16"/>
 | 
				
			||||||
 | 
					                 { label }
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -19,15 +19,12 @@ limitations under the License.
 | 
				
			|||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
var classNames = require("classnames");
 | 
					var classNames = require("classnames");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var SenderProfileController = require('matrix-react-sdk/lib/controllers/molecules/SenderProfile')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The Lato WOFF doesn't include sensible combining diacritics, so Chrome chokes on rendering them.
 | 
					// 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.
 | 
					// Revert to Arial when this happens, which on OSX works at least.
 | 
				
			||||||
var zalgo = /[\u0300-\u036f\u1ab0-\u1aff\u1dc0-\u1dff\u20d0-\u20ff\ufe20-\ufe2f]/;
 | 
					var zalgo = /[\u0300-\u036f\u1ab0-\u1aff\u1dc0-\u1dff\u20d0-\u20ff\ufe20-\ufe2f]/;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'SenderProfile',
 | 
					    displayName: 'SenderProfile',
 | 
				
			||||||
    mixins: [SenderProfileController],
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var mxEvent = this.props.mxEvent;
 | 
					        var mxEvent = this.props.mxEvent;
 | 
				
			||||||
 | 
				
			|||||||
@ -18,11 +18,8 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var UnknownMessageTileController = require('matrix-react-sdk/lib/controllers/molecules/UnknownMessageTile')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'UnknownMessageTile',
 | 
					    displayName: 'UnknownMessageTile',
 | 
				
			||||||
    mixins: [UnknownMessageTileController],
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var content = this.props.mxEvent.getContent();
 | 
					        var content = this.props.mxEvent.getContent();
 | 
				
			||||||
 | 
				
			|||||||
@ -31,24 +31,28 @@ module.exports = React.createClass({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        if (!this.state.incomingCall || !this.state.incomingCall.roomId) {
 | 
					
 | 
				
			||||||
            return (
 | 
					        // NB: This block MUST have a "key" so React doesn't clobber the elements
 | 
				
			||||||
                <div>
 | 
					        // between in-call / not-in-call.
 | 
				
			||||||
                    <audio ref="ringAudio" loop>
 | 
					        var audioBlock = (
 | 
				
			||||||
 | 
					            <audio ref="ringAudio" key="voip_ring_audio" loop>
 | 
				
			||||||
                <source src="media/ring.ogg" type="audio/ogg" />
 | 
					                <source src="media/ring.ogg" type="audio/ogg" />
 | 
				
			||||||
                <source src="media/ring.mp3" type="audio/mpeg" />
 | 
					                <source src="media/ring.mp3" type="audio/mpeg" />
 | 
				
			||||||
            </audio>
 | 
					            </audio>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!this.state.incomingCall || !this.state.incomingCall.roomId) {
 | 
				
			||||||
 | 
					            return (
 | 
				
			||||||
 | 
					                <div>
 | 
				
			||||||
 | 
					                    {audioBlock}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        var caller = MatrixClientPeg.get().getRoom(this.state.incomingCall.roomId).name;
 | 
					        var caller = MatrixClientPeg.get().getRoom(this.state.incomingCall.roomId).name;
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className="mx_IncomingCallBox">
 | 
					            <div className="mx_IncomingCallBox">
 | 
				
			||||||
 | 
					                {audioBlock}
 | 
				
			||||||
                <img className="mx_IncomingCallBox_chevron" src="img/chevron-left.png" width="9" height="16" />
 | 
					                <img className="mx_IncomingCallBox_chevron" src="img/chevron-left.png" width="9" height="16" />
 | 
				
			||||||
                <audio ref="ringAudio" loop>
 | 
					 | 
				
			||||||
                    <source src="media/ring.ogg" type="audio/ogg" />
 | 
					 | 
				
			||||||
                    <source src="media/ring.mp3" type="audio/mpeg" />
 | 
					 | 
				
			||||||
                </audio>
 | 
					 | 
				
			||||||
                <div className="mx_IncomingCallBox_title">
 | 
					                <div className="mx_IncomingCallBox_title">
 | 
				
			||||||
                    Incoming { this.state.incomingCall ? this.state.incomingCall.type : '' } call from { caller }
 | 
					                    Incoming { this.state.incomingCall ? this.state.incomingCall.type : '' } call from { caller }
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -19,26 +19,69 @@ limitations under the License.
 | 
				
			|||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
var VideoViewController = require('matrix-react-sdk/lib/controllers/molecules/voip/VideoView')
 | 
					var dis = require('matrix-react-sdk/lib/dispatcher')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'VideoView',
 | 
					    displayName: 'VideoView',
 | 
				
			||||||
    mixins: [VideoViewController],
 | 
					
 | 
				
			||||||
 | 
					    componentWillMount: function() {
 | 
				
			||||||
 | 
					        dis.register(this.onAction);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getRemoteVideoElement: function() {
 | 
					    getRemoteVideoElement: function() {
 | 
				
			||||||
        return this.refs.remote.getDOMNode();
 | 
					        return this.refs.remote.getDOMNode();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getRemoteAudioElement: function() {
 | 
				
			||||||
 | 
					        return this.refs.remoteAudio.getDOMNode();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getLocalVideoElement: function() {
 | 
					    getLocalVideoElement: function() {
 | 
				
			||||||
        return this.refs.local.getDOMNode();
 | 
					        return this.refs.local.getDOMNode();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setContainer: function(c) {
 | 
				
			||||||
 | 
					        this.container = c;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onAction: function(payload) {
 | 
				
			||||||
 | 
					        switch (payload.action) {
 | 
				
			||||||
 | 
					            case 'video_fullscreen':
 | 
				
			||||||
 | 
					                if (!this.container) {
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                var element = this.container.getDOMNode();
 | 
				
			||||||
 | 
					                if (payload.fullscreen) {
 | 
				
			||||||
 | 
					                    var requestMethod = (
 | 
				
			||||||
 | 
					                        element.requestFullScreen ||
 | 
				
			||||||
 | 
					                        element.webkitRequestFullScreen ||
 | 
				
			||||||
 | 
					                        element.mozRequestFullScreen ||
 | 
				
			||||||
 | 
					                        element.msRequestFullscreen
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                    requestMethod.call(element);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    var exitMethod = (
 | 
				
			||||||
 | 
					                        document.exitFullscreen ||
 | 
				
			||||||
 | 
					                        document.mozCancelFullScreen ||
 | 
				
			||||||
 | 
					                        document.webkitExitFullscreen ||
 | 
				
			||||||
 | 
					                        document.msExitFullscreen
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                    if (exitMethod) {
 | 
				
			||||||
 | 
					                        exitMethod.call(document);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var VideoFeed = sdk.getComponent('atoms.voip.VideoFeed');
 | 
					        var VideoFeed = sdk.getComponent('atoms.voip.VideoFeed');
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className="mx_VideoView">
 | 
					            <div className="mx_VideoView" ref={this.setContainer}>
 | 
				
			||||||
                <div className="mx_VideoView_remoteVideoFeed">
 | 
					                <div className="mx_VideoView_remoteVideoFeed">
 | 
				
			||||||
                    <VideoFeed ref="remote"/>
 | 
					                    <VideoFeed ref="remote"/>
 | 
				
			||||||
 | 
					                    <audio ref="remoteAudio"/>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div className="mx_VideoView_localVideoFeed">                
 | 
					                <div className="mx_VideoView_localVideoFeed">                
 | 
				
			||||||
                    <VideoFeed ref="local"/>
 | 
					                    <VideoFeed ref="local"/>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										35
									
								
								src/skins/vector/views/organisms/CasLogin.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 CasLoginController = require('matrix-react-sdk/lib/controllers/organisms/CasLogin');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
					    displayName: 'CasLogin',
 | 
				
			||||||
 | 
					    mixins: [CasLoginController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                <button onClick={this.onCasClicked}>Sign in with CAS</button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -18,21 +18,37 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					var dis = require('matrix-react-sdk/lib/dispatcher');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'LeftPanel',
 | 
					    displayName: 'LeftPanel',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onHideClick: function() {
 | 
				
			||||||
 | 
					        dis.dispatch({
 | 
				
			||||||
 | 
					            action: 'hide_left_panel',
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var RoomList = sdk.getComponent('organisms.RoomList');
 | 
					        var RoomList = sdk.getComponent('organisms.RoomList');
 | 
				
			||||||
        var BottomLeftMenu = sdk.getComponent('molecules.BottomLeftMenu');
 | 
					        var BottomLeftMenu = sdk.getComponent('molecules.BottomLeftMenu');
 | 
				
			||||||
        var IncomingCallBox = sdk.getComponent('molecules.voip.IncomingCallBox');
 | 
					        var IncomingCallBox = sdk.getComponent('molecules.voip.IncomingCallBox');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var collapseButton;
 | 
				
			||||||
 | 
					        var classes = "mx_LeftPanel";
 | 
				
			||||||
 | 
					        if (this.props.collapsed) {
 | 
				
			||||||
 | 
					            classes += " collapsed";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            collapseButton = <img className="mx_LeftPanel_hideButton" onClick={ this.onHideClick } src="img/hide.png" width="12" height="20" alt="<"/>   
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <aside className="mx_LeftPanel">
 | 
					            <aside className={classes}>
 | 
				
			||||||
                <img className="mx_LeftPanel_hideButton" src="img/hide.png" width="32" height="32" alt="<"/>
 | 
					                { collapseButton }
 | 
				
			||||||
                <IncomingCallBox />
 | 
					                <IncomingCallBox />
 | 
				
			||||||
                <RoomList selectedRoom={this.props.selectedRoom} />
 | 
					                <RoomList selectedRoom={this.props.selectedRoom} collapsed={this.props.collapsed}/>
 | 
				
			||||||
                <BottomLeftMenu />
 | 
					                <BottomLeftMenu collapsed={this.props.collapsed}/>
 | 
				
			||||||
            </aside>
 | 
					            </aside>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,7 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
var classNames = require('classnames');
 | 
					var classNames = require('classnames');
 | 
				
			||||||
 | 
					var Loader = require('react-loader');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var MemberListController = require('matrix-react-sdk/lib/controllers/organisms/MemberList')
 | 
					var MemberListController = require('matrix-react-sdk/lib/controllers/organisms/MemberList')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -32,12 +33,38 @@ module.exports = React.createClass({
 | 
				
			|||||||
        return { editing: false };
 | 
					        return { editing: false };
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    makeMemberTiles: function() {
 | 
					    memberSort: function(userIdA, userIdB) {
 | 
				
			||||||
 | 
					        var userA = this.memberDict[userIdA].user;
 | 
				
			||||||
 | 
					        var userB = this.memberDict[userIdB].user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var presenceMap = {
 | 
				
			||||||
 | 
					            online: 3,
 | 
				
			||||||
 | 
					            unavailable: 2,
 | 
				
			||||||
 | 
					            offline: 1
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var presenceOrdA = userA ? presenceMap[userA.presence] : 0;
 | 
				
			||||||
 | 
					        var presenceOrdB = userB ? presenceMap[userB.presence] : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (presenceOrdA != presenceOrdB) {
 | 
				
			||||||
 | 
					            return presenceOrdB - presenceOrdA;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var latA = userA ? (userA.lastPresenceTs - (userA.lastActiveAgo || userA.lastPresenceTs)) : 0;
 | 
				
			||||||
 | 
					        var latB = userB ? (userB.lastPresenceTs - (userB.lastActiveAgo || userB.lastPresenceTs)) : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return latB - latA;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    makeMemberTiles: function(membership) {
 | 
				
			||||||
        var MemberTile = sdk.getComponent("molecules.MemberTile");
 | 
					        var MemberTile = sdk.getComponent("molecules.MemberTile");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var self = this;
 | 
					        var self = this;
 | 
				
			||||||
        return Object.keys(self.state.memberDict).map(function(userId) {
 | 
					        return self.state.members.filter(function(userId) {
 | 
				
			||||||
            var m = self.state.memberDict[userId];
 | 
					            var m = self.memberDict[userId];
 | 
				
			||||||
 | 
					            return m.membership == membership;
 | 
				
			||||||
 | 
					        }).map(function(userId) {
 | 
				
			||||||
 | 
					            var m = self.memberDict[userId];
 | 
				
			||||||
            return (
 | 
					            return (
 | 
				
			||||||
                <MemberTile key={userId} member={m} ref={userId} />
 | 
					                <MemberTile key={userId} member={m} ref={userId} />
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
@ -69,6 +96,11 @@ module.exports = React.createClass({
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var EditableText = sdk.getComponent("atoms.EditableText");
 | 
					        var EditableText = sdk.getComponent("atoms.EditableText");
 | 
				
			||||||
 | 
					        if (this.state.inviting) {
 | 
				
			||||||
 | 
					            return (
 | 
				
			||||||
 | 
					                <Loader />
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
            return (
 | 
					            return (
 | 
				
			||||||
                <div className={ classes } onClick={ this.onClickInvite } >
 | 
					                <div className={ classes } onClick={ this.onClickInvite } >
 | 
				
			||||||
                    <div className="mx_MemberTile_avatar"><img src="img/create-big.png" width="40" height="40" alt=""/></div>
 | 
					                    <div className="mx_MemberTile_avatar"><img src="img/create-big.png" width="40" height="40" alt=""/></div>
 | 
				
			||||||
@ -77,21 +109,37 @@ module.exports = React.createClass({
 | 
				
			|||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        var invitedSection = null;
 | 
				
			||||||
 | 
					        var invitedMemberTiles = this.makeMemberTiles('invite');
 | 
				
			||||||
 | 
					        if (invitedMemberTiles.length > 0) {
 | 
				
			||||||
 | 
					            invitedSection = (
 | 
				
			||||||
 | 
					                <div>
 | 
				
			||||||
 | 
					                    <h2>Invited</h2>
 | 
				
			||||||
 | 
					                    <div className="mx_MemberList_wrapper">
 | 
				
			||||||
 | 
					                        {invitedMemberTiles}
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className="mx_MemberList">
 | 
					            <div className="mx_MemberList">
 | 
				
			||||||
                <div className="mx_MemberList_chevron">
 | 
					                <div className="mx_MemberList_chevron">
 | 
				
			||||||
                    <img src="img/chevron.png" width="24" height="13"/>
 | 
					                    <img src="img/chevron.png" width="24" height="13"/>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div className="mx_MemberList_border">
 | 
					                <div className="mx_MemberList_border">
 | 
				
			||||||
 | 
					                    <div>
 | 
				
			||||||
                        <h2>Members</h2>
 | 
					                        <h2>Members</h2>
 | 
				
			||||||
                        <div className="mx_MemberList_wrapper">
 | 
					                        <div className="mx_MemberList_wrapper">
 | 
				
			||||||
                        {this.makeMemberTiles()}
 | 
					                            {this.makeMemberTiles('join')}
 | 
				
			||||||
                        {this.inviteTile()}
 | 
					 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    {invitedSection}
 | 
				
			||||||
 | 
					                    {this.inviteTile()}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -58,15 +58,16 @@ var NotifierView = {
 | 
				
			|||||||
            if (ev.getContent().body) msg = ev.getContent().body;
 | 
					            if (ev.getContent().body) msg = ev.getContent().body;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var avatarUrl = Avatar.avatarUrlForMember(
 | 
					        var avatarUrl = ev.sender ? Avatar.avatarUrlForMember(
 | 
				
			||||||
            ev.sender, 40, 40, 'crop'
 | 
					            ev.sender, 40, 40, 'crop'
 | 
				
			||||||
        );
 | 
					        ) : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var notification = new global.Notification(
 | 
					        var notification = new global.Notification(
 | 
				
			||||||
            title,
 | 
					            title,
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                "body": msg,
 | 
					                "body": msg,
 | 
				
			||||||
                "icon": avatarUrl
 | 
					                "icon": avatarUrl,
 | 
				
			||||||
 | 
					                "tag": "vector"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,13 +18,12 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					var dis = require('matrix-react-sdk/lib/dispatcher');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'RightPanel',
 | 
					    displayName: 'RightPanel',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Phase : {
 | 
					    Phase : {
 | 
				
			||||||
        Blank: 'Blank',
 | 
					 | 
				
			||||||
        None: 'None',
 | 
					 | 
				
			||||||
        MemberList: 'MemberList',
 | 
					        MemberList: 'MemberList',
 | 
				
			||||||
        FileList: 'FileList',
 | 
					        FileList: 'FileList',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -36,11 +35,16 @@ module.exports = React.createClass({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onMemberListButtonClick: function() {
 | 
					    onMemberListButtonClick: function() {
 | 
				
			||||||
        if (this.state.phase == this.Phase.None) {
 | 
					        if (this.props.collapsed) {
 | 
				
			||||||
            this.setState({ phase: this.Phase.MemberList });
 | 
					            this.setState({ phase: this.Phase.MemberList });
 | 
				
			||||||
 | 
					            dis.dispatch({
 | 
				
			||||||
 | 
					                action: 'show_right_panel',
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            this.setState({ phase: this.Phase.None });
 | 
					            dis.dispatch({
 | 
				
			||||||
 | 
					                action: 'hide_right_panel',
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -48,6 +52,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
        var MemberList = sdk.getComponent('organisms.MemberList');
 | 
					        var MemberList = sdk.getComponent('organisms.MemberList');
 | 
				
			||||||
        var buttonGroup;
 | 
					        var buttonGroup;
 | 
				
			||||||
        var panel;
 | 
					        var panel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.props.roomId) {
 | 
					        if (this.props.roomId) {
 | 
				
			||||||
            buttonGroup =
 | 
					            buttonGroup =
 | 
				
			||||||
                    <div className="mx_RightPanel_headerButtonGroup">
 | 
					                    <div className="mx_RightPanel_headerButtonGroup">
 | 
				
			||||||
@ -59,13 +64,18 @@ module.exports = React.createClass({
 | 
				
			|||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>;
 | 
					                    </div>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.state.phase == this.Phase.MemberList) {
 | 
					            if (!this.props.collapsed && this.state.phase == this.Phase.MemberList) {
 | 
				
			||||||
                panel = <MemberList roomId={this.props.roomId} key={this.props.roomId} />
 | 
					                panel = <MemberList roomId={this.props.roomId} key={this.props.roomId} />
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var classes = "mx_RightPanel";
 | 
				
			||||||
 | 
					        if (this.props.collapsed) {
 | 
				
			||||||
 | 
					            classes += " collapsed";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <aside className="mx_RightPanel">
 | 
					            <aside className={classes}>
 | 
				
			||||||
                <div className="mx_RightPanel_header">
 | 
					                <div className="mx_RightPanel_header">
 | 
				
			||||||
                    { buttonGroup }
 | 
					                    { buttonGroup }
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,7 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					var dis = require('matrix-react-sdk/lib/dispatcher');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var RoomListController = require('../../../../controllers/organisms/RoomList')
 | 
					var RoomListController = require('../../../../controllers/organisms/RoomList')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -25,6 +26,12 @@ module.exports = React.createClass({
 | 
				
			|||||||
    displayName: 'RoomList',
 | 
					    displayName: 'RoomList',
 | 
				
			||||||
    mixins: [RoomListController],
 | 
					    mixins: [RoomListController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onShowClick: function() {
 | 
				
			||||||
 | 
					        dis.dispatch({
 | 
				
			||||||
 | 
					            action: 'show_left_panel',
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        var CallView = sdk.getComponent('molecules.voip.CallView');
 | 
					        var CallView = sdk.getComponent('molecules.voip.CallView');
 | 
				
			||||||
        var RoomDropTarget = sdk.getComponent('molecules.RoomDropTarget');
 | 
					        var RoomDropTarget = sdk.getComponent('molecules.RoomDropTarget');
 | 
				
			||||||
@ -34,13 +41,17 @@ module.exports = React.createClass({
 | 
				
			|||||||
            callElement = <CallView className="mx_MatrixChat_callView"/>
 | 
					            callElement = <CallView className="mx_MatrixChat_callView"/>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var recentsLabel = this.props.collapsed ? 
 | 
				
			||||||
 | 
					                           <img style={{cursor: 'pointer'}} onClick={ this.onShowClick } src="img/menu.png" width="27" height="20" alt=">"/> :
 | 
				
			||||||
 | 
					                           "Recents";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className="mx_RoomList">
 | 
					            <div className="mx_RoomList" onScroll={this._repositionTooltip}>
 | 
				
			||||||
                {callElement}
 | 
					                {callElement}
 | 
				
			||||||
                <h2 className="mx_RoomList_favourites_label">Favourites</h2>
 | 
					                <h2 className="mx_RoomList_favourites_label">Favourites</h2>
 | 
				
			||||||
                <RoomDropTarget text="Drop here to favourite"/>
 | 
					                <RoomDropTarget text="Drop here to favourite"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <h2 className="mx_RoomList_recents_label">Recents</h2>
 | 
					                <h2 className="mx_RoomList_recents_label">{ recentsLabel }</h2>
 | 
				
			||||||
                <div className="mx_RoomList_recents">
 | 
					                <div className="mx_RoomList_recents">
 | 
				
			||||||
                    {this.makeRoomTiles()}
 | 
					                    {this.makeRoomTiles()}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -19,12 +19,13 @@ limitations under the License.
 | 
				
			|||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
					var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
				
			||||||
 | 
					var dis = require('matrix-react-sdk/lib/dispatcher');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
var classNames = require("classnames");
 | 
					var classNames = require("classnames");
 | 
				
			||||||
var filesize = require('filesize');
 | 
					var filesize = require('filesize');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var RoomViewController = require('matrix-react-sdk/lib/controllers/organisms/RoomView')
 | 
					var RoomViewController = require('../../../../controllers/organisms/RoomView')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var Loader = require("react-loader");
 | 
					var Loader = require("react-loader");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,6 +63,14 @@ module.exports = React.createClass({
 | 
				
			|||||||
        this.setState(this.getInitialState());
 | 
					        this.setState(this.getInitialState());
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onConferenceNotificationClick: function() {
 | 
				
			||||||
 | 
					        dis.dispatch({
 | 
				
			||||||
 | 
					            action: 'place_call',
 | 
				
			||||||
 | 
					            type: "video",
 | 
				
			||||||
 | 
					            room_id: this.props.roomId
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getUnreadMessagesString: function() {
 | 
					    getUnreadMessagesString: function() {
 | 
				
			||||||
        if (!this.state.numUnreadMessages) {
 | 
					        if (!this.state.numUnreadMessages) {
 | 
				
			||||||
            return "";
 | 
					            return "";
 | 
				
			||||||
@ -129,19 +138,33 @@ module.exports = React.createClass({
 | 
				
			|||||||
                <div />
 | 
					                <div />
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // for testing UI...
 | 
				
			||||||
 | 
					            // this.state.upload = {
 | 
				
			||||||
 | 
					            //     uploadedBytes: 123493,
 | 
				
			||||||
 | 
					            //     totalBytes: 347534,
 | 
				
			||||||
 | 
					            //     fileName: "testing_fooble.jpg",
 | 
				
			||||||
 | 
					            // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.state.upload) {
 | 
					            if (this.state.upload) {
 | 
				
			||||||
                var innerProgressStyle = {
 | 
					                var innerProgressStyle = {
 | 
				
			||||||
                    width: ((this.state.upload.uploadedBytes / this.state.upload.totalBytes) * 100) + '%'
 | 
					                    width: ((this.state.upload.uploadedBytes / this.state.upload.totalBytes) * 100) + '%'
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					                var uploadedSize = filesize(this.state.upload.uploadedBytes);
 | 
				
			||||||
 | 
					                var totalSize = filesize(this.state.upload.totalBytes);
 | 
				
			||||||
 | 
					                if (uploadedSize.replace(/^.* /,'') === totalSize.replace(/^.* /,'')) {
 | 
				
			||||||
 | 
					                    uploadedSize = uploadedSize.replace(/ .*/, '');
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                statusBar = (
 | 
					                statusBar = (
 | 
				
			||||||
                    <div className="mx_RoomView_uploadBar">
 | 
					                    <div className="mx_RoomView_uploadBar">
 | 
				
			||||||
                        <span className="mx_RoomView_uploadFilename">Uploading {this.state.upload.fileName}</span>
 | 
					 | 
				
			||||||
                        <span className="mx_RoomView_uploadBytes">
 | 
					 | 
				
			||||||
                        {filesize(this.state.upload.uploadedBytes)} / {filesize(this.state.upload.totalBytes)}
 | 
					 | 
				
			||||||
                        </span>
 | 
					 | 
				
			||||||
                        <div className="mx_RoomView_uploadProgressOuter">
 | 
					                        <div className="mx_RoomView_uploadProgressOuter">
 | 
				
			||||||
                            <div className="mx_RoomView_uploadProgressInner" style={innerProgressStyle}></div>
 | 
					                            <div className="mx_RoomView_uploadProgressInner" style={innerProgressStyle}></div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
 | 
					                        <img className="mx_RoomView_uploadIcon" src="img/fileicon.png" width="40" height="40"/>
 | 
				
			||||||
 | 
					                        <img className="mx_RoomView_uploadCancel" src="img/cancel.png" width="40" height="40"/>
 | 
				
			||||||
 | 
					                        <div className="mx_RoomView_uploadBytes">
 | 
				
			||||||
 | 
					                            { uploadedSize } / { totalSize }
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                        <div className="mx_RoomView_uploadFilename">Uploading {this.state.upload.fileName}</div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,15 @@ module.exports = React.createClass({
 | 
				
			|||||||
    editAvatar: function() {
 | 
					    editAvatar: function() {
 | 
				
			||||||
        var url = MatrixClientPeg.get().mxcUrlToHttp(this.state.avatarUrl);
 | 
					        var url = MatrixClientPeg.get().mxcUrlToHttp(this.state.avatarUrl);
 | 
				
			||||||
        var ChangeAvatar = sdk.getComponent('molecules.ChangeAvatar');
 | 
					        var ChangeAvatar = sdk.getComponent('molecules.ChangeAvatar');
 | 
				
			||||||
        Modal.createDialog(ChangeAvatar, {initialAvatarUrl: url});
 | 
					        var avatarDialog = (
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                <ChangeAvatar initialAvatarUrl={url} />
 | 
				
			||||||
 | 
					                <div className="mx_Dialog_buttons">
 | 
				
			||||||
 | 
					                    <button onClick={this.onAvatarDialogCancel}>Cancel</button>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        this.avatarDialog = Modal.createDialogWithElement(avatarDialog);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    addEmail: function() {
 | 
					    addEmail: function() {
 | 
				
			||||||
@ -55,12 +63,16 @@ module.exports = React.createClass({
 | 
				
			|||||||
        this.logoutModal.closeDialog();
 | 
					        this.logoutModal.closeDialog();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onAvatarDialogCancel: function() {
 | 
				
			||||||
 | 
					        this.avatarDialog.close();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render: function() {
 | 
					    render: function() {
 | 
				
			||||||
        switch (this.state.phase) {
 | 
					        switch (this.state.phase) {
 | 
				
			||||||
            case this.Phases.Loading:
 | 
					            case this.Phases.Loading:
 | 
				
			||||||
                return <Loader />
 | 
					                return <Loader />
 | 
				
			||||||
            case this.Phases.Display:
 | 
					            case this.Phases.Display:
 | 
				
			||||||
                var EditableText = sdk.getComponent('atoms.EditableText');
 | 
					                var ChangeDisplayName = sdk.getComponent('molecules.ChangeDisplayName');
 | 
				
			||||||
                var EnableNotificationsButton = sdk.getComponent('atoms.EnableNotificationsButton');
 | 
					                var EnableNotificationsButton = sdk.getComponent('atoms.EnableNotificationsButton');
 | 
				
			||||||
                return (
 | 
					                return (
 | 
				
			||||||
                    <div className="mx_UserSettings">
 | 
					                    <div className="mx_UserSettings">
 | 
				
			||||||
@ -74,13 +86,13 @@ module.exports = React.createClass({
 | 
				
			|||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                <div className="mx_UserSettings_DisplayName">
 | 
					                                <div className="mx_UserSettings_DisplayName">
 | 
				
			||||||
                                    <EditableText ref="displayname" initialValue={this.state.displayName} label="Click to set display name." onValueChanged={this.changeDisplayname}/>
 | 
					                                    <ChangeDisplayName ref="displayname" />
 | 
				
			||||||
                                    <div className="mx_UserSettings_DisplayName_Edit" onClick={this.editDisplayName}>Edit</div>
 | 
					                                    <div className="mx_UserSettings_DisplayName_Edit" onClick={this.editDisplayName}>Edit</div>
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                <div className="mx_UserSettings_3pids">
 | 
					                                <div className="mx_UserSettings_3pids">
 | 
				
			||||||
                                    {this.state.threepids.map(function(val) {
 | 
					                                    {this.state.threepids.map(function(val) {
 | 
				
			||||||
                                        return <div>{val.address}</div>;
 | 
					                                        return <div key={val.address}>{val.address}</div>;
 | 
				
			||||||
                                    })}
 | 
					                                    })}
 | 
				
			||||||
                                </div>
 | 
					                                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										34
									
								
								src/skins/vector/views/organisms/ViewSource.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = React.createClass({
 | 
				
			||||||
 | 
					    displayName: 'ViewSource',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render: function() {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div className="mx_ViewSource">
 | 
				
			||||||
 | 
					                <pre>
 | 
				
			||||||
 | 
					                    {JSON.stringify(this.props.mxEvent.event, null, 2)}
 | 
				
			||||||
 | 
					                </pre>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -25,12 +25,66 @@ var MatrixChatController = require('matrix-react-sdk/lib/controllers/pages/Matri
 | 
				
			|||||||
var Loader = require("react-loader");
 | 
					var Loader = require("react-loader");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var dis = require('matrix-react-sdk/lib/dispatcher');
 | 
					var dis = require('matrix-react-sdk/lib/dispatcher');
 | 
				
			||||||
 | 
					var Matrix = require("matrix-js-sdk");
 | 
				
			||||||
 | 
					var ContextualMenu = require("../../../../ContextualMenu");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    displayName: 'MatrixChat',
 | 
					    displayName: 'MatrixChat',
 | 
				
			||||||
    mixins: [MatrixChatController],
 | 
					    mixins: [MatrixChatController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getInitialState: function() {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            width: 10000,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentDidMount: function() {
 | 
				
			||||||
 | 
					        window.addEventListener('resize', this.handleResize);
 | 
				
			||||||
 | 
					        this.handleResize();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentWillUnmount: function() {
 | 
				
			||||||
 | 
					        window.removeEventListener('resize', this.handleResize);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onAliasClick: function(event, alias) {
 | 
				
			||||||
 | 
					        event.preventDefault();
 | 
				
			||||||
 | 
					        dis.dispatch({action: 'view_room_alias', room_alias: alias});
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onUserClick: function(event, userId) {
 | 
				
			||||||
 | 
					        event.preventDefault();
 | 
				
			||||||
 | 
					        var MemberInfo = sdk.getComponent('molecules.MemberInfo');
 | 
				
			||||||
 | 
					        var member = new Matrix.RoomMember(null, userId);
 | 
				
			||||||
 | 
					        ContextualMenu.createMenu(MemberInfo, {
 | 
				
			||||||
 | 
					            member: member,
 | 
				
			||||||
 | 
					            right: window.innerWidth - event.pageX,
 | 
				
			||||||
 | 
					            top: event.pageY
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    handleResize: function(e) {
 | 
				
			||||||
 | 
					        var hideLhsThreshold = 1000;
 | 
				
			||||||
 | 
					        var showLhsThreshold = 1000;
 | 
				
			||||||
 | 
					        var hideRhsThreshold = 820;
 | 
				
			||||||
 | 
					        var showRhsThreshold = 820;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.state.width > hideLhsThreshold && window.innerWidth <= hideLhsThreshold) {
 | 
				
			||||||
 | 
					            dis.dispatch({ action: 'hide_left_panel' });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (this.state.width <= showLhsThreshold && window.innerWidth > showLhsThreshold) {
 | 
				
			||||||
 | 
					            dis.dispatch({ action: 'show_left_panel' });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (this.state.width > hideRhsThreshold && window.innerWidth <= hideRhsThreshold) {
 | 
				
			||||||
 | 
					            dis.dispatch({ action: 'hide_right_panel' });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (this.state.width <= showRhsThreshold && window.innerWidth > showRhsThreshold) {
 | 
				
			||||||
 | 
					            dis.dispatch({ action: 'show_right_panel' });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.setState({width: window.innerWidth});
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onRoomCreated: function(room_id) {
 | 
					    onRoomCreated: function(room_id) {
 | 
				
			||||||
        dis.dispatch({
 | 
					        dis.dispatch({
 | 
				
			||||||
            action: "view_room",
 | 
					            action: "view_room",
 | 
				
			||||||
@ -57,19 +111,19 @@ module.exports = React.createClass({
 | 
				
			|||||||
            switch (this.state.page_type) {
 | 
					            switch (this.state.page_type) {
 | 
				
			||||||
                case this.PageTypes.RoomView:
 | 
					                case this.PageTypes.RoomView:
 | 
				
			||||||
                    page_element = <RoomView roomId={this.state.currentRoom} key={this.state.currentRoom} />
 | 
					                    page_element = <RoomView roomId={this.state.currentRoom} key={this.state.currentRoom} />
 | 
				
			||||||
                    right_panel = <RightPanel roomId={this.state.currentRoom} />
 | 
					                    right_panel = <RightPanel roomId={this.state.currentRoom} collapsed={this.state.collapse_rhs} />
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case this.PageTypes.UserSettings:
 | 
					                case this.PageTypes.UserSettings:
 | 
				
			||||||
                    page_element = <UserSettings />
 | 
					                    page_element = <UserSettings />
 | 
				
			||||||
                    right_panel = <RightPanel/>
 | 
					                    right_panel = <RightPanel collapsed={this.state.collapse_rhs}/>
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case this.PageTypes.CreateRoom:
 | 
					                case this.PageTypes.CreateRoom:
 | 
				
			||||||
                    page_element = <CreateRoom onRoomCreated={this.onRoomCreated}/>
 | 
					                    page_element = <CreateRoom onRoomCreated={this.onRoomCreated}/>
 | 
				
			||||||
                    right_panel = <RightPanel/>
 | 
					                    right_panel = <RightPanel collapsed={this.state.collapse_rhs}/>
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case this.PageTypes.RoomDirectory:
 | 
					                case this.PageTypes.RoomDirectory:
 | 
				
			||||||
                    page_element = <RoomDirectory />
 | 
					                    page_element = <RoomDirectory />
 | 
				
			||||||
                    right_panel = <RightPanel/>
 | 
					                    right_panel = <RightPanel collapsed={this.state.collapse_rhs}/>
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,7 +133,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
                        <div className="mx_MatrixChat_wrapper">
 | 
					                        <div className="mx_MatrixChat_wrapper">
 | 
				
			||||||
                            <MatrixToolbar />
 | 
					                            <MatrixToolbar />
 | 
				
			||||||
                            <div className="mx_MatrixChat mx_MatrixChat_toolbarShowing">
 | 
					                            <div className="mx_MatrixChat mx_MatrixChat_toolbarShowing">
 | 
				
			||||||
                                <LeftPanel selectedRoom={this.state.currentRoom} />
 | 
					                                <LeftPanel selectedRoom={this.state.currentRoom} collapsed={this.state.collapse_lhs} />
 | 
				
			||||||
                                <main className="mx_MatrixChat_middlePanel">
 | 
					                                <main className="mx_MatrixChat_middlePanel">
 | 
				
			||||||
                                    {page_element}
 | 
					                                    {page_element}
 | 
				
			||||||
                                </main>
 | 
					                                </main>
 | 
				
			||||||
@ -91,7 +145,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
            else {
 | 
					            else {
 | 
				
			||||||
                return (
 | 
					                return (
 | 
				
			||||||
                        <div className="mx_MatrixChat">
 | 
					                        <div className="mx_MatrixChat">
 | 
				
			||||||
                            <LeftPanel selectedRoom={this.state.currentRoom} />
 | 
					                            <LeftPanel selectedRoom={this.state.currentRoom} collapsed={this.state.collapse_lhs} />
 | 
				
			||||||
                            <main className="mx_MatrixChat_middlePanel">
 | 
					                            <main className="mx_MatrixChat_middlePanel">
 | 
				
			||||||
                                {page_element}
 | 
					                                {page_element}
 | 
				
			||||||
                            </main>
 | 
					                            </main>
 | 
				
			||||||
 | 
				
			|||||||
@ -141,6 +141,11 @@ module.exports = React.createClass({
 | 
				
			|||||||
                        </form>
 | 
					                        </form>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					            case 'stage_m.login.cas':
 | 
				
			||||||
 | 
					                var CasLogin = sdk.getComponent('organisms.CasLogin');
 | 
				
			||||||
 | 
					                return (
 | 
				
			||||||
 | 
					                    <CasLogin />
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -19,15 +19,15 @@ limitations under the License.
 | 
				
			|||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var sdk = require('matrix-react-sdk')
 | 
					var sdk = require('matrix-react-sdk')
 | 
				
			||||||
 | 
					var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var Loader = require("react-loader");
 | 
					var Loader = require("react-loader");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var RegisterController = require('matrix-react-sdk/lib/controllers/templates/Register')
 | 
					var RegisterController = require('../../../../controllers/templates/Register')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var config = require('../../../../../config.json');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = React.createClass({
 | 
					module.exports = React.createClass({
 | 
				
			||||||
    DEFAULT_HS_URL: 'https://matrix.org',
 | 
					 | 
				
			||||||
    DEFAULT_IS_URL: 'https://vector.im',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    displayName: 'Register',
 | 
					    displayName: 'Register',
 | 
				
			||||||
    mixins: [RegisterController],
 | 
					    mixins: [RegisterController],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -38,8 +38,8 @@ module.exports = React.createClass({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentWillMount: function() {
 | 
					    componentWillMount: function() {
 | 
				
			||||||
        this.customHsUrl = this.DEFAULT_HS_URL;
 | 
					        this.customHsUrl = config.default_hs_url;
 | 
				
			||||||
        this.customIsUrl = this.DEFAULT_IS_URL;
 | 
					        this.customIsUrl = config.default_is_url;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getRegFormVals: function() {
 | 
					    getRegFormVals: function() {
 | 
				
			||||||
@ -55,7 +55,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
        if (this.state.serverConfigVisible) {
 | 
					        if (this.state.serverConfigVisible) {
 | 
				
			||||||
            return this.customHsUrl;
 | 
					            return this.customHsUrl;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return this.DEFAULT_HS_URL;
 | 
					            return config.default_hs_url;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -63,7 +63,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
        if (this.state.serverConfigVisible) {
 | 
					        if (this.state.serverConfigVisible) {
 | 
				
			||||||
            return this.customIsUrl;
 | 
					            return this.customIsUrl;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return this.DEFAULT_IS_URL;
 | 
					            return config.default_is_url;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,6 +79,10 @@ module.exports = React.createClass({
 | 
				
			|||||||
        this.forceUpdate();
 | 
					        this.forceUpdate();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onProfileContinueClicked: function() {
 | 
				
			||||||
 | 
					        this.onAccountReady();
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentForStep: function(step) {
 | 
					    componentForStep: function(step) {
 | 
				
			||||||
        switch (step) {
 | 
					        switch (step) {
 | 
				
			||||||
            case 'initial':
 | 
					            case 'initial':
 | 
				
			||||||
@ -127,6 +131,18 @@ module.exports = React.createClass({
 | 
				
			|||||||
            return (
 | 
					            return (
 | 
				
			||||||
                <Loader />
 | 
					                <Loader />
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					        } else if (this.state.step == 'profile') {
 | 
				
			||||||
 | 
					            var ChangeDisplayName = sdk.getComponent('molecules.ChangeDisplayName');
 | 
				
			||||||
 | 
					            var ChangeAvatar = sdk.getComponent('molecules.ChangeAvatar');
 | 
				
			||||||
 | 
					            return (
 | 
				
			||||||
 | 
					                <div className="mx_Login_profile">
 | 
				
			||||||
 | 
					                    Set a display name:
 | 
				
			||||||
 | 
					                    <ChangeDisplayName />
 | 
				
			||||||
 | 
					                    Upload an avatar:
 | 
				
			||||||
 | 
					                    <ChangeAvatar initialAvatarUrl={MatrixClientPeg.get().mxcUrlToHttp(this.state.avatarUrl)} />
 | 
				
			||||||
 | 
					                    <button onClick={this.onProfileContinueClicked}>Continue</button>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return (
 | 
					            return (
 | 
				
			||||||
                <div>
 | 
					                <div>
 | 
				
			||||||
@ -156,6 +172,12 @@ module.exports = React.createClass({
 | 
				
			|||||||
                case this.FieldErrors.InUse:
 | 
					                case this.FieldErrors.InUse:
 | 
				
			||||||
                    strings.push(keys[i]+" is already taken");
 | 
					                    strings.push(keys[i]+" is already taken");
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					                case this.FieldErrors.Length:
 | 
				
			||||||
 | 
					                    strings.push(keys[i] + " is not long enough.");
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    console.error("Unhandled FieldError: %s", bad[keys[i]]);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        var errtxt = strings.join(', ');
 | 
					        var errtxt = strings.join(', ');
 | 
				
			||||||
 | 
				
			|||||||
@ -21,24 +21,29 @@ var sdk = require("matrix-react-sdk");
 | 
				
			|||||||
sdk.loadSkin(require('../skins/vector/skindex'));
 | 
					sdk.loadSkin(require('../skins/vector/skindex'));
 | 
				
			||||||
sdk.loadModule(require('../modules/VectorConferenceHandler'));
 | 
					sdk.loadModule(require('../modules/VectorConferenceHandler'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var qs = require("querystring");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var lastLocationHashSet = null;
 | 
					var lastLocationHashSet = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// We want to support some name / value pairs in the fragment
 | 
				
			||||||
 | 
					// so we're re-using query string like format
 | 
				
			||||||
 | 
					function parseQsFromFragment(location) {
 | 
				
			||||||
 | 
					    var hashparts = location.hash.split('?');
 | 
				
			||||||
 | 
					    if (hashparts.length > 1) {
 | 
				
			||||||
 | 
					        return qs.parse(hashparts[1]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Here, we do some crude URL analysis to allow
 | 
					// Here, we do some crude URL analysis to allow
 | 
				
			||||||
// deep-linking. We only support registration
 | 
					// deep-linking. We only support registration
 | 
				
			||||||
// deep-links in this example.
 | 
					// deep-links in this example.
 | 
				
			||||||
function routeUrl(location) {
 | 
					function routeUrl(location) {
 | 
				
			||||||
    if (location.hash.indexOf('#/register') == 0) {
 | 
					    if (location.hash.indexOf('#/register') == 0) {
 | 
				
			||||||
        var hashparts = location.hash.split('?');
 | 
					        window.matrixChat.showScreen('register', parseQsFromFragment(location));
 | 
				
			||||||
        var params = {};
 | 
					    } else if (location.hash.indexOf('#/login/cas') == 0) {
 | 
				
			||||||
        if (hashparts.length == 2) {
 | 
					        window.matrixChat.showScreen('cas_login', parseQsFromFragment(location));
 | 
				
			||||||
            var pairs = hashparts[1].split('&');
 | 
					 | 
				
			||||||
            for (var i = 0; i < pairs.length; ++i) {
 | 
					 | 
				
			||||||
                var parts = pairs[i].split('=');
 | 
					 | 
				
			||||||
                if (parts.length != 2) continue;
 | 
					 | 
				
			||||||
                params[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        window.matrixChat.showScreen('register', params);
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        window.matrixChat.showScreen(location.hash.substring(2));
 | 
					        window.matrixChat.showScreen(location.hash.substring(2));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -53,14 +58,18 @@ function onHashChange(ev) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var loaded = false;
 | 
					var loaded = false;
 | 
				
			||||||
 | 
					var lastLoadedScreen = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This will be called whenever the SDK changes screens,
 | 
					// This will be called whenever the SDK changes screens,
 | 
				
			||||||
// so a web page can update the URL bar appropriately.
 | 
					// so a web page can update the URL bar appropriately.
 | 
				
			||||||
var onNewScreen = function(screen) {
 | 
					var onNewScreen = function(screen) {
 | 
				
			||||||
    if (!loaded) return;
 | 
					    if (!loaded) {
 | 
				
			||||||
 | 
					        lastLoadedScreen = screen;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
        var hash = '#/' + screen;
 | 
					        var hash = '#/' + screen;
 | 
				
			||||||
        lastLocationHashSet = hash;
 | 
					        lastLocationHashSet = hash;
 | 
				
			||||||
        window.location.hash = hash;
 | 
					        window.location.hash = hash;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// We use this to work out what URL the SDK should
 | 
					// We use this to work out what URL the SDK should
 | 
				
			||||||
@ -85,5 +94,9 @@ window.addEventListener('hashchange', onHashChange);
 | 
				
			|||||||
window.onload = function() {
 | 
					window.onload = function() {
 | 
				
			||||||
    routeUrl(window.location);
 | 
					    routeUrl(window.location);
 | 
				
			||||||
    loaded = true;
 | 
					    loaded = true;
 | 
				
			||||||
 | 
					    if (lastLoadedScreen) {
 | 
				
			||||||
 | 
					        onNewScreen(lastLoadedScreen);
 | 
				
			||||||
 | 
					        lastLoadedScreen = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,19 @@ module.exports = {
 | 
				
			|||||||
            { test: /\.js$/, loader: "babel", include: path.resolve('./src') },
 | 
					            { test: /\.js$/, loader: "babel", include: path.resolve('./src') },
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    output: {
 | 
				
			||||||
 | 
					        devtoolModuleFilenameTemplate: function(info) {
 | 
				
			||||||
 | 
					            // Reading input source maps gives only relative paths here for
 | 
				
			||||||
 | 
					            // everything. Until I figure out how to fix this, this is a
 | 
				
			||||||
 | 
					            // workaround.
 | 
				
			||||||
 | 
					            // We use the relative resource path with any '../'s on the front
 | 
				
			||||||
 | 
					            // removed which gives a tree with matrix-react-sdk and vector
 | 
				
			||||||
 | 
					            // trees smashed together, but this fixes everything being under
 | 
				
			||||||
 | 
					            // various levels of '.' and '..'
 | 
				
			||||||
 | 
					            // Also, sometimes the resource path is absolute.
 | 
				
			||||||
 | 
					            return path.relative(process.cwd(), info.resourcePath).replace(/^[\/\.]*/, '');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    resolve: {
 | 
					    resolve: {
 | 
				
			||||||
        alias: {
 | 
					        alias: {
 | 
				
			||||||
            // alias any requires to the react module to the one in our path, otherwise
 | 
					            // alias any requires to the react module to the one in our path, otherwise
 | 
				
			||||||
@ -19,7 +32,12 @@ module.exports = {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    plugins: [
 | 
					    plugins: [
 | 
				
			||||||
        new webpack.IgnorePlugin(/^olm/)
 | 
					        new webpack.IgnorePlugin(/^olm/),
 | 
				
			||||||
 | 
					        new webpack.DefinePlugin({
 | 
				
			||||||
 | 
					            'process.env': {
 | 
				
			||||||
 | 
					                NODE_ENV: JSON.stringify(process.env.NODE_ENV)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    devtool: 'source-map'
 | 
					    devtool: 'source-map'
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||