diff --git a/package.json b/package.json index 8f0f1a5a54..d6be714a8a 100644 --- a/package.json +++ b/package.json @@ -8,18 +8,16 @@ "url": "https://github.com/vector-im/vector-web" }, "license": "Apache-2.0", - "main": "src/index.js", "style": "bundle.css", "scripts": { - "build:skins": "jsx skins build/skins", - "build:logic": "jsx src build/src", - "build:js": "npm run build:skins && npm run build:logic", - "start:js": "jsx -w skins/base/views/ build --source-map-inline", - "build:css": "catw 'skins/base/css/**/*.css' -o bundle.css -c uglifycss --no-watch", - "start:css": "catw 'skins/base/css/**/*.css' -o bundle.css -v", - "build": "npm run build:js && npm run build:css", - "start": "parallelshell \"npm run start:js\" \"npm run start:css\"", - "prepublish": "npm run build" + "reskindex": "reskindex base -h src/skins/base/header", + "build": "NODE_ENV=production browserify --ignore olm -t reactify src/index.js | uglifyjs -c -m -o vector/bundle.js", + "start": "parallelshell 'watchify --ignore olm -v -d -t reactify src/index.js -o vector/bundle.js' 'npm run start:skins:css' 'http-server vector'", + "build:skins:js": "babel src/skins -d lib/skins --source-maps", + "build:skins:css": "catw 'src/skins/base/css/**/*.css' -o vector/bundle.css -c uglifycss --no-watch", + "start:skins:css": "catw 'src/skins/base/css/**/*.css' -o vector/bundle.css", + "clean": "rimraf lib vector/bundle.css vector/bundle.js", + "prepublish": "npm run build:skins" }, "dependencies": { "matrix-react-sdk": "^0.0.1", @@ -32,9 +30,11 @@ "linkifyjs": "^2.0.0-beta.4" }, "devDependencies": { + "babel": "^5.8.23", "catw": "^1.0.1", "parallelshell": "^1.2.0", "react-tools": "^0.13.3", + "rimraf": "^2.4.3", "uglifycss": "0.0.15" } } diff --git a/src/ComponentBroker.js b/src/ComponentBroker.js deleted file mode 100644 index 61499defc7..0000000000 --- a/src/ComponentBroker.js +++ /dev/null @@ -1,115 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -function load(name) { - var module = require("../skins/base/views/"+name); - return module; -}; - -var ComponentBroker = function() { - this.components = {}; -}; - -ComponentBroker.prototype = { - get: function(name) { - if (this.components[name]) { - return this.components[name]; - } - - this.components[name] = load(name); - return this.components[name]; - }, - - set: function(name, module) { - this.components[name] = module; - } -}; - -// We define one Component Broker globally, because the intention is -// very much that it is a singleton. Relying on there only being one -// copy of the module can be dicey and not work as browserify's -// behaviour with multiple copies of files etc. is erratic at best. -// XXX: We can still end up with the same file twice in the resulting -// JS bundle which is nonideal. -if (global.componentBroker === undefined) { - global.componentBroker = new ComponentBroker(); -} -module.exports = global.componentBroker; - -// We need to tell browserify to include all the components -// by direct require syntax in here, but we don't want them -// to be evaluated in this file because then we wouldn't be -// able to override them. if (0) does this. -// Must be in this file (because the require is file-specific) and -// must be at the end because the components include this file. -if (0) { -require('../skins/base/views/atoms/LogoutButton'); -require('../skins/base/views/atoms/EnableNotificationsButton'); -require('../skins/base/views/atoms/MessageTimestamp'); -require('../skins/base/views/atoms/create_room/CreateRoomButton'); -require('../skins/base/views/atoms/create_room/RoomAlias'); -require('../skins/base/views/atoms/create_room/Presets'); -require('../skins/base/views/atoms/EditableText'); -require('../skins/base/views/molecules/MatrixToolbar'); -require('../skins/base/views/molecules/RoomTile'); -require('../skins/base/views/molecules/MessageTile'); -require('../skins/base/views/molecules/SenderProfile'); -require('../skins/base/views/molecules/UnknownMessageTile'); -require('../skins/base/views/molecules/MTextTile'); -require('../skins/base/views/molecules/MNoticeTile'); -require('../skins/base/views/molecules/MEmoteTile'); -require('../skins/base/views/molecules/MImageTile'); -require('../skins/base/views/molecules/MFileTile'); -require('../skins/base/views/molecules/RoomHeader'); -require('../skins/base/views/molecules/MessageComposer'); -require('../skins/base/views/molecules/ProgressBar'); -require('../skins/base/views/molecules/ServerConfig'); -require('../skins/base/views/organisms/MemberList'); -require('../skins/base/views/molecules/MemberTile'); -require('../skins/base/views/organisms/RoomList'); -require('../skins/base/views/organisms/RoomView'); -require('../skins/base/views/templates/Login'); -require('../skins/base/views/templates/Register'); -require('../skins/base/views/organisms/Notifier'); -require('../skins/base/views/organisms/CreateRoom'); -require('../skins/base/views/molecules/UserSelector'); -require('../skins/base/views/organisms/UserSettings'); -require('../skins/base/views/molecules/ChangeAvatar'); -require('../skins/base/views/molecules/ChangePassword'); -require('../skins/base/views/molecules/RoomSettings'); -// new for vector -require('../skins/base/views/organisms/LeftPanel'); -require('../skins/base/views/organisms/RightPanel'); -require('../skins/base/views/organisms/LogoutPrompt'); -require('../skins/base/views/organisms/RoomDirectory'); -require('../skins/base/views/molecules/RoomCreate'); -require('../skins/base/views/molecules/RoomDropTarget'); -require('../skins/base/views/molecules/BottomLeftMenu'); -require('../skins/base/views/molecules/DateSeparator'); -require('../skins/base/views/atoms/voip/VideoFeed'); -require('../skins/base/views/atoms/MemberAvatar'); -require('../skins/base/views/atoms/RoomAvatar'); -require('../skins/base/views/atoms/ImageView'); -require('../skins/base/views/molecules/voip/VideoView'); -require('../skins/base/views/molecules/voip/CallView'); -require('../skins/base/views/molecules/voip/IncomingCallBox'); -require('../skins/base/views/molecules/EventAsTextTile'); -require('../skins/base/views/molecules/MemberInfo'); -require('../skins/base/views/organisms/ErrorDialog'); -require('../skins/base/views/organisms/QuestionDialog'); -} diff --git a/src/ContentMessages.js b/src/ContentMessages.js deleted file mode 100644 index fdd29fd58a..0000000000 --- a/src/ContentMessages.js +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var q = require('q'); -var extend = require('./extend'); - -function infoForImageFile(imageFile) { - var deferred = q.defer(); - - // Load the file into an html element - var img = document.createElement("img"); - - var reader = new FileReader(); - reader.onload = function(e) { - img.src = e.target.result; - - // Once ready, returns its size - img.onload = function() { - deferred.resolve({ - w: img.width, - h: img.height - }); - }; - img.onerror = function(e) { - deferred.reject(e); - }; - }; - reader.onerror = function(e) { - deferred.reject(e); - }; - reader.readAsDataURL(imageFile); - - return deferred.promise; -} - -function sendContentToRoom(file, roomId, matrixClient) { - var content = { - body: file.name, - info: { - size: file.size, - mimetype: file.type - } - }; - - var def = q.defer(); - if (file.type.indexOf('image/') == 0) { - content.msgtype = 'm.image'; - infoForImageFile(file).then(function(imageInfo) { - extend(content.info, imageInfo); - def.resolve(); - }); - } else { - content.msgtype = 'm.file'; - def.resolve(); - } - - return def.promise.then(function() { - return matrixClient.uploadContent(file); - }).then(function(url) { - content.url = url; - return matrixClient.sendMessage(roomId, content); - }); -} - -module.exports = { - sendContentToRoom: sendContentToRoom -}; diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js deleted file mode 100644 index 36ccd0a7dc..0000000000 --- a/src/MatrixClientPeg.js +++ /dev/null @@ -1,101 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -// A thing that holds your Matrix Client -var Matrix = require("matrix-js-sdk"); - -var matrixClient = null; - -var localStorage = window.localStorage; - -function deviceId() { - var id = Math.floor(Math.random()*16777215).toString(16); - id = "W" + "000000".substring(id.length) + id; - if (localStorage) { - id = localStorage.getItem("mx_device_id") || id; - localStorage.setItem("mx_device_id", id); - } - return id; -} - -function createClient(hs_url, is_url, user_id, access_token) { - var opts = { - baseUrl: hs_url, - idBaseUrl: is_url, - accessToken: access_token, - userId: user_id - }; - - if (localStorage) { - opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage); - opts.deviceId = deviceId(); - } - - matrixClient = Matrix.createClient(opts); -} - -if (localStorage) { - var hs_url = localStorage.getItem("mx_hs_url"); - var is_url = localStorage.getItem("mx_is_url") || 'https://matrix.org'; - var access_token = localStorage.getItem("mx_access_token"); - var user_id = localStorage.getItem("mx_user_id"); - if (access_token && user_id && hs_url) { - createClient(hs_url, is_url, user_id, access_token); - } -} - -module.exports = { - get: function() { - return matrixClient; - }, - - unset: function() { - matrixClient = null; - }, - - replaceUsingUrls: function(hs_url, is_url) { - matrixClient = Matrix.createClient({ - baseUrl: hs_url, - idBaseUrl: is_url - }); - }, - - replaceUsingAccessToken: function(hs_url, is_url, user_id, access_token) { - if (localStorage) { - try { - localStorage.clear(); - } catch (e) { - console.warn("Error using local storage"); - } - } - createClient(hs_url, is_url, user_id, access_token); - if (localStorage) { - try { - localStorage.setItem("mx_hs_url", hs_url); - localStorage.setItem("mx_is_url", is_url); - localStorage.setItem("mx_user_id", user_id); - localStorage.setItem("mx_access_token", access_token); - } catch (e) { - console.warn("Error using local storage: can't persist session!"); - } - } else { - console.warn("No local storage available: can't persist session!"); - } - } -}; - diff --git a/src/MatrixTools.js b/src/MatrixTools.js deleted file mode 100644 index fa9f038b08..0000000000 --- a/src/MatrixTools.js +++ /dev/null @@ -1,22 +0,0 @@ -var MatrixClientPeg = require('./MatrixClientPeg'); - -module.exports = { - /** - * Given a room object, return the canonical alias for it - * if there is one. Otherwise return null; - */ - getCanonicalAliasForRoom: function(room) { - var aliasEvents = room.currentState.getStateEvents( - "m.room.aliases" - ); - // Canonical aliases aren't implemented yet, so just return the first - for (var j = 0; j < aliasEvents.length; j++) { - var aliases = aliasEvents[j].getContent().aliases; - if (aliases && aliases.length) { - return aliases[0]; - } - } - return null; - } -} - diff --git a/src/Modal.js b/src/Modal.js deleted file mode 100644 index ba7660bf9d..0000000000 --- a/src/Modal.js +++ /dev/null @@ -1,62 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - - -'use strict'; - -var React = require('react'); -var q = require('q'); - -module.exports = { - DialogContainerId: "mx_Dialog_Container", - - getOrCreateContainer: function() { - var container = document.getElementById(this.DialogContainerId); - - if (!container) { - container = document.createElement("div"); - container.id = this.DialogContainerId; - document.body.appendChild(container); - } - - return container; - }, - - createDialog: function (Element, props) { - var self = this; - - var closeDialog = function() { - React.unmountComponentAtNode(self.getOrCreateContainer()); - - if (props && props.onFinished) props.onFinished.apply(null, arguments); - }; - - // FIXME: If a dialog uses getDefaultProps it clobbers the onFinished - // property set here so you can't close the dialog from a button click! - var dialog = ( -
-
- -
-
-
- ); - - React.render(dialog, this.getOrCreateContainer()); - - return {close: closeDialog}; - }, -}; diff --git a/src/Presence.js b/src/Presence.js deleted file mode 100644 index 558c7e9926..0000000000 --- a/src/Presence.js +++ /dev/null @@ -1,107 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -"use strict"; -var MatrixClientPeg = require("./MatrixClientPeg"); - - // Time in ms after that a user is considered as unavailable/away -var UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins -var PRESENCE_STATES = ["online", "offline", "unavailable"]; - -// The current presence state -var state, timer; - -module.exports = { - - /** - * Start listening the user activity to evaluate his presence state. - * Any state change will be sent to the Home Server. - */ - start: function() { - var self = this; - this.running = true; - if (undefined === state) { - // The user is online if they move the mouse or press a key - document.onmousemove = function() { self._resetTimer(); }; - document.onkeypress = function() { self._resetTimer(); }; - this._resetTimer(); - } - }, - - /** - * Stop tracking user activity - */ - stop: function() { - this.running = false; - if (timer) { - clearTimeout(timer); - timer = undefined; - } - state = undefined; - }, - - /** - * Get the current presence state. - * @returns {string} the presence state (see PRESENCE enum) - */ - getState: function() { - return state; - }, - - /** - * Set the presence state. - * If the state has changed, the Home Server will be notified. - * @param {string} newState the new presence state (see PRESENCE enum) - */ - setState: function(newState) { - if (newState === state) { - return; - } - if (PRESENCE_STATES.indexOf(newState) === -1) { - throw new Error("Bad presence state: " + newState); - } - if (!this.running) { - return; - } - state = newState; - MatrixClientPeg.get().setPresence(state).done(function() { - console.log("Presence: %s", newState); - }, function(err) { - console.error("Failed to set presence: %s", err); - }); - }, - - /** - * Callback called when the user made no action on the page for UNAVAILABLE_TIME ms. - * @private - */ - _onUnavailableTimerFire: function() { - this.setState("unavailable"); - }, - - /** - * Callback called when the user made an action on the page - * @private - */ - _resetTimer: function() { - var self = this; - this.setState("online"); - // Re-arm the timer - clearTimeout(timer); - timer = setTimeout(function() { - self._onUnavailableTimerFire(); - }, UNAVAILABLE_TIME_MS); - } -}; \ No newline at end of file diff --git a/src/RoomListSorter.js b/src/RoomListSorter.js deleted file mode 100644 index 730a0de18b..0000000000 --- a/src/RoomListSorter.js +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -function tsOfNewestEvent(room) { - if (room.timeline.length) { - return room.timeline[room.timeline.length - 1].getTs(); - } - else { - return Number.MAX_SAFE_INTEGER; - } -} - -function mostRecentActivityFirst(roomList) { - return roomList.sort(function(a,b) { - return tsOfNewestEvent(b) - tsOfNewestEvent(a); - }); -} - -module.exports = { - mostRecentActivityFirst: mostRecentActivityFirst -}; diff --git a/src/SlashCommands.js b/src/SlashCommands.js deleted file mode 100644 index b47b953a12..0000000000 --- a/src/SlashCommands.js +++ /dev/null @@ -1,314 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var MatrixClientPeg = require("./MatrixClientPeg"); -var dis = require("./dispatcher"); -var encryption = require("./encryption"); - -var reject = function(msg) { - return { - error: msg - }; -}; - -var success = function(promise) { - return { - promise: promise - }; -}; - -var commands = { - // Change your nickname - nick: function(room_id, args) { - if (args) { - return success( - MatrixClientPeg.get().setDisplayName(args) - ); - } - return reject("Usage: /nick "); - }, - - encrypt: function(room_id, args) { - if (args == "on") { - var client = MatrixClientPeg.get(); - var members = client.getRoom(room_id).currentState.members; - var user_ids = Object.keys(members); - return success( - encryption.enableEncryption(client, room_id, user_ids) - ); - } - if (args == "off") { - var client = MatrixClientPeg.get(); - return success( - encryption.disableEncryption(client, room_id) - ); - - } - return reject("Usage: encrypt "); - }, - - // Change the room topic - topic: function(room_id, args) { - if (args) { - return success( - MatrixClientPeg.get().setRoomTopic(room_id, args) - ); - } - return reject("Usage: /topic "); - }, - - // Invite a user - invite: function(room_id, args) { - if (args) { - var matches = args.match(/^(\S+)$/); - if (matches) { - return success( - MatrixClientPeg.get().invite(room_id, matches[1]) - ); - } - } - return reject("Usage: /invite "); - }, - - // Join a room - join: function(room_id, args) { - if (args) { - var matches = args.match(/^(\S+)$/); - if (matches) { - var room_alias = matches[1]; - if (room_alias[0] !== '#') { - return reject("Usage: /join #alias:domain"); - } - if (!room_alias.match(/:/)) { - var domain = MatrixClientPeg.get().credentials.userId.replace(/^.*:/, ''); - room_alias += ':' + domain; - } - - // Try to find a room with this alias - var rooms = MatrixClientPeg.get().getRooms(); - var roomId; - for (var i = 0; i < rooms.length; i++) { - var aliasEvents = rooms[i].currentState.getStateEvents( - "m.room.aliases" - ); - for (var j = 0; j < aliasEvents.length; j++) { - var aliases = aliasEvents[j].getContent().aliases || []; - for (var k = 0; k < aliases.length; k++) { - if (aliases[k] === room_alias) { - roomId = rooms[i].roomId; - break; - } - } - if (roomId) { break; } - } - if (roomId) { break; } - } - if (roomId) { // we've already joined this room, view it. - dis.dispatch({ - action: 'view_room', - room_id: roomId - }); - return success(); - } - else { - // attempt to join this alias. - return success( - MatrixClientPeg.get().joinRoom(room_alias).then( - function(room) { - dis.dispatch({ - action: 'view_room', - room_id: room.roomId - }); - }) - ); - } - } - } - return reject("Usage: /join "); - }, - - part: function(room_id, args) { - var targetRoomId; - if (args) { - var matches = args.match(/^(\S+)$/); - if (matches) { - var room_alias = matches[1]; - if (room_alias[0] !== '#') { - return reject("Usage: /part [#alias:domain]"); - } - if (!room_alias.match(/:/)) { - var domain = MatrixClientPeg.get().credentials.userId.replace(/^.*:/, ''); - room_alias += ':' + domain; - } - - // Try to find a room with this alias - var rooms = MatrixClientPeg.get().getRooms(); - for (var i = 0; i < rooms.length; i++) { - var aliasEvents = rooms[i].currentState.getStateEvents( - "m.room.aliases" - ); - for (var j = 0; j < aliasEvents.length; j++) { - var aliases = aliasEvents[j].getContent().aliases || []; - for (var k = 0; k < aliases.length; k++) { - if (aliases[k] === room_alias) { - targetRoomId = rooms[i].roomId; - break; - } - } - if (targetRoomId) { break; } - } - if (targetRoomId) { break; } - } - } - if (!targetRoomId) { - return reject("Unrecognised room alias: " + room_alias); - } - } - if (!targetRoomId) targetRoomId = room_id; - return success( - MatrixClientPeg.get().leave(targetRoomId).then( - function() { - dis.dispatch({action: 'view_next_room'}); - }) - ); - }, - - // Kick a user from the room with an optional reason - kick: function(room_id, args) { - if (args) { - var matches = args.match(/^(\S+?)( +(.*))?$/); - if (matches) { - return success( - MatrixClientPeg.get().kick(room_id, matches[1], matches[3]) - ); - } - } - return reject("Usage: /kick []"); - }, - - // Ban a user from the room with an optional reason - ban: function(room_id, args) { - if (args) { - var matches = args.match(/^(\S+?)( +(.*))?$/); - if (matches) { - return success( - MatrixClientPeg.get().ban(room_id, matches[1], matches[3]) - ); - } - } - return reject("Usage: /ban []"); - }, - - // Unban a user from the room - unban: function(room_id, args) { - if (args) { - var matches = args.match(/^(\S+)$/); - if (matches) { - // Reset the user membership to "leave" to unban him - return success( - MatrixClientPeg.get().unban(room_id, matches[1]) - ); - } - } - return reject("Usage: /unban "); - }, - - // Define the power level of a user - op: function(room_id, args) { - if (args) { - var matches = args.match(/^(\S+?)( +(\d+))?$/); - var powerLevel = 50; // default power level for op - if (matches) { - var user_id = matches[1]; - if (matches.length === 4 && undefined !== matches[3]) { - powerLevel = parseInt(matches[3]); - } - if (powerLevel !== NaN) { - var room = MatrixClientPeg.get().getRoom(room_id); - if (!room) { - return reject("Bad room ID: " + room_id); - } - var powerLevelEvent = room.currentState.getStateEvents( - "m.room.power_levels", "" - ); - return success( - MatrixClientPeg.get().setPowerLevel( - room_id, user_id, powerLevel, powerLevelEvent - ) - ); - } - } - } - return reject("Usage: /op []"); - }, - - // Reset the power level of a user - deop: function(room_id, args) { - if (args) { - var matches = args.match(/^(\S+)$/); - if (matches) { - var room = MatrixClientPeg.get().getRoom(room_id); - if (!room) { - return reject("Bad room ID: " + room_id); - } - - var powerLevelEvent = room.currentState.getStateEvents( - "m.room.power_levels", "" - ); - return success( - MatrixClientPeg.get().setPowerLevel( - room_id, args, undefined, powerLevelEvent - ) - ); - } - } - return reject("Usage: /deop "); - } -}; - -// helpful aliases -commands.j = commands.join; - -module.exports = { - /** - * Process the given text for /commands and perform them. - * @param {string} roomId The room in which the command was performed. - * @param {string} input The raw text input by the user. - * @return {Object|null} An object with the property 'error' if there was an error - * processing the command, or 'promise' if a request was sent out. - * Returns null if the input didn't match a command. - */ - processInput: function(roomId, input) { - // trim any trailing whitespace, as it can confuse the parser for - // IRC-style commands - input = input.replace(/\s+$/, ""); - if (input[0] === "/" && input[1] !== "/") { - var bits = input.match(/^(\S+?)( +(.*))?$/); - var cmd = bits[1].substring(1).toLowerCase(); - var args = bits[3]; - if (cmd === "me") return null; - if (commands[cmd]) { - return commands[cmd](roomId, args); - } - else { - return reject("Unrecognised command: " + input); - } - } - return null; // not a command - } -}; diff --git a/src/TextForEvent.js b/src/TextForEvent.js deleted file mode 100644 index 3d6ba2cf64..0000000000 --- a/src/TextForEvent.js +++ /dev/null @@ -1,106 +0,0 @@ - -function textForMemberEvent(ev) { - // XXX: SYJS-16 - var senderName = ev.sender ? ev.sender.name : ev.getSender(); - var targetName = ev.target ? ev.target.name : ev.getStateKey(); - var reason = ev.getContent().reason ? ( - " Reason: " + ev.getContent().reason - ) : ""; - switch (ev.getContent().membership) { - case 'invite': - return senderName + " invited " + targetName + "."; - case 'ban': - return senderName + " banned " + targetName + "." + reason; - case 'join': - if (ev.getPrevContent() && ev.getPrevContent().membership == 'join') { - if (ev.getPrevContent().displayname && ev.getContent().displayname && ev.getPrevContent().displayname != ev.getContent().displayname) { - return ev.getSender() + " changed their display name from " + - ev.getPrevContent().displayname + " to " + - ev.getContent().displayname; - } else if (!ev.getPrevContent().displayname && ev.getContent().displayname) { - return ev.getSender() + " set their display name to " + ev.getContent().displayname; - } else if (ev.getPrevContent().displayname && !ev.getContent().displayname) { - return ev.getSender() + " removed their display name"; - } else if (ev.getPrevContent().avatar_url && !ev.getContent().avatar_url) { - return ev.getSender() + " removed their profile picture"; - } else if (ev.getPrevContent().avatar_url && ev.getContent().avatar_url && ev.getPrevContent().avatar_url != ev.getContent().avatar_url) { - return ev.getSender() + " changed their profile picture"; - } else if (!ev.getPrevContent().avatar_url && ev.getContent().avatar_url) { - return ev.getSender() + " set a profile picture"; - } - } else { - if (!ev.target) console.warn("Join message has no target! -- " + ev.getContent().state_key); - return targetName + " joined the room."; - } - return ''; - case 'leave': - if (ev.getSender() === ev.getStateKey()) { - return targetName + " left the room."; - } - else if (ev.getPrevContent().membership === "ban") { - return senderName + " unbanned " + targetName + "."; - } - else if (ev.getPrevContent().membership === "join") { - return senderName + " kicked " + targetName + "." + reason; - } - else { - return targetName + " left the room."; - } - } -}; - -function textForTopicEvent(ev) { - var senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); - - return senderDisplayName + ' changed the topic to, "' + ev.getContent().topic + '"'; -}; - -function textForMessageEvent(ev) { - var senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); - - var message = senderDisplayName + ': ' + ev.getContent().body; - if (ev.getContent().msgtype === "m.emote") { - message = "* " + senderDisplayName + " " + message; - } else if (ev.getContent().msgtype === "m.image") { - message = senderDisplayName + " sent an image."; - } - return message; -}; - -function textForCallAnswerEvent(event) { - var senderName = event.sender ? event.sender.name : "Someone"; - return senderName + " answered the call."; -}; - -function textForCallHangupEvent(event) { - var senderName = event.sender ? event.sender.name : "Someone"; - return senderName + " ended the call."; -}; - -function textForCallInviteEvent(event) { - var senderName = event.sender ? event.sender.name : "Someone"; - // FIXME: Find a better way to determine this from the event? - var type = "voice"; - if (event.getContent().offer && event.getContent().offer.sdp && - event.getContent().offer.sdp.indexOf('m=video') !== -1) { - type = "video"; - } - return senderName + " placed a " + type + " call."; -}; - -var handlers = { - 'm.room.message': textForMessageEvent, - 'm.room.topic': textForTopicEvent, - 'm.room.member': textForMemberEvent, - 'm.call.invite': textForCallInviteEvent, - 'm.call.answer': textForCallAnswerEvent, - 'm.call.hangup': textForCallHangupEvent, -}; - -module.exports = { - textForEvent: function(ev) { - var hdlr = handlers[ev.getType()]; - if (!hdlr) return ""; - return hdlr(ev); - } -} diff --git a/src/WhoIsTyping.js b/src/WhoIsTyping.js deleted file mode 100644 index 4fb5399027..0000000000 --- a/src/WhoIsTyping.js +++ /dev/null @@ -1,49 +0,0 @@ -var MatrixClientPeg = require("./MatrixClientPeg"); - -module.exports = { - usersTypingApartFromMe: function(room) { - return this.usersTyping( - room, [MatrixClientPeg.get().credentials.userId] - ); - }, - - /** - * Given a Room object and, optionally, a list of userID strings - * to exclude, return a list of user objects who are typing. - */ - usersTyping: function(room, exclude) { - var whoIsTyping = []; - - if (exclude === undefined) { - exclude = []; - } - - var memberKeys = Object.keys(room.currentState.members); - for (var i = 0; i < memberKeys.length; ++i) { - var userId = memberKeys[i]; - - if (room.currentState.members[userId].typing) { - if (exclude.indexOf(userId) == -1) { - whoIsTyping.push(room.currentState.members[userId]); - } - } - } - - return whoIsTyping; - }, - - whoIsTypingString: function(room) { - var whoIsTyping = this.usersTypingApartFromMe(room); - if (whoIsTyping.length == 0) { - return null; - } else if (whoIsTyping.length == 1) { - return whoIsTyping[0].name + ' is typing'; - } else { - var names = whoIsTyping.map(function(m) { - return m.name; - }); - var lastPerson = names.shift(); - return names.join(', ') + ' and ' + lastPerson + ' are typing'; - } - } -} diff --git a/src/controllers/atoms/EditableText.js b/src/controllers/atoms/EditableText.js deleted file mode 100644 index 5ea4ce8c4a..0000000000 --- a/src/controllers/atoms/EditableText.js +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -module.exports = { - propTypes: { - onValueChanged: React.PropTypes.func, - initialValue: React.PropTypes.string, - label: React.PropTypes.string, - placeHolder: React.PropTypes.string, - }, - - Phases: { - Display: "display", - Edit: "edit", - }, - - getDefaultProps: function() { - return { - onValueChanged: function() {}, - initialValue: '', - label: 'Click to set', - placeholder: '', - }; - }, - - getInitialState: function() { - return { - value: this.props.initialValue, - phase: this.Phases.Display, - } - }, - - componentWillReceiveProps: function(nextProps) { - this.setState({ - value: nextProps.initialValue - }); - }, - - getValue: function() { - return this.state.value; - }, - - setValue: function(val, shouldSubmit, suppressListener) { - var self = this; - this.setState({ - value: val, - phase: this.Phases.Display, - }, function() { - if (!suppressListener) { - self.onValueChanged(shouldSubmit); - } - }); - }, - - edit: function() { - this.setState({ - phase: this.Phases.Edit, - }); - }, - - cancelEdit: function() { - this.setState({ - phase: this.Phases.Display, - }); - this.onValueChanged(false); - }, - - onValueChanged: function(shouldSubmit) { - this.props.onValueChanged(this.state.value, shouldSubmit); - }, -}; diff --git a/src/controllers/atoms/EnableNotificationsButton.js b/src/controllers/atoms/EnableNotificationsButton.js deleted file mode 100644 index d6638b2758..0000000000 --- a/src/controllers/atoms/EnableNotificationsButton.js +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; -var ComponentBroker = require("../../ComponentBroker"); -var Notifier = ComponentBroker.get('organisms/Notifier'); -var dis = require("../../dispatcher"); - -module.exports = { - - componentDidMount: function() { - this.dispatcherRef = dis.register(this.onAction); - }, - - componentWillUnmount: function() { - dis.unregister(this.dispatcherRef); - }, - - onAction: function(payload) { - if (payload.action !== "notifier_enabled") { - return; - } - this.forceUpdate(); - }, - - enabled: function() { - return Notifier.isEnabled(); - }, - - onClick: function() { - var self = this; - if (!Notifier.supportsDesktopNotifications()) { - return; - } - if (!Notifier.isEnabled()) { - Notifier.setEnabled(true, function() { - self.forceUpdate(); - }); - } else { - Notifier.setEnabled(false); - } - this.forceUpdate(); - }, -}; diff --git a/src/controllers/atoms/ImageView.js b/src/controllers/atoms/ImageView.js deleted file mode 100644 index d0977e0043..0000000000 --- a/src/controllers/atoms/ImageView.js +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = { -}; diff --git a/src/controllers/atoms/LogoutButton.js b/src/controllers/atoms/LogoutButton.js deleted file mode 100644 index 87cf814801..0000000000 --- a/src/controllers/atoms/LogoutButton.js +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var dis = require("../../dispatcher"); - -module.exports = { - onClick: function() { - dis.dispatch({ - action: 'logout' - }); - }, -}; diff --git a/src/controllers/atoms/MemberAvatar.js b/src/controllers/atoms/MemberAvatar.js deleted file mode 100644 index f29b3544e7..0000000000 --- a/src/controllers/atoms/MemberAvatar.js +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var Avatar = require('../../Avatar'); - -var React = require('react'); - -module.exports = { - propTypes: { - member: React.PropTypes.object.isRequired, - width: React.PropTypes.number, - height: React.PropTypes.number, - resizeMethod: React.PropTypes.string, - }, - - getDefaultProps: function() { - return { - width: 40, - height: 40, - resizeMethod: 'crop' - } - }, - - defaultAvatarUrl: function(member) { - return Avatar.defaultAvatarUrlForString( - member.userId - ); - }, - - onError: function(ev) { - // don't tightloop if the browser can't load a data url - if (ev.target.src == this.defaultAvatarUrl(this.props.member)) { - return; - } - this.setState({ - imageUrl: this.defaultAvatarUrl(this.props.member) - }); - }, - - getInitialState: function() { - return { - imageUrl: Avatar.avatarUrlForMember( - this.props.member, - this.props.width, this.props.height, - this.props.resizeMethod - ) - }; - } -}; diff --git a/src/controllers/atoms/MessageTimestamp.js b/src/controllers/atoms/MessageTimestamp.js deleted file mode 100644 index 8aa688b21e..0000000000 --- a/src/controllers/atoms/MessageTimestamp.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = { -}; - diff --git a/src/controllers/atoms/RoomAvatar.js b/src/controllers/atoms/RoomAvatar.js deleted file mode 100644 index 1504a77613..0000000000 --- a/src/controllers/atoms/RoomAvatar.js +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var MatrixClientPeg = require('../../MatrixClientPeg'); -var Avatar = require('../../Avatar'); - -module.exports = { - getDefaultProps: function() { - return { - width: 40, - height: 40, - resizeMethod: 'crop' - } - }, - - avatarUrlForRoom: function(room) { - var url = MatrixClientPeg.get().getAvatarUrlForRoom( - room, - this.props.width, this.props.height, this.props.resizeMethod, - false - ); - if (url === null) { - url = this.defaultAvatarUrl(room); - } - return url; - }, - - defaultAvatarUrl: function(room) { - return Avatar.defaultAvatarUrlForString( - this.props.room.roomId - ); - }, - - onError: function(ev) { - // don't tightloop if the browser can't load a data url - if (ev.target.src == this.defaultAvatarUrl(this.props.room)) { - return; - } - this.setState({ - imageUrl: this.defaultAvatarUrl(this.props.room) - }); - }, - - getInitialState: function() { - return { - imageUrl: this.avatarUrlForRoom(this.props.room) - }; - } -}; diff --git a/src/controllers/atoms/create_room/CreateRoomButton.js b/src/controllers/atoms/create_room/CreateRoomButton.js deleted file mode 100644 index f03dd56c97..0000000000 --- a/src/controllers/atoms/create_room/CreateRoomButton.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -module.exports = { - propTypes: { - onCreateRoom: React.PropTypes.func, - }, - - getDefaultProps: function() { - return { - onCreateRoom: function() {}, - }; - }, - - onClick: function() { - this.props.onCreateRoom(); - }, -}; diff --git a/src/controllers/atoms/create_room/Presets.js b/src/controllers/atoms/create_room/Presets.js deleted file mode 100644 index bcc2f51481..0000000000 --- a/src/controllers/atoms/create_room/Presets.js +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var Presets = { - PrivateChat: "private_chat", - PublicChat: "public_chat", - Custom: "custom", -}; - -module.exports = { - propTypes: { - onChange: React.PropTypes.func, - preset: React.PropTypes.string - }, - - Presets: Presets, - - getDefaultProps: function() { - return { - onChange: function() {}, - }; - }, -}; diff --git a/src/controllers/atoms/create_room/RoomAlias.js b/src/controllers/atoms/create_room/RoomAlias.js deleted file mode 100644 index 4b268e9024..0000000000 --- a/src/controllers/atoms/create_room/RoomAlias.js +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -module.exports = { - propTypes: { - // Specifying a homeserver will make magical things happen when you, - // e.g. start typing in the room alias box. - homeserver: React.PropTypes.string, - alias: React.PropTypes.string, - onChange: React.PropTypes.func, - }, - - getDefaultProps: function() { - return { - onChange: function() {}, - alias: '', - }; - }, - - getAliasLocalpart: function() { - var room_alias = this.props.alias; - - if (room_alias && this.props.homeserver) { - var suffix = ":" + this.props.homeserver; - if (room_alias.startsWith("#") && room_alias.endsWith(suffix)) { - room_alias = room_alias.slice(1, -suffix.length); - } - } - - return room_alias; - }, -}; diff --git a/src/controllers/atoms/voip/VideoFeed.js b/src/controllers/atoms/voip/VideoFeed.js deleted file mode 100644 index 8aa688b21e..0000000000 --- a/src/controllers/atoms/voip/VideoFeed.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = { -}; - diff --git a/src/controllers/molecules/ChangeAvatar.js b/src/controllers/molecules/ChangeAvatar.js deleted file mode 100644 index 72a541b1af..0000000000 --- a/src/controllers/molecules/ChangeAvatar.js +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var MatrixClientPeg = require("../../MatrixClientPeg"); - -var dis = require("../../dispatcher"); - -module.exports = { - propTypes: { - onFinished: React.PropTypes.func, - initialAvatarUrl: React.PropTypes.string.isRequired, - }, - - Phases: { - Display: "display", - Uploading: "uploading", - Error: "error", - }, - - getDefaultProps: function() { - return { - onFinished: function() {}, - }; - }, - - getInitialState: function() { - return { - avatarUrl: this.props.initialAvatarUrl, - phase: this.Phases.Display, - } - }, - - setAvatarFromFile: function(file) { - var newUrl = null; - - this.setState({ - phase: this.Phases.Uploading - }); - var self = this; - MatrixClientPeg.get().uploadContent(file).then(function(url) { - newUrl = url; - return MatrixClientPeg.get().setAvatarUrl(url); - }).done(function() { - self.setState({ - phase: self.Phases.Display, - avatarUrl: MatrixClientPeg.get().mxcUrlToHttp(newUrl) - }); - }, function(error) { - self.setState({ - phase: this.Phases.Error - }); - self.onError(error); - }); - }, -} diff --git a/src/controllers/molecules/ChangePassword.js b/src/controllers/molecules/ChangePassword.js deleted file mode 100644 index 5cc73c5def..0000000000 --- a/src/controllers/molecules/ChangePassword.js +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); -var MatrixClientPeg = require("../../MatrixClientPeg"); - -var dis = require("../../dispatcher"); - -module.exports = { - propTypes: { - onFinished: React.PropTypes.func, - }, - - Phases: { - Edit: "edit", - Uploading: "uploading", - Error: "error", - Success: "Success" - }, - - getDefaultProps: function() { - return { - onFinished: function() {}, - }; - }, - - getInitialState: function() { - return { - phase: this.Phases.Edit, - errorString: '' - } - }, - - changePassword: function(old_password, new_password) { - var cli = MatrixClientPeg.get(); - - var authDict = { - type: 'm.login.password', - user: cli.credentials.userId, - password: old_password - }; - - this.setState({ - phase: this.Phases.Uploading, - errorString: '', - }) - - var d = cli.setPassword(authDict, new_password); - - var self = this; - d.then(function() { - self.setState({ - phase: self.Phases.Success, - errorString: '', - }) - }, function(err) { - self.setState({ - phase: self.Phases.Error, - errorString: err.toString() - }) - }); - }, -} diff --git a/src/controllers/molecules/EventAsTextTile.js b/src/controllers/molecules/EventAsTextTile.js deleted file mode 100644 index 8aa688b21e..0000000000 --- a/src/controllers/molecules/EventAsTextTile.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = { -}; - diff --git a/src/controllers/molecules/MEmoteTile.js b/src/controllers/molecules/MEmoteTile.js deleted file mode 100644 index 1fb117ceef..0000000000 --- a/src/controllers/molecules/MEmoteTile.js +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var linkify = require('linkifyjs'); -var linkifyElement = require('linkifyjs/element'); -var linkifyMatrix = require('../../linkify-matrix'); - -linkifyMatrix(linkify); - -module.exports = { - componentDidMount: function() { - linkifyElement(this.refs.content.getDOMNode(), linkifyMatrix.options); - } -}; - diff --git a/src/controllers/molecules/MFileTile.js b/src/controllers/molecules/MFileTile.js deleted file mode 100644 index bd3576e575..0000000000 --- a/src/controllers/molecules/MFileTile.js +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var filesize = require('filesize'); - -module.exports = { - presentableTextForFile: function(content) { - var linkText = 'Attachment'; - if (content.body && content.body.length > 0) { - linkText = content.body; - } - - var additionals = []; - if (content.info) { - if (content.info.mimetype && content.info.mimetype.length > 0) { - additionals.push(content.info.mimetype); - } - if (content.info.size) { - additionals.push(filesize(content.info.size)); - } - } - - if (additionals.length > 0) { - linkText += ' (' + additionals.join(', ') + ')'; - } - return linkText; - } -}; - diff --git a/src/controllers/molecules/MImageTile.js b/src/controllers/molecules/MImageTile.js deleted file mode 100644 index 8aa688b21e..0000000000 --- a/src/controllers/molecules/MImageTile.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = { -}; - diff --git a/src/controllers/molecules/MNoticeTile.js b/src/controllers/molecules/MNoticeTile.js deleted file mode 100644 index aceb029495..0000000000 --- a/src/controllers/molecules/MNoticeTile.js +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var linkify = require('linkifyjs'); -var linkifyElement = require('linkifyjs/element'); -var linkifyMatrix = require('../../linkify-matrix.js'); -linkifyMatrix(linkify); - -module.exports = { - componentDidMount: function() { - linkifyElement(this.refs.content.getDOMNode(), linkifyMatrix.options); - } -}; diff --git a/src/controllers/molecules/MTextTile.js b/src/controllers/molecules/MTextTile.js deleted file mode 100644 index 1fb117ceef..0000000000 --- a/src/controllers/molecules/MTextTile.js +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var linkify = require('linkifyjs'); -var linkifyElement = require('linkifyjs/element'); -var linkifyMatrix = require('../../linkify-matrix'); - -linkifyMatrix(linkify); - -module.exports = { - componentDidMount: function() { - linkifyElement(this.refs.content.getDOMNode(), linkifyMatrix.options); - } -}; - diff --git a/src/controllers/molecules/MatrixToolbar.js b/src/controllers/molecules/MatrixToolbar.js deleted file mode 100644 index 8aa688b21e..0000000000 --- a/src/controllers/molecules/MatrixToolbar.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = { -}; - diff --git a/src/controllers/molecules/MemberInfo.js b/src/controllers/molecules/MemberInfo.js deleted file mode 100644 index 21cbe7a54f..0000000000 --- a/src/controllers/molecules/MemberInfo.js +++ /dev/null @@ -1,319 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/* - * State vars: - * 'can': { - * kick: boolean, - * ban: boolean, - * mute: boolean, - * modifyLevel: boolean - * }, - * 'muted': boolean, - * 'isTargetMod': boolean - */ - -'use strict'; -var MatrixClientPeg = require("../../MatrixClientPeg"); -var dis = require("../../dispatcher"); -var Modal = require("../../Modal"); -var ComponentBroker = require('../../ComponentBroker'); -var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog"); -var QuestionDialog = ComponentBroker.get("organisms/QuestionDialog"); -var Loader = require("react-loader"); - -module.exports = { - componentDidMount: function() { - var self = this; - - // work out the current state - if (this.props.member) { - var usr = MatrixClientPeg.get().getUser(this.props.member.userId) || {}; - var memberState = this._calculateOpsPermissions(); - this.setState(memberState); - } - }, - - onKick: function() { - var roomId = this.props.member.roomId; - var target = this.props.member.userId; - var self = this; - MatrixClientPeg.get().kick(roomId, target).done(function() { - // NO-OP; rely on the m.room.member event coming down else we could - // get out of sync if we force setState here! - console.log("Kick success"); - }, function(err) { - Modal.createDialog(ErrorDialog, { - title: "Kick error", - description: err.message - }); - }); - this.props.onFinished(); - }, - - onBan: function() { - var roomId = this.props.member.roomId; - var target = this.props.member.userId; - var self = this; - MatrixClientPeg.get().ban(roomId, target).done(function() { - // NO-OP; rely on the m.room.member event coming down else we could - // get out of sync if we force setState here! - console.log("Ban success"); - }, function(err) { - Modal.createDialog(ErrorDialog, { - title: "Ban error", - description: err.message - }); - }); - this.props.onFinished(); - }, - - onMuteToggle: function() { - var roomId = this.props.member.roomId; - var target = this.props.member.userId; - var self = this; - var room = MatrixClientPeg.get().getRoom(roomId); - if (!room) { - this.props.onFinished(); - return; - } - var powerLevelEvent = room.currentState.getStateEvents( - "m.room.power_levels", "" - ); - if (!powerLevelEvent) { - this.props.onFinished(); - return; - } - var isMuted = this.state.muted; - var powerLevels = powerLevelEvent.getContent(); - var levelToSend = ( - (powerLevels.events ? powerLevels.events["m.room.message"] : null) || - powerLevels.events_default - ); - var level; - if (isMuted) { // unmute - level = levelToSend; - } - else { // mute - level = levelToSend - 1; - } - - MatrixClientPeg.get().setPowerLevel(roomId, target, level, powerLevelEvent).done( - function() { - // NO-OP; rely on the m.room.member event coming down else we could - // get out of sync if we force setState here! - console.log("Mute toggle success"); - }, function(err) { - Modal.createDialog(ErrorDialog, { - title: "Mute error", - description: err.message - }); - }); - this.props.onFinished(); - }, - - onModToggle: function() { - var roomId = this.props.member.roomId; - var target = this.props.member.userId; - var room = MatrixClientPeg.get().getRoom(roomId); - if (!room) { - this.props.onFinished(); - return; - } - var powerLevelEvent = room.currentState.getStateEvents( - "m.room.power_levels", "" - ); - if (!powerLevelEvent) { - this.props.onFinished(); - return; - } - var me = room.getMember(MatrixClientPeg.get().credentials.userId); - if (!me) { - this.props.onFinished(); - return; - } - var defaultLevel = powerLevelEvent.getContent().users_default; - var modLevel = me.powerLevel - 1; - // toggle the level - var newLevel = this.state.isTargetMod ? defaultLevel : modLevel; - MatrixClientPeg.get().setPowerLevel(roomId, target, newLevel, powerLevelEvent).done( - function() { - // NO-OP; rely on the m.room.member event coming down else we could - // get out of sync if we force setState here! - console.log("Mod toggle success"); - }, function(err) { - Modal.createDialog(ErrorDialog, { - title: "Mod error", - description: err.message - }); - }); - this.props.onFinished(); - }, - - onChatClick: function() { - // check if there are any existing rooms with just us and them (1:1) - // If so, just view that room. If not, create a private room with them. - var rooms = MatrixClientPeg.get().getRooms(); - var userIds = [ - this.props.member.userId, - MatrixClientPeg.get().credentials.userId - ]; - var existingRoomId = null; - for (var i = 0; i < rooms.length; i++) { - var members = rooms[i].getJoinedMembers(); - if (members.length === 2) { - var hasTargetUsers = true; - for (var j = 0; j < members.length; j++) { - if (userIds.indexOf(members[j].userId) === -1) { - hasTargetUsers = false; - break; - } - } - if (hasTargetUsers) { - existingRoomId = rooms[i].roomId; - break; - } - } - } - - if (existingRoomId) { - dis.dispatch({ - action: 'view_room', - room_id: existingRoomId - }); - } - else { - MatrixClientPeg.get().createRoom({ - invite: [this.props.member.userId], - preset: "private_chat" - }).done(function(res) { - dis.dispatch({ - action: 'view_room', - room_id: res.room_id - }); - }, function(err) { - console.error( - "Failed to create room: %s", JSON.stringify(err) - ); - }); - } - this.props.onFinished(); - }, - - // FIXME: this is horribly duplicated with MemberTile's onLeaveClick. - // Not sure what the right solution to this is. - onLeaveClick: function() { - var roomId = this.props.member.roomId; - Modal.createDialog(QuestionDialog, { - title: "Leave room", - description: "Are you sure you want to leave the room?", - onFinished: function(should_leave) { - if (should_leave) { - var d = MatrixClientPeg.get().leave(roomId); - - var modal = Modal.createDialog(Loader); - - d.then(function() { - modal.close(); - dis.dispatch({action: 'view_next_room'}); - }, function(err) { - modal.close(); - Modal.createDialog(ErrorDialog, { - title: "Failed to leave room", - description: err.toString() - }); - }); - } - } - }); - this.props.onFinished(); - }, - - getInitialState: function() { - return { - can: { - kick: false, - ban: false, - mute: false, - modifyLevel: false - }, - muted: false, - isTargetMod: false - } - }, - - _calculateOpsPermissions: function() { - var defaultPerms = { - can: {}, - muted: false, - modifyLevel: false - }; - var room = MatrixClientPeg.get().getRoom(this.props.member.roomId); - if (!room) { - return defaultPerms; - } - var powerLevels = room.currentState.getStateEvents( - "m.room.power_levels", "" - ); - if (!powerLevels) { - return defaultPerms; - } - var me = room.getMember(MatrixClientPeg.get().credentials.userId); - var them = this.props.member; - return { - can: this._calculateCanPermissions( - me, them, powerLevels.getContent() - ), - muted: this._isMuted(them, powerLevels.getContent()), - isTargetMod: them.powerLevel > powerLevels.getContent().users_default - }; - }, - - _calculateCanPermissions: function(me, them, powerLevels) { - var can = { - kick: false, - ban: false, - mute: false, - modifyLevel: false - }; - var canAffectUser = them.powerLevel < me.powerLevel; - if (!canAffectUser) { - //console.log("Cannot affect user: %s >= %s", them.powerLevel, me.powerLevel); - return can; - } - var editPowerLevel = ( - (powerLevels.events ? powerLevels.events["m.room.power_levels"] : null) || - powerLevels.state_default - ); - can.kick = me.powerLevel >= powerLevels.kick; - can.ban = me.powerLevel >= powerLevels.ban; - can.mute = me.powerLevel >= editPowerLevel; - can.modifyLevel = me.powerLevel > them.powerLevel; - return can; - }, - - _isMuted: function(member, powerLevelContent) { - if (!powerLevelContent || !member) { - return false; - } - var levelToSend = ( - (powerLevelContent.events ? powerLevelContent.events["m.room.message"] : null) || - powerLevelContent.events_default - ); - return member.powerLevel < levelToSend; - } -}; - diff --git a/src/controllers/molecules/MemberTile.js b/src/controllers/molecules/MemberTile.js deleted file mode 100644 index 43db7d1dba..0000000000 --- a/src/controllers/molecules/MemberTile.js +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var dis = require("../../dispatcher"); -var Modal = require("../../Modal"); -var ComponentBroker = require('../../ComponentBroker'); -var QuestionDialog = ComponentBroker.get("organisms/QuestionDialog"); -var Loader = require("react-loader"); - -var MatrixClientPeg = require("../../MatrixClientPeg"); - -module.exports = { - // onClick: function() { - // dis.dispatch({ - // action: 'view_user', - // user_id: this.props.member.userId - // }); - // }, - - getInitialState: function() { - return { - hover: false, - menu: false, - } - }, - - onLeaveClick: function(ev) { - ev.stopPropagation(); - ev.preventDefault(); - var roomId = this.props.member.roomId; - Modal.createDialog(QuestionDialog, { - title: "Leave room", - description: "Are you sure you want to leave the room?", - onFinished: function(should_leave) { - if (should_leave) { - var d = MatrixClientPeg.get().leave(roomId); - - var modal = Modal.createDialog(Loader); - - d.then(function() { - modal.close(); - dis.dispatch({action: 'view_next_room'}); - }, function(err) { - modal.close(); - Modal.createDialog(ErrorDialog, { - title: "Failed to leave room", - description: err.toString() - }); - }); - } - } - }); - } -}; diff --git a/src/controllers/molecules/MessageComposer.js b/src/controllers/molecules/MessageComposer.js deleted file mode 100644 index 3bd0f7f8e8..0000000000 --- a/src/controllers/molecules/MessageComposer.js +++ /dev/null @@ -1,414 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var MatrixClientPeg = require("../../MatrixClientPeg"); -var SlashCommands = require("../../SlashCommands"); -var Modal = require("../../Modal"); -var ComponentBroker = require('../../ComponentBroker'); -var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog"); - -var dis = require("../../dispatcher"); -var KeyCode = { - ENTER: 13, - TAB: 9, - SHIFT: 16, - UP: 38, - DOWN: 40 -}; - -var TYPING_USER_TIMEOUT = 10000; -var TYPING_SERVER_TIMEOUT = 30000; - -module.exports = { - componentWillMount: function() { - this.tabStruct = { - completing: false, - original: null, - index: 0 - }; - this.sentHistory = { - // The list of typed messages. Index 0 is more recent - data: [], - // The position in data currently displayed - position: -1, - // The room the history is for. - roomId: null, - // The original text before they hit UP - originalText: null, - // The textarea element to set text to. - element: null, - - init: function(element, roomId) { - this.roomId = roomId; - this.element = element; - this.position = -1; - var storedData = window.sessionStorage.getItem( - "history_" + roomId - ); - if (storedData) { - this.data = JSON.parse(storedData); - } - if (this.roomId) { - this.setLastTextEntry(); - } - }, - - push: function(text) { - // store a message in the sent history - this.data.unshift(text); - window.sessionStorage.setItem( - "history_" + this.roomId, - JSON.stringify(this.data) - ); - // reset history position - this.position = -1; - this.originalText = null; - }, - - // move in the history. Returns true if we managed to move. - next: function(offset) { - if (this.position === -1) { - // user is going into the history, save the current line. - this.originalText = this.element.value; - } - else { - // user may have modified this line in the history; remember it. - this.data[this.position] = this.element.value; - } - - if (offset > 0 && this.position === (this.data.length - 1)) { - // we've run out of history - return false; - } - - // retrieve the next item (bounded). - var newPosition = this.position + offset; - newPosition = Math.max(-1, newPosition); - newPosition = Math.min(newPosition, this.data.length - 1); - this.position = newPosition; - - if (this.position !== -1) { - // show the message - this.element.value = this.data[this.position]; - } - else if (this.originalText !== undefined) { - // restore the original text the user was typing. - this.element.value = this.originalText; - } - return true; - }, - - saveLastTextEntry: function() { - // save the currently entered text in order to restore it later. - // NB: This isn't 'originalText' because we want to restore - // sent history items too! - var text = this.element.value; - window.sessionStorage.setItem("input_" + this.roomId, text); - }, - - setLastTextEntry: function() { - var text = window.sessionStorage.getItem("input_" + this.roomId); - if (text) { - this.element.value = text; - } - } - }; - }, - - componentDidMount: function() { - this.dispatcherRef = dis.register(this.onAction); - this.sentHistory.init( - this.refs.textarea.getDOMNode(), - this.props.room.roomId - ); - }, - - componentWillUnmount: function() { - dis.unregister(this.dispatcherRef); - this.sentHistory.saveLastTextEntry(); - }, - - onAction: function(payload) { - switch (payload.action) { - case 'focus_composer': - this.refs.textarea.getDOMNode().focus(); - break; - } - }, - - onKeyDown: function (ev) { - if (ev.keyCode === KeyCode.ENTER) { - var input = this.refs.textarea.getDOMNode().value; - if (input.length === 0) { - ev.preventDefault(); - return; - } - this.sentHistory.push(input); - this.onEnter(ev); - } - else if (ev.keyCode === KeyCode.TAB) { - var members = []; - if (this.props.room) { - members = this.props.room.getJoinedMembers(); - } - this.onTab(ev, members); - } - else if (ev.keyCode === KeyCode.UP || ev.keyCode === KeyCode.DOWN) { - this.sentHistory.next( - ev.keyCode === KeyCode.UP ? 1 : -1 - ); - ev.preventDefault(); - } - else if (ev.keyCode !== KeyCode.SHIFT && this.tabStruct.completing) { - // they're resuming typing; reset tab complete state vars. - this.tabStruct.completing = false; - this.tabStruct.index = 0; - } - - var self = this; - setTimeout(function() { - if (self.refs.textarea && self.refs.textarea.getDOMNode().value != '') { - self.onTypingActivity(); - } else { - self.onFinishedTyping(); - } - }, 10); // XXX: what is this 10ms setTimeout doing? Looks hacky :( - }, - - onEnter: function(ev) { - var contentText = this.refs.textarea.getDOMNode().value; - - var cmd = SlashCommands.processInput(this.props.room.roomId, contentText); - if (cmd) { - ev.preventDefault(); - if (!cmd.error) { - this.refs.textarea.getDOMNode().value = ''; - } - if (cmd.promise) { - cmd.promise.done(function() { - console.log("Command success."); - }, function(err) { - console.error("Command failure: %s", err); - Modal.createDialog(ErrorDialog, { - title: "Server error", - description: err.message - }); - }); - } - else if (cmd.error) { - console.error(cmd.error); - Modal.createDialog(ErrorDialog, { - title: "Command error", - description: cmd.error - }); - } - return; - } - - var content = null; - if (/^\/me /i.test(contentText)) { - content = { - msgtype: 'm.emote', - body: contentText.substring(4) - }; - } else { - content = { - msgtype: 'm.text', - body: contentText - }; - } - - MatrixClientPeg.get().sendMessage(this.props.room.roomId, content).then(function() { - dis.dispatch({ - action: 'message_sent' - }); - }, function() { - dis.dispatch({ - action: 'message_send_failed' - }); - }); - this.refs.textarea.getDOMNode().value = ''; - ev.preventDefault(); - }, - - onTab: function(ev, sortedMembers) { - var textArea = this.refs.textarea.getDOMNode(); - if (!this.tabStruct.completing) { - this.tabStruct.completing = true; - this.tabStruct.index = 0; - // cache starting text - this.tabStruct.original = textArea.value; - } - - // loop in the right direction - if (ev.shiftKey) { - this.tabStruct.index --; - if (this.tabStruct.index < 0) { - // wrap to the last search match, and fix up to a real index - // value after we've matched. - this.tabStruct.index = Number.MAX_VALUE; - } - } - else { - this.tabStruct.index++; - } - - var searchIndex = 0; - var targetIndex = this.tabStruct.index; - var text = this.tabStruct.original; - - var search = /@?([a-zA-Z0-9_\-:\.]+)$/.exec(text); - // console.log("Searched in '%s' - got %s", text, search); - if (targetIndex === 0) { // 0 is always the original text - textArea.value = text; - } - else if (search && search[1]) { - // console.log("search found: " + search+" from "+text); - var expansion; - - // FIXME: could do better than linear search here - for (var i=0; i= targetIndex) { - break; - } - var userId = sortedMembers[i].userId; - // === 1 because mxids are @username - if (userId.toLowerCase().indexOf(search[1].toLowerCase()) === 1) { - expansion = userId; - searchIndex++; - } - } - } - - if (searchIndex === targetIndex || - targetIndex === Number.MAX_VALUE) { - // xchat-style tab complete, add a colon if tab - // completing at the start of the text - if (search[0].length === text.length) { - expansion += ": "; - } - else { - expansion += " "; - } - textArea.value = text.replace( - /@?([a-zA-Z0-9_\-:\.]+)$/, expansion - ); - // cancel blink - textArea.style["background-color"] = ""; - if (targetIndex === Number.MAX_VALUE) { - // wrap the index around to the last index found - this.tabStruct.index = searchIndex; - targetIndex = searchIndex; - } - } - else { - // console.log("wrapped!"); - textArea.style["background-color"] = "#faa"; - setTimeout(function() { - textArea.style["background-color"] = ""; - }, 150); - textArea.value = text; - this.tabStruct.index = 0; - } - } - else { - this.tabStruct.index = 0; - } - // prevent the default TAB operation (typically focus shifting) - ev.preventDefault(); - }, - - onTypingActivity: function() { - this.isTyping = true; - if (!this.userTypingTimer) { - this.sendTyping(true); - } - this.startUserTypingTimer(); - this.startServerTypingTimer(); - }, - - onFinishedTyping: function() { - this.isTyping = false; - this.sendTyping(false); - this.stopUserTypingTimer(); - this.stopServerTypingTimer(); - }, - - startUserTypingTimer: function() { - this.stopUserTypingTimer(); - var self = this; - this.userTypingTimer = setTimeout(function() { - self.isTyping = false; - self.sendTyping(self.isTyping); - self.userTypingTimer = null; - }, TYPING_USER_TIMEOUT); - }, - - stopUserTypingTimer: function() { - if (this.userTypingTimer) { - clearTimeout(this.userTypingTimer); - this.userTypingTimer = null; - } - }, - - startServerTypingTimer: function() { - if (!this.serverTypingTimer) { - var self = this; - this.serverTypingTimer = setTimeout(function() { - if (self.isTyping) { - self.sendTyping(self.isTyping); - self.startServerTypingTimer(); - } - }, TYPING_SERVER_TIMEOUT / 2); - } - }, - - stopServerTypingTimer: function() { - if (this.serverTypingTimer) { - clearTimeout(this.servrTypingTimer); - this.serverTypingTimer = null; - } - }, - - sendTyping: function(isTyping) { - MatrixClientPeg.get().sendTyping( - this.props.room.roomId, - this.isTyping, TYPING_SERVER_TIMEOUT - ).done(); - }, - - refreshTyping: function() { - if (this.typingTimeout) { - clearTimeout(this.typingTimeout); - this.typingTimeout = null; - } - - } -}; - diff --git a/src/controllers/molecules/MessageTile.js b/src/controllers/molecules/MessageTile.js deleted file mode 100644 index 47b616e724..0000000000 --- a/src/controllers/molecules/MessageTile.js +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var MatrixClientPeg = require("../../MatrixClientPeg"); - -module.exports = { - shouldHighlight: function() { - var actions = MatrixClientPeg.get().getPushActionsForEvent(this.props.mxEvent); - if (!actions || !actions.tweaks) { return false; } - return actions.tweaks.highlight; - }, - - getInitialState: function() { - return { - resending: false - }; - }, - - onResend: function() { - var self = this; - self.setState({ - resending: true - }); - MatrixClientPeg.get().resendEvent( - this.props.mxEvent, MatrixClientPeg.get().getRoom( - this.props.mxEvent.getRoomId() - ) - ).finally(function() { - self.setState({ - resending: false - }); - }) - } -}; - diff --git a/src/controllers/molecules/ProgressBar.js b/src/controllers/molecules/ProgressBar.js deleted file mode 100644 index c711650a25..0000000000 --- a/src/controllers/molecules/ProgressBar.js +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -module.exports = { - propTypes: { - value: React.PropTypes.number, - max: React.PropTypes.number - }, -}; diff --git a/src/controllers/molecules/RoomHeader.js b/src/controllers/molecules/RoomHeader.js deleted file mode 100644 index c7e023fc33..0000000000 --- a/src/controllers/molecules/RoomHeader.js +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -/* - * State vars: - * this.state.call_state = the UI state of the call (see CallHandler) - * - * Props: - * room (JS SDK Room) - */ - -var React = require('react'); -var dis = require("../../dispatcher"); -var CallHandler = require("../../CallHandler"); - -module.exports = { - propTypes: { - room: React.PropTypes.object.isRequired, - editing: React.PropTypes.bool, - onSettingsClick: React.PropTypes.func, - onSaveClick: React.PropTypes.func, - }, - - getDefaultProps: function() { - return { - editing: false, - onSettingsClick: function() {}, - onSaveClick: function() {}, - }; - }, - - componentDidMount: function() { - this.dispatcherRef = dis.register(this.onAction); - if (this.props.room) { - var call = CallHandler.getCallForRoom(this.props.room.roomId); - var callState = call ? call.call_state : "ended"; - this.setState({ - call_state: callState - }); - } - }, - - componentWillUnmount: function() { - dis.unregister(this.dispatcherRef); - }, - - onAction: function(payload) { - // don't filter out payloads for room IDs other than props.room because - // we may be interested in the conf 1:1 room - if (payload.action !== 'call_state' || !payload.room_id) { - return; - } - var call = CallHandler.getCallForRoom(payload.room_id); - var callState = call ? call.call_state : "ended"; - this.setState({ - call_state: callState - }); - }, - - onVideoClick: function() { - dis.dispatch({ - action: 'place_call', - type: "video", - room_id: this.props.room.roomId - }); - }, - onVoiceClick: function() { - dis.dispatch({ - action: 'place_call', - type: "voice", - room_id: this.props.room.roomId - }); - }, - onHangupClick: function() { - var call = CallHandler.getCallForRoom(this.props.room.roomId); - if (!call) { return; } - dis.dispatch({ - action: 'hangup', - // hangup the call for this room, which may not be the room in props - // (e.g. conferences which will hangup the 1:1 room instead) - room_id: call.roomId - }); - } -}; diff --git a/src/controllers/molecules/RoomSettings.js b/src/controllers/molecules/RoomSettings.js deleted file mode 100644 index fe7cd63430..0000000000 --- a/src/controllers/molecules/RoomSettings.js +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -module.exports = { - propTypes: { - room: React.PropTypes.object.isRequired, - }, - - getInitialState: function() { - return { - power_levels_changed: false - }; - } -}; diff --git a/src/controllers/molecules/RoomTile.js b/src/controllers/molecules/RoomTile.js deleted file mode 100644 index 78927ec55e..0000000000 --- a/src/controllers/molecules/RoomTile.js +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var dis = require("../../dispatcher"); - -module.exports = { - onClick: function() { - dis.dispatch({ - action: 'view_room', - room_id: this.props.room.roomId - }); - }, -}; diff --git a/src/controllers/molecules/SenderProfile.js b/src/controllers/molecules/SenderProfile.js deleted file mode 100644 index 8aa688b21e..0000000000 --- a/src/controllers/molecules/SenderProfile.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = { -}; - diff --git a/src/controllers/molecules/ServerConfig.js b/src/controllers/molecules/ServerConfig.js deleted file mode 100644 index 3f5dd99bb5..0000000000 --- a/src/controllers/molecules/ServerConfig.js +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require("react"); - -module.exports = { - propTypes: { - onHsUrlChanged: React.PropTypes.func, - onIsUrlChanged: React.PropTypes.func, - default_hs_url: React.PropTypes.string, - default_is_url: React.PropTypes.string - }, - - getDefaultProps: function() { - return { - onHsUrlChanged: function() {}, - onIsUrlChanged: function() {}, - defaultHsUrl: 'https://matrix.org/', - defaultIsUrl: 'https://matrix.org/' - }; - }, - - getInitialState: function() { - return { - hs_url: this.props.defaultHsUrl, - is_url: this.props.defaultIsUrl, - } - }, - - hsChanged: function(ev) { - this.setState({hs_url: ev.target.value}, function() { - this.props.onHsUrlChanged(this.state.hs_url); - }); - }, - - isChanged: function(ev) { - this.setState({is_url: ev.target.value}, function() { - this.props.onIsUrlChanged(this.state.is_url); - }); - }, - - getHsUrl: function() { - return this.state.hs_url; - }, - - getIsUrl: function() { - return this.state.is_url; - }, -}; diff --git a/src/controllers/molecules/UnknownMessageTile.js b/src/controllers/molecules/UnknownMessageTile.js deleted file mode 100644 index d0977e0043..0000000000 --- a/src/controllers/molecules/UnknownMessageTile.js +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = { -}; diff --git a/src/controllers/molecules/UserSelector.js b/src/controllers/molecules/UserSelector.js deleted file mode 100644 index 67a56163fa..0000000000 --- a/src/controllers/molecules/UserSelector.js +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -module.exports = { - propTypes: { - onChange: React.PropTypes.func, - selected_users: React.PropTypes.arrayOf(React.PropTypes.string), - }, - - getDefaultProps: function() { - return { - onChange: function() {}, - selected: [], - }; - }, - - addUser: function(user_id) { - if (this.props.selected_users.indexOf(user_id == -1)) { - this.props.onChange(this.props.selected_users.concat([user_id])); - } - }, - - removeUser: function(user_id) { - this.props.onChange(this.props.selected_users.filter(function(e) { - return e != user_id; - })); - }, -}; diff --git a/src/controllers/molecules/voip/IncomingCallBox.js b/src/controllers/molecules/voip/IncomingCallBox.js deleted file mode 100644 index 809c0833ef..0000000000 --- a/src/controllers/molecules/voip/IncomingCallBox.js +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var dis = require("../../../dispatcher"); -var CallHandler = require("../../../CallHandler"); - -module.exports = { - componentDidMount: function() { - this.dispatcherRef = dis.register(this.onAction); - }, - - componentWillUnmount: function() { - dis.unregister(this.dispatcherRef); - }, - - getInitialState: function() { - return { - incomingCall: null - } - }, - - onAction: function(payload) { - if (payload.action !== 'call_state') { - return; - } - var call = CallHandler.getCall(payload.room_id); - if (!call || call.call_state !== 'ringing') { - this.setState({ - incomingCall: null, - }); - this.getRingAudio().pause(); - return; - } - if (call.call_state === "ringing") { - this.getRingAudio().load(); - this.getRingAudio().play(); - } - else { - this.getRingAudio().pause(); - } - - this.setState({ - incomingCall: call - }); - }, - - onAnswerClick: function() { - dis.dispatch({ - action: 'answer', - room_id: this.state.incomingCall.roomId - }); - }, - onRejectClick: function() { - dis.dispatch({ - action: 'hangup', - room_id: this.state.incomingCall.roomId - }); - } -}; - diff --git a/src/controllers/molecules/voip/VideoView.js b/src/controllers/molecules/voip/VideoView.js deleted file mode 100644 index 8aa688b21e..0000000000 --- a/src/controllers/molecules/voip/VideoView.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = { -}; - diff --git a/src/controllers/organisms/CreateRoom.js b/src/controllers/organisms/CreateRoom.js deleted file mode 100644 index f6404eb231..0000000000 --- a/src/controllers/organisms/CreateRoom.js +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require("react"); -var MatrixClientPeg = require("../../MatrixClientPeg"); -var PresetValues = require('../atoms/create_room/Presets').Presets; -var q = require('q'); -var encryption = require("../../encryption"); - -module.exports = { - propTypes: { - onRoomCreated: React.PropTypes.func, - }, - - phases: { - CONFIG: "CONFIG", // We're waiting for user to configure and hit create. - CREATING: "CREATING", // We're sending the request. - CREATED: "CREATED", // We successfully created the room. - ERROR: "ERROR", // There was an error while trying to create room. - }, - - getDefaultProps: function() { - return { - onRoomCreated: function() {}, - }; - }, - - getInitialState: function() { - return { - phase: this.phases.CONFIG, - error_string: "", - is_private: true, - share_history: false, - default_preset: PresetValues.PrivateChat, - topic: '', - room_name: '', - invited_users: [], - }; - }, - - onCreateRoom: function() { - var options = {}; - - if (this.state.room_name) { - options.name = this.state.room_name; - } - - if (this.state.topic) { - options.topic = this.state.topic; - } - - if (this.state.preset) { - if (this.state.preset != PresetValues.Custom) { - options.preset = this.state.preset; - } else { - options.initial_state = [ - { - type: "m.room.join_rules", - content: { - "join_rules": this.state.is_private ? "invite" : "public" - } - }, - { - type: "m.room.history_visibility", - content: { - "history_visibility": this.state.share_history ? "shared" : "invited" - } - }, - ]; - } - } - - options.invite = this.state.invited_users; - - var alias = this.getAliasLocalpart(); - if (alias) { - options.room_alias_name = alias; - } - - var cli = MatrixClientPeg.get(); - if (!cli) { - // TODO: Error. - console.error("Cannot create room: No matrix client."); - return; - } - - var deferred = cli.createRoom(options); - - var response; - - if (this.state.encrypt) { - deferred = deferred.then(function(res) { - response = res; - return encryption.enableEncryption( - cli, response.roomId, options.invite - ); - }).then(function() { - return q(response) } - ); - } - - this.setState({ - phase: this.phases.CREATING, - }); - - var self = this; - - deferred.then(function (resp) { - self.setState({ - phase: self.phases.CREATED, - }); - self.props.onRoomCreated(resp.room_id); - }, function(err) { - self.setState({ - phase: self.phases.ERROR, - error_string: err.toString(), - }); - }); - } -}; diff --git a/src/controllers/organisms/ErrorDialog.js b/src/controllers/organisms/ErrorDialog.js deleted file mode 100644 index 73f66c87e6..0000000000 --- a/src/controllers/organisms/ErrorDialog.js +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require("react"); - -module.exports = { - propTypes: { - title: React.PropTypes.string, - description: React.PropTypes.string, - button: React.PropTypes.string, - focus: React.PropTypes.bool, - onFinished: React.PropTypes.func.isRequired, - }, - - getDefaultProps: function() { - var self = this; - return { - title: "Error", - description: "An error has occurred.", - button: "OK", - focus: true, - }; - }, -}; diff --git a/src/controllers/organisms/LogoutPrompt.js b/src/controllers/organisms/LogoutPrompt.js deleted file mode 100644 index 8875a55cb4..0000000000 --- a/src/controllers/organisms/LogoutPrompt.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var dis = require("../../dispatcher"); - -module.exports = { - logOut: function() { - dis.dispatch({action: 'logout'}); - if (this.props.onFinished) { - this.props.onFinished(); - } - }, - - cancelPrompt: function() { - if (this.props.onFinished) { - this.props.onFinished(); - } - } -}; - diff --git a/src/controllers/organisms/MemberList.js b/src/controllers/organisms/MemberList.js deleted file mode 100644 index 3eef007ed4..0000000000 --- a/src/controllers/organisms/MemberList.js +++ /dev/null @@ -1,164 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require("react"); -var MatrixClientPeg = require("../../MatrixClientPeg"); -var Modal = require("../../Modal"); -var ComponentBroker = require('../../ComponentBroker'); -var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog"); - -var INITIAL_LOAD_NUM_MEMBERS = 50; - -module.exports = { - getInitialState: function() { - var members = this.roomMembers(INITIAL_LOAD_NUM_MEMBERS); - return { - memberDict: members - }; - }, - - componentWillMount: function() { - var cli = MatrixClientPeg.get(); - cli.on("RoomState.members", this.onRoomStateMember); - cli.on("Room", this.onRoom); // invites - }, - - componentWillUnmount: function() { - if (MatrixClientPeg.get()) { - MatrixClientPeg.get().removeListener("Room", this.onRoom); - MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember); - MatrixClientPeg.get().removeListener("User.presence", this.userPresenceFn); - } - }, - - componentDidMount: function() { - var self = this; - setTimeout(function() { - if (!self.isMounted()) return; - self.setState({ - memberDict: self.roomMembers() - }); - }, 50); - - // Attach a SINGLE listener for global presence changes then locate the - // member tile and re-render it. This is more efficient than every tile - // evar attaching their own listener. - function updateUserState(event, user) { - var tile = self.refs[user.userId]; - if (tile) { - // update the whole list to get the order right, not just this cell... - self.forceUpdate(); - // tile.forceUpdate(); - } - } - MatrixClientPeg.get().on("User.presence", updateUserState); - this.userPresenceFn = updateUserState; - }, - // Remember to set 'key' on a MemberList to the ID of the room it's for - /*componentWillReceiveProps: function(newProps) { - },*/ - - onRoom: function(room) { - if (room.roomId !== this.props.roomId) { - return; - } - // We listen for room events because when we accept an invite - // we need to wait till the room is fully populated with state - // before refreshing the member list else we get a stale list. - this._updateList(); - }, - - onRoomStateMember: function(ev, state, member) { - this._updateList(); - }, - - _updateList: function() { - var members = this.roomMembers(); - this.setState({ - memberDict: members - }); - }, - - onInvite: function(inputText) { - var self = this; - // sanity check the input - inputText = inputText.trim(); // react requires es5-shim so we know trim() exists - if (inputText[0] !== '@' || inputText.indexOf(":") === -1) { - console.error("Bad user ID to invite: %s", inputText); - Modal.createDialog(ErrorDialog, { - title: "Invite Error", - description: "Malformed user ID. Should look like '@localpart:domain'" - }); - return; - } - self.setState({ - inviting: true - }); - console.log("Invite %s to %s", inputText, this.props.roomId); - MatrixClientPeg.get().invite(this.props.roomId, inputText).done( - function(res) { - console.log("Invited"); - self.setState({ - inviting: false - }); - }, function(err) { - console.error("Failed to invite: %s", JSON.stringify(err)); - Modal.createDialog(ErrorDialog, { - title: "Server error whilst inviting", - description: err.message - }); - self.setState({ - inviting: false - }); - }); - }, - - roomMembers: function(limit) { - if (!this.props.roomId) return {}; - var cli = MatrixClientPeg.get(); - var room = cli.getRoom(this.props.roomId); - if (!room) return {}; - var all_members = room.currentState.members; - var all_user_ids = Object.keys(all_members); - - all_user_ids.sort(function(userIdA, userIdB) { - var userA = all_members[userIdA].user; - var userB = all_members[userIdB].user; - - var latA = userA ? userA.lastActiveAgo || Number.MAX_VALUE : Number.MAX_VALUE; - var latB = userB ? userB.lastActiveAgo || Number.MAX_VALUE : Number.MAX_VALUE; - - return latA - latB; - }); - - - var to_display = {}; - var count = 0; - for (var i = 0; i < all_user_ids.length && (limit === undefined || count < limit); ++i) { - var user_id = all_user_ids[i]; - var m = all_members[user_id]; - - if (m.membership == 'join' || m.membership == 'invite') { - to_display[user_id] = m; - ++count; - } - } - return to_display; - } -}; - diff --git a/src/controllers/organisms/Notifier.js b/src/controllers/organisms/Notifier.js deleted file mode 100644 index 0d493bf340..0000000000 --- a/src/controllers/organisms/Notifier.js +++ /dev/null @@ -1,129 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var MatrixClientPeg = require("../../MatrixClientPeg"); -var dis = require("../../dispatcher"); - -/* - * Dispatches: - * { - * action: "notifier_enabled", - * value: boolean - * } - */ - -// XXX: This isn't an organism surely in the atomic sense of the word -// what on earth is it doing here?! - -module.exports = { - start: function() { - this.boundOnRoomTimeline = this.onRoomTimeline.bind(this); - MatrixClientPeg.get().on('Room.timeline', this.boundOnRoomTimeline); - this.state = { 'toolbarHidden' : false }; - }, - - stop: function() { - if (MatrixClientPeg.get()) { - MatrixClientPeg.get().removeListener('Room.timeline', this.boundOnRoomTimeline); - } - }, - - supportsDesktopNotifications: function() { - return !!global.Notification; - }, - - havePermission: function() { - if (!this.supportsDesktopNotifications()) return false; - return global.Notification.permission == 'granted'; - }, - - setEnabled: function(enable, callback) { - console.log("Notifier.setEnabled => %s", enable); - if(enable) { - if (!this.havePermission()) { - var self = this; - global.Notification.requestPermission(function() { - if (callback) { - callback(); - dis.dispatch({ - action: "notifier_enabled", - value: true - }); - } - }); - } - - if (!global.localStorage) return; - global.localStorage.setItem('notifications_enabled', 'true'); - - if (this.havePermission) { - dis.dispatch({ - action: "notifier_enabled", - value: true - }); - } - } - else { - if (!global.localStorage) return; - global.localStorage.setItem('notifications_enabled', 'false'); - dis.dispatch({ - action: "notifier_enabled", - value: false - }); - } - - this.setToolbarHidden(false); - }, - - isEnabled: function() { - if (!this.havePermission()) return false; - - if (!global.localStorage) return true; - - var enabled = global.localStorage.getItem('notifications_enabled'); - if (enabled === null) return true; - return enabled === 'true'; - }, - - setToolbarHidden: function(hidden) { - this.state.toolbarHidden = hidden; - dis.dispatch({ - action: "notifier_enabled", - value: this.isEnabled() - }); - }, - - isToolbarHidden: function() { - return this.state.toolbarHidden; - }, - - onRoomTimeline: function(ev, room, toStartOfTimeline) { - if (toStartOfTimeline) return; - if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) return; - - if (!this.isEnabled()) { - return; - } - - var actions = MatrixClientPeg.get().getPushActionsForEvent(ev); - if (actions && actions.notify) { - this.displayNotification(ev, room); - } - } -}; - diff --git a/src/controllers/organisms/QuestionDialog.js b/src/controllers/organisms/QuestionDialog.js deleted file mode 100644 index c890d143aa..0000000000 --- a/src/controllers/organisms/QuestionDialog.js +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require("react"); - -module.exports = { - propTypes: { - title: React.PropTypes.string, - description: React.PropTypes.string, - button: React.PropTypes.string, - focus: React.PropTypes.bool, - onFinished: React.PropTypes.func.isRequired, - }, - - getDefaultProps: function() { - var self = this; - return { - title: "", - description: "", - button: "OK", - focus: true, - }; - }, -}; diff --git a/src/controllers/organisms/RoomList.js b/src/controllers/organisms/RoomList.js deleted file mode 100644 index 3933f53ec8..0000000000 --- a/src/controllers/organisms/RoomList.js +++ /dev/null @@ -1,170 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require("react"); -var MatrixClientPeg = require("../../MatrixClientPeg"); -var RoomListSorter = require("../../RoomListSorter"); -var dis = require("../../dispatcher"); - -var ComponentBroker = require('../../ComponentBroker'); -var ConferenceHandler = require("../../ConferenceHandler"); -var CallHandler = require("../../CallHandler"); - -var RoomTile = ComponentBroker.get("molecules/RoomTile"); - -var HIDE_CONFERENCE_CHANS = true; - -module.exports = { - componentWillMount: function() { - var cli = MatrixClientPeg.get(); - cli.on("Room", this.onRoom); - cli.on("Room.timeline", this.onRoomTimeline); - cli.on("Room.name", this.onRoomName); - - var rooms = this.getRoomList(); - this.setState({ - roomList: rooms, - activityMap: {} - }); - }, - - componentDidMount: function() { - this.dispatcherRef = dis.register(this.onAction); - }, - - onAction: function(payload) { - switch (payload.action) { - // listen for call state changes to prod the render method, which - // may hide the global CallView if the call it is tracking is dead - case 'call_state': - this._recheckCallElement(this.props.selectedRoom); - break; - } - }, - - componentWillUnmount: function() { - dis.unregister(this.dispatcherRef); - if (MatrixClientPeg.get()) { - MatrixClientPeg.get().removeListener("Room", this.onRoom); - MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline); - MatrixClientPeg.get().removeListener("Room.name", this.onRoomName); - } - }, - - componentWillReceiveProps: function(newProps) { - this.state.activityMap[newProps.selectedRoom] = undefined; - this._recheckCallElement(newProps.selectedRoom); - this.setState({ - activityMap: this.state.activityMap - }); - }, - - onRoom: function(room) { - this.refreshRoomList(); - }, - - onRoomTimeline: function(ev, room, toStartOfTimeline) { - if (toStartOfTimeline) return; - - var newState = { - roomList: this.getRoomList() - }; - if ( - room.roomId != this.props.selectedRoom && - ev.getSender() != MatrixClientPeg.get().credentials.userId) - { - var hl = 1; - - var actions = MatrixClientPeg.get().getPushActionsForEvent(ev); - if (actions && actions.tweaks && actions.tweaks.highlight) { - hl = 2; - } - // obviously this won't deep copy but this shouldn't be necessary - var amap = this.state.activityMap; - amap[room.roomId] = Math.max(amap[room.roomId] || 0, hl); - - newState.activityMap = amap; - } - this.setState(newState); - }, - - onRoomName: function(room) { - this.refreshRoomList(); - }, - - refreshRoomList: function() { - var rooms = this.getRoomList(); - this.setState({ - roomList: rooms - }); - }, - - getRoomList: function() { - return RoomListSorter.mostRecentActivityFirst( - MatrixClientPeg.get().getRooms().filter(function(room) { - var me = room.getMember(MatrixClientPeg.get().credentials.userId); - var shouldShowRoom = ( - me && (me.membership == "join" || me.membership == "invite") - ); - // hiding conf rooms only ever toggles shouldShowRoom to false - if (shouldShowRoom && HIDE_CONFERENCE_CHANS) { - // we want to hide the 1:1 conf<->user room and not the group chat - var joinedMembers = room.getJoinedMembers(); - if (joinedMembers.length === 2) { - var otherMember = joinedMembers.filter(function(m) { - return m.userId !== me.userId - })[0]; - if (ConferenceHandler.isConferenceUser(otherMember)) { - // console.log("Hiding conference 1:1 room %s", room.roomId); - shouldShowRoom = false; - } - } - } - return shouldShowRoom; - }) - ); - }, - - _recheckCallElement: function(selectedRoomId) { - // if we aren't viewing a room with an ongoing call, but there is an - // active call, show the call element - we need to do this to make - // audio/video not crap out - var activeCall = CallHandler.getAnyActiveCall(); - var callForRoom = CallHandler.getCallForRoom(selectedRoomId); - var showCall = (activeCall && !callForRoom); - this.setState({ - show_call_element: showCall - }); - }, - - makeRoomTiles: function() { - var self = this; - return this.state.roomList.map(function(room) { - var selected = room.roomId == self.props.selectedRoom; - return ( - - ); - }); - } -}; diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js deleted file mode 100644 index c6881de36a..0000000000 --- a/src/controllers/organisms/RoomView.js +++ /dev/null @@ -1,510 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var MatrixClientPeg = require("../../MatrixClientPeg"); -var React = require("react"); -var q = require("q"); -var ContentMessages = require("../../ContentMessages"); -var WhoIsTyping = require("../../WhoIsTyping"); -var Modal = require("../../Modal"); -var ComponentBroker = require('../../ComponentBroker'); - -var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog"); - -var dis = require("../../dispatcher"); - -var PAGINATE_SIZE = 20; -var INITIAL_SIZE = 100; - -var ConferenceHandler = require("../../ConferenceHandler"); -var CallHandler = require("../../CallHandler"); -var Notifier = ComponentBroker.get('organisms/Notifier'); - -var tileTypes = { - 'm.room.message': ComponentBroker.get('molecules/MessageTile'), - 'm.room.member' : ComponentBroker.get('molecules/EventAsTextTile'), - 'm.call.invite' : ComponentBroker.get('molecules/EventAsTextTile'), - 'm.call.answer' : ComponentBroker.get('molecules/EventAsTextTile'), - 'm.call.hangup' : ComponentBroker.get('molecules/EventAsTextTile'), - 'm.room.topic' : ComponentBroker.get('molecules/EventAsTextTile'), -}; - -var DateSeparator = ComponentBroker.get('molecules/DateSeparator'); - -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': - 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 !== ConferenceHandler.getConferenceUserIdForRoom(member.roomId)) { - return; - } - this._updateConfCallNotification(); - }, - - _updateConfCallNotification: function() { - var confMember = MatrixClientPeg.get().getRoom(this.props.roomId).getMember( - ConferenceHandler.getConferenceUserIdForRoom(this.props.roomId) - ); - - if (!confMember) { - return; - } - var confCall = CallHandler.getConferenceCall(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" - ) - }); - }, - - onConferenceNotificationClick: function() { - dis.dispatch({ - action: 'place_call', - type: "video", - room_id: this.props.roomId - }); - }, - - 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 ret = []; - var count = 0; - - for (var i = this.state.room.timeline.length-1; i >= 0 && count < this.state.messageCap; --i) { - var mxEv = this.state.room.timeline[i]; - var TileType = tileTypes[mxEv.getType()]; - 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 = ; - continuation = false; - } - } - if (!TileType) continue; - ret.unshift( - // XXX: don't wrap everything in a needless li - make the TileType a li if we must :( -
  • - ); - 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) { - Modal.createDialog(ErrorDialog, { - title: "Failed to set state", - description: err.toString() - }); - }).finally(function() { - self.setState({ - uploadingRoomSettings: false, - }); - }); - } else { - this.setState({ - editingRoomSettings: false, - uploadingRoomSettings: false, - }); - } - } -}; diff --git a/src/controllers/organisms/UserSettings.js b/src/controllers/organisms/UserSettings.js deleted file mode 100644 index 4eb1fd5902..0000000000 --- a/src/controllers/organisms/UserSettings.js +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var MatrixClientPeg = require("../../MatrixClientPeg"); -var React = require("react"); -var q = require('q'); -var dis = require("../../dispatcher"); -var version = require('../../../package.json').version; - -var ComponentBroker = require('../../ComponentBroker'); - -module.exports = { - Phases: { - Loading: "loading", - Display: "display", - }, - - getInitialState: function() { - return { - displayName: null, - avatarUrl: null, - threePids: [], - clientVersion: version, - phase: this.Phases.Loading, - }; - }, - - changeDisplayname: function(new_displayname) { - if (this.state.displayName == new_displayname) return; - - var self = this; - return MatrixClientPeg.get().setDisplayName(new_displayname).then( - function() { self.setState({displayName: new_displayname}); }, - function(err) { console.err(err); } - ); - }, - - componentWillMount: function() { - var self = this; - var cli = MatrixClientPeg.get(); - - var profile_d = cli.getProfileInfo(cli.credentials.userId); - var threepid_d = cli.getThreePids(); - - q.all([profile_d, threepid_d]).then( - function(resps) { - self.setState({ - displayName: resps[0].displayname, - avatarUrl: resps[0].avatar_url, - threepids: resps[1].threepids, - phase: self.Phases.Display, - }); - }, - function(err) { console.err(err); } - ); - } -} diff --git a/src/controllers/pages/MatrixChat.js b/src/controllers/pages/MatrixChat.js deleted file mode 100644 index 08cc652d9f..0000000000 --- a/src/controllers/pages/MatrixChat.js +++ /dev/null @@ -1,332 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -// should be atomised -var Loader = require("react-loader"); - -var MatrixClientPeg = require("../../MatrixClientPeg"); -var RoomListSorter = require("../../RoomListSorter"); -var Presence = require("../../Presence"); -var dis = require("../../dispatcher"); -var q = require("q"); - -var ComponentBroker = require('../../ComponentBroker'); -var Notifier = ComponentBroker.get('organisms/Notifier'); -var MatrixTools = require('../../MatrixTools'); - -module.exports = { - PageTypes: { - RoomView: "room_view", - UserSettings: "user_settings", - CreateRoom: "create_room", - RoomDirectory: "room_directory", - }, - - AuxPanel: { - RoomSettings: "room_settings", - }, - - getInitialState: function() { - var s = { - logged_in: !!(MatrixClientPeg.get() && MatrixClientPeg.get().credentials), - ready: false, - aux_panel: null, - }; - if (s.logged_in) { - if (MatrixClientPeg.get().getRooms().length) { - s.page_type = this.PageTypes.RoomView; - } else { - s.page_type = this.PageTypes.RoomDirectory; - } - } - return s; - }, - - componentDidMount: function() { - this.dispatcherRef = dis.register(this.onAction); - if (this.state.logged_in) { - this.startMatrixClient(); - } - this.focusComposer = false; - document.addEventListener("keydown", this.onKeyDown); - window.addEventListener("focus", this.onFocus); - if (this.state.logged_in) { - this.notifyNewScreen(''); - } else { - this.notifyNewScreen('login'); - } - }, - - componentWillUnmount: function() { - dis.unregister(this.dispatcherRef); - document.removeEventListener("keydown", this.onKeyDown); - window.removeEventListener("focus", this.onFocus); - }, - - componentDidUpdate: function() { - if (this.focusComposer) { - dis.dispatch({action: 'focus_composer'}); - this.focusComposer = false; - } - }, - - onAction: function(payload) { - var roomIndexDelta = 1; - - switch (payload.action) { - case 'logout': - this.replaceState({ - logged_in: false, - ready: false - }); - if (window.localStorage) { - window.localStorage.clear(); - } - Notifier.stop(); - Presence.stop(); - MatrixClientPeg.get().stopClient(); - MatrixClientPeg.get().removeAllListeners(); - MatrixClientPeg.unset(); - this.notifyNewScreen(''); - break; - case 'start_registration': - if (this.state.logged_in) return; - var newState = payload.params || {}; - newState.screen = 'register'; - if ( - payload.params && - payload.params.client_secret && - payload.params.session_id && - payload.params.hs_url && - payload.params.is_url && - payload.params.sid - ) { - newState.register_client_secret = payload.params.client_secret; - newState.register_session_id = payload.params.session_id; - newState.register_hs_url = payload.params.hs_url; - newState.register_is_url = payload.params.is_url; - newState.register_id_sid = payload.params.sid; - } - this.replaceState(newState); - this.notifyNewScreen('register'); - break; - case 'start_login': - if (this.state.logged_in) return; - this.replaceState({ - screen: 'login' - }); - this.notifyNewScreen('login'); - break; - case 'view_room': - this.focusComposer = true; - this.setState({ - currentRoom: payload.room_id, - page_type: this.PageTypes.RoomView, - }); - if (this.sdkReady) { - // if the SDK is not ready yet, remember what room - // we're supposed to be on but don't notify about - // the new screen yet (we won't be showing it yet) - // The normal case where this happens is navigating - // to the room in the URL bar on page load. - var presentedId = payload.room_id; - var room = MatrixClientPeg.get().getRoom(payload.room_id); - if (room) { - var theAlias = MatrixTools.getCanonicalAliasForRoom(room); - if (theAlias) presentedId = theAlias; - } - this.notifyNewScreen('room/'+presentedId); - } - break; - case 'view_prev_room': - roomIndexDelta = -1; - case 'view_next_room': - var allRooms = RoomListSorter.mostRecentActivityFirst( - MatrixClientPeg.get().getRooms() - ); - var roomIndex = -1; - for (var i = 0; i < allRooms.length; ++i) { - if (allRooms[i].roomId == this.state.currentRoom) { - roomIndex = i; - break; - } - } - roomIndex = (roomIndex + roomIndexDelta) % allRooms.length; - if (roomIndex < 0) roomIndex = allRooms.length - 1; - this.focusComposer = true; - this.setState({ - currentRoom: allRooms[roomIndex].roomId - }); - this.notifyNewScreen('room/'+allRooms[roomIndex].roomId); - break; - case 'view_indexed_room': - var allRooms = RoomListSorter.mostRecentActivityFirst( - MatrixClientPeg.get().getRooms() - ); - var roomIndex = payload.roomIndex; - if (allRooms[roomIndex]) { - this.focusComposer = true; - this.setState({ - currentRoom: allRooms[roomIndex].roomId - }); - this.notifyNewScreen('room/'+allRooms[roomIndex].roomId); - } - break; - case 'view_user_settings': - this.setState({ - page_type: this.PageTypes.UserSettings, - }); - break; - case 'view_create_room': - this.setState({ - page_type: this.PageTypes.CreateRoom, - }); - break; - case 'view_room_directory': - this.setState({ - page_type: this.PageTypes.RoomDirectory, - }); - break; - case 'notifier_enabled': - this.forceUpdate(); - break; - } - }, - - onLoggedIn: function() { - this.setState({ - screen: undefined, - logged_in: true - }); - this.startMatrixClient(); - this.notifyNewScreen(''); - }, - - startMatrixClient: function() { - var cli = MatrixClientPeg.get(); - var self = this; - cli.on('syncComplete', function() { - self.sdkReady = true; - if (!self.state.currentRoom) { - var firstRoom = null; - if (cli.getRooms() && cli.getRooms().length) { - firstRoom = RoomListSorter.mostRecentActivityFirst( - cli.getRooms() - )[0].roomId; - self.setState({ready: true, currentRoom: firstRoom, page_type: self.PageTypes.RoomView}); - } else { - self.setState({ready: true, page_type: self.PageTypes.RoomDirectory}); - } - } else { - self.setState({ready: true, currentRoom: self.state.currentRoom}); - } - - // we notifyNewScreen now because now the room will actually be displayed, - // and (mostly) now we can get the correct alias. - var presentedId = self.state.currentRoom; - var room = MatrixClientPeg.get().getRoom(self.state.currentRoom); - if (room) { - var theAlias = MatrixTools.getCanonicalAliasForRoom(room); - if (theAlias) presentedId = theAlias; - } - self.notifyNewScreen('room/'+presentedId); - dis.dispatch({action: 'focus_composer'}); - }); - cli.on('Call.incoming', function(call) { - dis.dispatch({ - action: 'incoming_call', - call: call - }); - }); - Notifier.start(); - Presence.start(); - cli.startClient(); - }, - - onKeyDown: function(ev) { - if (ev.altKey) { - if (ev.ctrlKey && ev.keyCode > 48 && ev.keyCode < 58) { - dis.dispatch({ - action: 'view_indexed_room', - roomIndex: ev.keyCode - 49, - }); - ev.stopPropagation(); - ev.preventDefault(); - return; - } - switch (ev.keyCode) { - case 38: - dis.dispatch({action: 'view_prev_room'}); - ev.stopPropagation(); - ev.preventDefault(); - break; - case 40: - dis.dispatch({action: 'view_next_room'}); - ev.stopPropagation(); - ev.preventDefault(); - break; - } - } - }, - - onFocus: function(ev) { - dis.dispatch({action: 'focus_composer'}); - }, - - showScreen: function(screen, params) { - if (screen == 'register') { - dis.dispatch({ - action: 'start_registration', - params: params - }); - } else if (screen == 'login') { - dis.dispatch({ - action: 'start_login', - params: params - }); - } else if (screen.indexOf('room/') == 0) { - var roomString = screen.split('/')[1]; - var defer = q.defer(); - if (roomString[0] == '#') { - var self = this; - MatrixClientPeg.get().getRoomIdForAlias(roomString).done(function(result) { - if (self.sdkReady) self.setState({ready: true}); - defer.resolve(result.room_id); - }, function() { - if (self.sdkReady) self.setState({ready: true}); - defer.resolve(null); - }); - this.setState({ready: false}); - } else { - defer.resolve(roomString); - } - defer.promise.done(function(roomId) { - dis.dispatch({ - action: 'view_room', - room_id: roomId - }); - }); - } - }, - - notifyNewScreen: function(screen) { - if (this.props.onNewScreen) { - this.props.onNewScreen(screen); - } - } -}; diff --git a/src/controllers/templates/Login.js b/src/controllers/templates/Login.js deleted file mode 100644 index f3528e33a7..0000000000 --- a/src/controllers/templates/Login.js +++ /dev/null @@ -1,114 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var MatrixClientPeg = require("../../MatrixClientPeg"); -var Matrix = require("matrix-js-sdk"); -var dis = require("../../dispatcher"); - -var ComponentBroker = require("../../ComponentBroker"); - -module.exports = { - getInitialState: function() { - return { - step: 'choose_hs', - busy: false, - currentStep: 0, - totalSteps: 1 - }; - }, - - setStep: function(step) { - this.setState({ step: step, busy: false }); - }, - - onHSChosen: function() { - MatrixClientPeg.replaceUsingUrls( - this.getHsUrl(), - this.getIsUrl() - ); - this.setState({ - hs_url: this.getHsUrl(), - is_url: this.getIsUrl(), - }); - this.setStep("fetch_stages"); - var cli = MatrixClientPeg.get(); - this.setState({ - busy: true, - errorText: "", - }); - var self = this; - cli.loginFlows().done(function(result) { - self.setState({ - flows: result.flows, - currentStep: 1, - totalSteps: result.flows.length+1 - }); - self.setStep('stage_'+result.flows[0].type); - }, function(error) { - self.setStep("choose_hs"); - self.setState({errorText: 'Unable to contact the given Home Server'}); - }); - }, - - onUserPassEntered: function(ev) { - ev.preventDefault(); - this.setState({ - busy: true, - errorText: "", - }); - var self = this; - - var formVals = this.getFormVals(); - - var loginParams = { - password: formVals.password - }; - if (formVals.username.indexOf('@') > 0) { - loginParams.medium = 'email'; - loginParams.address = formVals.username; - } else { - loginParams.user = formVals.username; - } - - MatrixClientPeg.get().login('m.login.password', loginParams).done(function(data) { - MatrixClientPeg.replaceUsingAccessToken( - self.state.hs_url, self.state.is_url, - data.user_id, data.access_token - ); - if (self.props.onLoggedIn) { - self.props.onLoggedIn(); - } - }, function(error) { - self.setStep("stage_m.login.password"); - if (error.httpStatus == 400 && loginParams.medium) { - self.setState({errorText: 'This Home Server does not support login using email address.'}); - } else { - self.setState({errorText: 'Login failed.'}); - } - }); - }, - - showRegister: function(ev) { - ev.preventDefault(); - dis.dispatch({ - action: 'start_registration' - }); - } -}; diff --git a/src/controllers/templates/Register.js b/src/controllers/templates/Register.js deleted file mode 100644 index 5ed5d7dc5b..0000000000 --- a/src/controllers/templates/Register.js +++ /dev/null @@ -1,347 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var React = require('react'); - -var MatrixClientPeg = require("../../MatrixClientPeg"); -var Matrix = require("matrix-js-sdk"); -var dis = require("../../dispatcher"); - -var ComponentBroker = require("../../ComponentBroker"); - -module.exports = { - FieldErrors: { - PasswordMismatch: 'PasswordMismatch', - TooShort: 'TooShort', - Missing: 'Missing', - InUse: 'InUse' - }, - - getInitialState: function() { - return { - step: 'initial', - busy: false, - currentStep: 0, - totalSteps: 1 - }; - }, - - componentWillMount: function() { - this.savedParams = { - email: '', - username: '', - password: '', - confirmPassword: '' - }; - this.readNewProps(); - }, - - componentWillReceiveProps: function() { - this.readNewProps(); - }, - - readNewProps: function() { - if (this.props.clientSecret && this.props.hsUrl && - this.props.isUrl && this.props.sessionId && - this.props.idSid) { - this.authSessionId = this.props.sessionId; - MatrixClientPeg.replaceUsingUrls( - this.props.hsUrl, - this.props.isUrl - ); - this.setState({ - hs_url: this.props.hsUrl, - is_url: this.props.isUrl - }); - this.savedParams = {client_secret: this.props.clientSecret}; - this.setState({busy: true}); - - var isLocation = document.createElement('a'); - isLocation.href = this.props.isUrl; - - var auth = { - type: 'm.login.email.identity', - threepid_creds: { - sid: this.props.idSid, - client_secret: this.savedParams.client_secret, - id_server: isLocation.host - } - }; - this.tryRegister(auth); - } - }, - - componentDidUpdate: function() { - // Just putting a script tag into the returned jsx doesn't work, annoyingly, - // so we do this instead. - if (this.refs.recaptchaContainer) { - var scriptTag = document.createElement('script'); - window.mx_on_recaptcha_loaded = this.onCaptchaLoaded; - scriptTag.setAttribute('src', "https://www.google.com/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit"); - this.refs.recaptchaContainer.getDOMNode().appendChild(scriptTag); - } - }, - - setStep: function(step) { - this.setState({ step: step, errorText: '', busy: false }); - }, - - getSupportedStageTypes: function() { - return ['m.login.email.identity', 'm.login.recaptcha']; - }, - - chooseFlow: function(flows) { - // this is fairly simple right now - var supportedTypes = this.getSupportedStageTypes(); - - var emailFlow = null; - var otherFlow = null; - for (var flowI = 0; flowI < flows.length; ++flowI) { - var flow = flows[flowI]; - var flowHasEmail = false; - var flowSupported = true; - for (var stageI = 0; stageI < flow.stages.length; ++stageI) { - var stage = flow.stages[stageI]; - - if (supportedTypes.indexOf(stage) == -1) { - flowSupported = false; - } - - if (stage == 'm.login.email.identity') { - flowHasEmail = true; - } - } - if (flowSupported) { - if (flowHasEmail) { - emailFlow = flow; - } else { - otherFlow = flow; - } - } - } - - if ( - this.savedParams.email != '' || - this.completedStages.indexOf('m.login.email.identity') > -1 - ) { - return emailFlow; - } else { - return otherFlow; - } - }, - - firstUncompletedStageIndex: function(flow) { - if (this.completedStages === undefined) return 0; - for (var i = 0; i < flow.stages.length; ++i) { - if (this.completedStages.indexOf(flow.stages[i]) == -1) { - return i; - } - } - }, - - numCompletedStages: function(flow) { - if (this.completedStages === undefined) return 0; - var nCompleted = 0; - for (var i = 0; i < flow.stages.length; ++i) { - if (this.completedStages.indexOf(flow.stages[i]) > -1) { - ++nCompleted; - } - } - return nCompleted; - }, - - onInitialStageSubmit: function(ev) { - ev.preventDefault(); - - var formVals = this.getRegFormVals(); - this.savedParams = formVals; - - var badFields = {}; - if (formVals.password != formVals.confirmPassword) { - badFields.confirmPassword = this.FieldErrors.PasswordMismatch; - } - if (formVals.password == '') { - badFields.password = this.FieldErrors.Missing; - } else if (formVals.password.length < 6) { - badFields.password = this.FieldErrors.Length; - } - if (formVals.username == '') { - badFields.username = this.FieldErrors.Missing; - } - if (Object.keys(badFields).length > 0) { - this.onBadFields(badFields); - return; - } - - MatrixClientPeg.replaceUsingUrls( - this.getHsUrl(), - this.getIsUrl() - ); - this.setState({ - hs_url: this.getHsUrl(), - is_url: this.getIsUrl() - }); - var cli = MatrixClientPeg.get(); - this.setState({busy: true}); - var self = this; - - this.tryRegister(); - }, - - startStage: function(stageName) { - var self = this; - this.setStep('stage_'+stageName); - switch(stageName) { - case 'm.login.email.identity': - self.setState({ - busy: true - }); - var cli = MatrixClientPeg.get(); - this.savedParams.client_secret = cli.generateClientSecret(); - this.savedParams.send_attempt = 1; - - var nextLink = this.props.registrationUrl + - '?client_secret=' + - encodeURIComponent(this.savedParams.client_secret) + - "&hs_url=" + - encodeURIComponent(this.state.hs_url) + - "&is_url=" + - encodeURIComponent(this.state.is_url) + - "&session_id=" + - encodeURIComponent(this.authSessionId); - - cli.requestEmailToken( - this.savedParams.email, - this.savedParams.client_secret, - this.savedParams.send_attempt, - nextLink - ).done(function(response) { - self.setState({ - busy: false, - }); - self.setStep('stage_m.login.email.identity'); - }, function(error) { - self.setStep('initial'); - var newState = {busy: false}; - if (error.errcode == 'THREEPID_IN_USE') { - self.onBadFields({email: self.FieldErrors.InUse}); - } else { - newState.errorText = 'Unable to contact the given Home Server'; - } - self.setState(newState); - }); - break; - case 'm.login.recaptcha': - if (!this.authParams || !this.authParams['m.login.recaptcha'].public_key) { - this.setState({ - errorText: "This server has not supplied enough information for Recaptcha authentication" - }); - } - break; - } - }, - - onRegistered: function(user_id, access_token) { - MatrixClientPeg.replaceUsingAccessToken( - this.state.hs_url, this.state.is_url, user_id, access_token - ); - if (this.props.onLoggedIn) { - this.props.onLoggedIn(); - } - }, - - onCaptchaLoaded: function() { - if (this.refs.recaptchaContainer) { - var sitekey = this.authParams['m.login.recaptcha'].public_key; - global.grecaptcha.render('mx_recaptcha', { - 'sitekey': sitekey, - 'callback': this.onCaptchaDone - }); - } - }, - - onCaptchaDone: function(captcha_response) { - this.tryRegister({ - type: 'm.login.recaptcha', - response: captcha_response - }); - }, - - tryRegister: function(auth) { - var self = this; - MatrixClientPeg.get().register( - this.savedParams.username, - this.savedParams.password, - this.authSessionId, - auth - ).done(function(result) { - self.onRegistered(result.user_id, result.access_token); - }, function(error) { - if (error.httpStatus == 401 && error.data.flows) { - self.authParams = error.data.params; - self.authSessionId = error.data.session; - - self.completedStages = error.data.completed || []; - - var flow = self.chooseFlow(error.data.flows); - - var flowStage = self.firstUncompletedStageIndex(flow); - var numDone = self.numCompletedStages(flow); - - self.setState({ - busy: false, - flows: flow, - currentStep: 1+numDone, - totalSteps: flow.stages.length+1, - flowStage: flowStage - }); - self.startStage(flow.stages[flowStage]); - } else { - self.setStep("initial"); - var newState = { - busy: false, - errorText: "Unable to contact the given Home Server" - }; - if (error.name == 'M_USER_IN_USE') { - delete newState.errorText; - self.onBadFields({ - username: self.FieldErrors.InUse - }); - } else if (error.httpStatus == 401) { - newState.errorText = "Authorisation failed!"; - } else if (error.httpStatus >= 400 && error.httpStatus < 500) { - newState.errorText = "Registration failed!"; - } else if (error.httpStatus >= 500 && error.httpStatus < 600) { - newState.errorText = "Server error during registration!"; - } else if (error.name == "M_MISSING_PARAM") { - // The HS hasn't remembered the login params from - // the first try when the login email was sent. - newState.errorText = "This home server does not support resuming registration."; - } - self.setState(newState); - } - }); - }, - - showLogin: function(ev) { - ev.preventDefault(); - dis.dispatch({ - action: 'start_login' - }); - } -}; diff --git a/src/dispatcher.js b/src/dispatcher.js deleted file mode 100644 index 3edb9c6947..0000000000 --- a/src/dispatcher.js +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var flux = require("flux"); -var extend = require("./extend"); - -var MatrixDispatcher = function() { - flux.Dispatcher.call(this); -}; - -extend(MatrixDispatcher.prototype, flux.Dispatcher.prototype); -MatrixDispatcher.prototype.dispatch = function(payload) { - if (this.dispatching) { - setTimeout(flux.Dispatcher.prototype.dispatch.bind(this, payload), 0); - } else { - this.dispatching = true; - flux.Dispatcher.prototype.dispatch.call(this, payload); - this.dispatching = false; - } -} - -module.exports = new MatrixDispatcher(); diff --git a/src/encryption.js b/src/encryption.js deleted file mode 100644 index dea454a3f3..0000000000 --- a/src/encryption.js +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -function enableEncyption(client, roomId, members) { - members = members.slice(0); - members.push(client.credentials.userId); - // TODO: Check the keys actually match what keys the user has. - // TODO: Don't redownload keys each time. - return client.downloadKeys(members, "forceDownload").then(function(res) { - return client.setRoomEncryption(roomId, { - algorithm: "m.olm.v1.curve25519-aes-sha2", - members: members, - }); - }) -} - -function disableEncryption(client, roomId) { - return client.disableRoomEncryption(roomId); -} - - -module.exports = { - enableEncryption: enableEncyption, - disableEncryption: disableEncryption, -} diff --git a/src/extend.js b/src/extend.js deleted file mode 100644 index 178748d72b..0000000000 --- a/src/extend.js +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports = function(dest, src) { - for (var i in src) { - if (src.hasOwnProperty(i)) { - dest[i] = src[i]; - } - } - return dest; -} diff --git a/src/index.js b/src/index.js deleted file mode 100644 index febf8d0dc8..0000000000 --- a/src/index.js +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -module.exports.MatrixChat = require("../skins/base/views/pages/MatrixChat"); diff --git a/src/linkify-matrix.js b/src/linkify-matrix.js deleted file mode 100644 index 273fe123a9..0000000000 --- a/src/linkify-matrix.js +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -var extend = require('./extend'); - -function matrixLinkify(linkify) { - // Text tokens - var TT = linkify.scanner.TOKENS; - var TextToken = TT.Base; - // Multi tokens - var MT = linkify.parser.TOKENS; - var MultiToken = MT.Base; - var S_START = linkify.parser.start; - - - var ROOMALIAS = function(value) { - MultiToken.call(this, value); - this.type = 'roomalias'; - this.isLink = true; - }; - ROOMALIAS.prototype = new MultiToken(); - - var S_HASH = new linkify.parser.State(); - var S_HASH_NAME = new linkify.parser.State(); - var S_HASH_NAME_COLON = new linkify.parser.State(); - var S_HASH_NAME_COLON_DOMAIN = new linkify.parser.State(); - var S_HASH_NAME_COLON_DOMAIN_DOT = new linkify.parser.State(); - var S_ROOMALIAS = new linkify.parser.State(ROOMALIAS); - - var roomname_tokens = [ - TT.DOT, - TT.PLUS, - TT.NUM, - TT.DOMAIN, - TT.TLD - ]; - - S_START.on(TT.POUND, S_HASH); - - S_HASH.on(roomname_tokens, S_HASH_NAME); - S_HASH_NAME.on(roomname_tokens, S_HASH_NAME); - S_HASH_NAME.on(TT.DOMAIN, S_HASH_NAME); - - S_HASH_NAME.on(TT.COLON, S_HASH_NAME_COLON); - - S_HASH_NAME_COLON.on(TT.DOMAIN, S_HASH_NAME_COLON_DOMAIN); - S_HASH_NAME_COLON_DOMAIN.on(TT.DOT, S_HASH_NAME_COLON_DOMAIN_DOT); - S_HASH_NAME_COLON_DOMAIN_DOT.on(TT.DOMAIN, S_HASH_NAME_COLON_DOMAIN); - S_HASH_NAME_COLON_DOMAIN_DOT.on(TT.TLD, S_ROOMALIAS); - - - var USERID = function(value) { - MultiToken.call(this, value); - this.type = 'userid'; - this.isLink = true; - }; - USERID.prototype = new MultiToken(); - - var S_AT = new linkify.parser.State(); - var S_AT_NAME = new linkify.parser.State(); - var S_AT_NAME_COLON = new linkify.parser.State(); - var S_AT_NAME_COLON_DOMAIN = new linkify.parser.State(); - var S_AT_NAME_COLON_DOMAIN_DOT = new linkify.parser.State(); - var S_USERID = new linkify.parser.State(USERID); - - var username_tokens = [ - TT.DOT, - TT.PLUS, - TT.NUM, - TT.DOMAIN, - TT.TLD - ]; - - S_START.on(TT.AT, S_AT); - - S_AT.on(username_tokens, S_AT_NAME); - S_AT_NAME.on(username_tokens, S_AT_NAME); - S_AT_NAME.on(TT.DOMAIN, S_AT_NAME); - - S_AT_NAME.on(TT.COLON, S_AT_NAME_COLON); - - S_AT_NAME_COLON.on(TT.DOMAIN, S_AT_NAME_COLON_DOMAIN); - S_AT_NAME_COLON_DOMAIN.on(TT.DOT, S_AT_NAME_COLON_DOMAIN_DOT); - S_AT_NAME_COLON_DOMAIN_DOT.on(TT.DOMAIN, S_AT_NAME_COLON_DOMAIN); - S_AT_NAME_COLON_DOMAIN_DOT.on(TT.TLD, S_USERID); -} - -matrixLinkify.options = { - formatHref: function (href, type) { - switch (type) { - case 'roomalias': - return '#'; - case 'userid': - return '#'; - default: - return href; - } - } -} - -module.exports = matrixLinkify; diff --git a/vector/fonts b/vector/fonts deleted file mode 120000 index 27f04cad54..0000000000 --- a/vector/fonts +++ /dev/null @@ -1 +0,0 @@ -../../skins/base/fonts/ \ No newline at end of file diff --git a/vector/img b/vector/img deleted file mode 120000 index 0d3ef0e2f2..0000000000 --- a/vector/img +++ /dev/null @@ -1 +0,0 @@ -../../skins/base/img \ No newline at end of file diff --git a/vector/index.html b/vector/index.html index be9e8f7ee6..2985994b10 100644 --- a/vector/index.html +++ b/vector/index.html @@ -41,6 +41,6 @@
    - + diff --git a/vector/package.json b/vector/package.json deleted file mode 100644 index 230a261b4a..0000000000 --- a/vector/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "matrix-react-example", - "version": "0.0.1", - "description": "Example usage of matrix-react-sdk", - "author": "matrix.org", - "repository": { - "type": "git", - "url": "https://github.com/matrix-org/matrix-react-sdk" - }, - "license": "Apache-2.0", - "devDependencies": { - "browserify": "^10.2.3", - "http-server": "^0.8.0", - "matrix-react-sdk": "../../", - "parallelshell": "^1.2.0", - "reactify": "^1.1.1", - "uglify-js": "^2.4.23", - "watchify": "^3.2.1" - }, - "scripts": { - "build": "NODE_ENV=production browserify --ignore olm -t reactify index.js | uglifyjs -c -m -o bundle.js", - "start": "parallelshell \"watchify --ignore olm -v -d -t reactify index.js -o bundle.js\" \"http-server\"" - } -}