diff --git a/.gitignore b/.gitignore index 191776811..13466ce84 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ node_modules -build -bundle.css -bundle.js +vector/bundle.* +lib diff --git a/README.md b/README.md index 591821028..690e1041d 100644 --- a/README.md +++ b/README.md @@ -10,145 +10,33 @@ Getting started 2. Clone the repo: `git clone https://github.com/vector-im/vector-web.git` 3. Switch to the SDK directory: `cd vector-web` 4. Install the prerequisites: `npm install` -5. Switch to the example directory: `cd examples/vector` -6. Install the example app prerequisites: `npm install` -7. Build the example and start a server: `npm start` +5. Start the development builder and a testing server: `npm start` +6. Wait a few seconds for the initial build to finish. +7. Open http://127.0.0.1:8080/ in your browser to see your newly built Vector. -Now open http://127.0.0.1:8080/ in your browser to see your newly built -Vector. +With `npm start`, any changes you make to the source files will cause a rebuild so +your changes will show up when you refresh. + +For production use, run `npm run build` to build all the necessary files +into the `vector` directory and run your own server. Development =========== - -To work on the CSS and Javascript and have the bundle files update as you -change the source files, you'll need to do two extra things: +You can work on any of the source files within Vector with the setup above, +and your changes will cause an instant rebuild. If you also need to make +changes to the react sdk, you can: 1. Link the react sdk package into the example: - `cd vector-web/examples/vector; npm link ../../` -2. Start a watcher for the CSS files: - `cd vector-web; npm run start:css` + `npm link path/to/your/react/sdk` +2. Start the development rebuilder in your react SDK directory: + `npm start` -Note that you may need to restart the CSS builder if you add a new file. Note -that `npm start` builds debug versions of the javascript and CSS, which are -much larger than the production versions build by the `npm run build` commands. - -IMPORTANT: If you customise components in your application (and hence require -react from your app) you must be sure to: - -1. Make your app depend on react directly -2. If you `npm link` matrix-react-sdk, manually remove the 'react' directory - from matrix-react-sdk's `node_modules` folder, otherwise browserify will - pull in both copies of react which causes the app to break. +If you add or remove any components from the Vector skin, you will need to rebuild +the skin's index by running, `npm run reskindex`. Deployment ========== -Just run `npm build` in the `examples/vector` directory, and then mount the -`examples/vector` directory on your webserver to actually serve up the app, -which is entirely static content. +Just run `npm build` and then mount the `vector` directory on your webserver to +actually serve up the app, which is entirely static content. -How to customise the SDK -======================== - -The matrix-react-sdk provides well-defined reusable UI components which may be -customised/replaced by the developer to build into an app. A set of consistent -UI components (View + CSS classes) is called a 'skin' - currently the SDK -provides a very vanilla whitelabelled 'base skin'. In future the SDK could -provide alternative skins (probably by extending the base skin) that provide more -specific look and feels (e.g. "IRC-style", "Skype-style") etc. However, unlike -Wordpress themes and similar, we don't normally expect app developers to define -reusable skins. Instead you just go and incorporate your view customisations -into your actual app. - -The SDK uses the 'atomic' design pattern as seen at http://patternlab.io to -encourage a very modular and reusable architecture, making it easy to -customise and use UI widgets independently of the rest of the SDK and your app. -In practice this means: - - * The UI of the app is strictly split up into a hierarchy of components. - - * Each component has its own: - * View object defined as a React javascript class containing embedded - HTML expressed in React's JSX notation. - * CSS file, which defines the styling specific to that component. - - * Components are loosely grouped into the 5 levels outlined by atomic design: - * atoms: fundamental building blocks (e.g. a timestamp tag) - * molecules: "group of atoms which functions together as a unit" - (e.g. a message in a chat timeline) - * organisms: "groups of molecules (and atoms) which form a distinct section - of a UI" (e.g. a view of a chat room) - * templates: "a reusable configuration of organisms" - used to combine and - style organisms into a well-defined global look and feel - * pages: specific instances of templates. - - Good separation between the components is maintained by adopting various best - practices that anyone working with the SDK needs to be be aware of and uphold: - - * Views are named with upper camel case (e.g. molecules/MessageTile.js) - - * The view's CSS file MUST have the same name (e.g. molecules/MessageTile.css) - - * Per-view CSS is optional - it could choose to inherit all its styling from - the context of the rest of the app, although this is unusual for any but - the simplest atoms and molecules. - - * The view MUST *only* refer to the CSS rules defined in its own CSS file. - 'Stealing' styling information from other components (including parents) - is not cool, as it breaks the independence of the components. - - * CSS classes are named with an app-specific namespacing prefix to try to avoid - CSS collisions. The base skin shipped by Matrix.org with the matrix-react-sdk - uses the naming prefix "mx_". A company called Yoyodyne Inc might use a - prefix like "yy_" for its app-specific classes. - - * CSS classes use upper camel case when they describe React components - e.g. - .mx_MessageTile is the selector for the CSS applied to a MessageTile view. - - * CSS classes for DOM elements within a view which aren't components are named - by appending a lower camel case identifier to the view's class name - e.g. - .mx_MessageTile_randomDiv is how you'd name the class of an arbitrary div - within the MessageTile view. - - * We deliberately use vanilla CSS 3.0 to avoid adding any more magic - dependencies into the mix than we already have. App developers are welcome - to use whatever floats their boat however. - - * The CSS for a component can however override the rules for child components. - For instance, .mx_RoomList .mx_RoomTile {} would be the selector to override - styles of RoomTiles when viewed in the context of a RoomList view. - Overrides *must* be scoped to the View's CSS class - i.e. don't just define - .mx_RoomTile {} in RoomList.css - only RoomTile.css is allowed to define its - own CSS. Instead, say .mx_RoomList .mx_RoomTile {} to scope the override - only to the context of RoomList views. N.B. overrides should be relatively - rare as in general CSS inheritence should be enough. - - * Components should render only within the bounding box of their outermost DOM - element. Page-absolute positioning and negative CSS margins and similar are - generally not cool and stop the component from being reused easily in - different places. - - * We don't use the atomify library itself, as React already provides most - of the modularity requirements it brings to the table. - -With all this in mind, here's how you go about skinning the react SDK UI -components to embed a Matrix client into your app: - - * Create a new NPM project. Be sure to directly depend on react, (otherwise - you can end up with two copies of react). - * Create an index.js file that sets up react. Add require statements for - React, the ComponentBroker and matrix-react-sdk and a call to Render - the root React element as in the examples. - * Create React classes for any custom components you wish to add. These - can be based off the files in `views` in the `matrix-react-sdk` package, - modifying the require() statement appropriately. - You only need to copy files you want to customise. - * Add a ComponentBroker.set() call for each of your custom components. These - must come *before* `require("matrix-react-sdk")`. - * Add a way to build your project: we suggest copying the browserify calls - from the example projects, but you could use grunt or gulp. - * Create an index.html file pulling in your compiled index.js file, the - CSS bundle from matrix-react-sdk. - -For more specific detail on any of these steps, look at the `custom` example in -matrix-react-sdk/examples. diff --git a/config.json b/config.json new file mode 100644 index 000000000..923d23ab2 --- /dev/null +++ b/config.json @@ -0,0 +1,4 @@ +{ + "default_hs_url": "https://matrix.org", + "default_is_url": "https://vector.im" +} diff --git a/examples/custom/CustomMTextTile.js b/examples/custom/CustomMTextTile.js deleted file mode 100644 index e58ed4c1e..000000000 --- a/examples/custom/CustomMTextTile.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 MTextTileController = require("matrix-react-sdk/src/controllers/molecules/MTextTile"); - -module.exports = React.createClass({ - displayName: 'MTextTile', - mixins: [MTextTileController], - - render: function() { - var content = this.props.mxEvent.getContent(); - return ( - - {content.body} - - ); - }, - - onClick: function(ev) { - global.alert(this.props.mxEvent.getContent().body); - } -}); - diff --git a/examples/custom/README.md b/examples/custom/README.md deleted file mode 100644 index 8125053ce..000000000 --- a/examples/custom/README.md +++ /dev/null @@ -1,4 +0,0 @@ -matrix-react-example -==================== - -An example of how to use the Matrix React SDK to build a more customised app diff --git a/examples/custom/index.html b/examples/custom/index.html deleted file mode 100644 index 04c1645c8..000000000 --- a/examples/custom/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Matrix React SDK Custom Example - - -
- - - - diff --git a/examples/custom/index.js b/examples/custom/index.js deleted file mode 100644 index 66602a0ad..000000000 --- a/examples/custom/index.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'; - -// Remember to make your project depend on react directly as soon as -// you add a require('react') to any file in your project. Do not rely -// on react being pulled in via matrix-react-sdk: browserify breaks -// horribly in this situation and can end up pulling in multiple copies -// of react. -var React = require("react"); - -// We pull in the component broker first, separately, as we need to replace -// components before the SDK loads. -var ComponentBroker = require("matrix-react-sdk/src/ComponentBroker"); - -var CustomMTextTile = require('./CustomMTextTile'); - -ComponentBroker.set('molecules/MTextTile', CustomMTextTile); - -var MatrixReactSdk = require("matrix-react-sdk"); -//var MatrixReactSdk = require("../../src/index"); - -React.render( - , - document.getElementById('matrixchat') -); diff --git a/examples/custom/package.json b/examples/custom/package.json deleted file mode 100644 index 6acec803f..000000000 --- a/examples/custom/package.json +++ /dev/null @@ -1,29 +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", - "envify": "^3.4.0", - "http-server": "^0.8.0", - "matrix-react-sdk": "../../", - "npm-css": "^0.2.3", - "parallelshell": "^1.2.0", - "reactify": "^1.1.1", - "uglify-js": "^2.4.23", - "watchify": "^3.2.1" - }, - "scripts": { - "build": "browserify -t [ envify --NODE_ENV production ] -g reactify index.js | uglifyjs -c -m -o bundle.js", - "start": "parallelshell 'watchify -v -d -g reactify index.js -o bundle.js' 'http-server'" - }, - "dependencies": { - "react": "^0.13.3" - } -} diff --git a/examples/vector/README.md b/examples/vector/README.md deleted file mode 100644 index ac2662773..000000000 --- a/examples/vector/README.md +++ /dev/null @@ -1,4 +0,0 @@ -matrix-react-example -==================== - -A simple example of how to use the Matrix React SDK diff --git a/examples/vector/fonts b/examples/vector/fonts deleted file mode 120000 index 27f04cad5..000000000 --- a/examples/vector/fonts +++ /dev/null @@ -1 +0,0 @@ -../../skins/base/fonts/ \ No newline at end of file diff --git a/examples/vector/img b/examples/vector/img deleted file mode 120000 index 0d3ef0e2f..000000000 --- a/examples/vector/img +++ /dev/null @@ -1 +0,0 @@ -../../skins/base/img \ No newline at end of file diff --git a/examples/vector/package.json b/examples/vector/package.json deleted file mode 100644 index 230a261b4..000000000 --- a/examples/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\"" - } -} diff --git a/package.json b/package.json index 5f99bd51c..429e61394 100644 --- a/package.json +++ b/package.json @@ -1,40 +1,48 @@ { - "name": "matrix-react-sdk", + "name": "vector-web", "version": "0.0.1", - "description": "SDK for matrix.org using React", + "description": "Vector webapp", "author": "matrix.org", "repository": { "type": "git", - "url": "https://github.com/matrix-org/matrix-react-sdk" + "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 vector -h src/skins/vector/header", + "build:css": "catw \"src/skins/vector/css/**/*.css\" -o vector/bundle.css -c uglifycss --no-watch", + "build:compile": "babel --source-maps -d lib src", + "build:bundle": "NODE_ENV=production webpack -p lib/vector/index.js vector/bundle.js", + "build": "npm run build:css && npm run build:compile && npm run build:bundle", + "start:js": "webpack -w src/vector/index.js vector/bundle.js", + "start:skins:css": "catw \"src/skins/vector/css/**/*.css\" -o vector/bundle.css", + "//cache": "Note the -c 1 below due to https://code.google.com/p/chromium/issues/detail?id=508270", + "start": "parallelshell \"npm run start:js\" \"npm run start:skins:css\" \"http-server -c 1 vector\"", + "clean": "rimraf lib vector/bundle.css vector/bundle.js vector/bundle.js.map", + "prepublish": "npm run build:css && npm run build:compile" }, "dependencies": { "classnames": "^2.1.2", "filesize": "^3.1.2", "flux": "~2.0.3", - "matrix-js-sdk": "git://github.com/matrix-org/matrix-js-sdk.git#develop", + "linkifyjs": "^2.0.0-beta.4", + "matrix-js-sdk": "^0.2.1", + "matrix-react-sdk": "^0.0.1", "q": "^1.4.1", "react": "^0.13.3", - "react-loader": "^1.4.0", - "linkifyjs": "^2.0.0-beta.4" + "react-loader": "^1.4.0" }, "devDependencies": { + "babel": "^5.8.23", + "babel-core": "^5.8.25", + "babel-loader": "^5.3.2", "catw": "^1.0.1", + "http-server": "^0.8.4", + "json-loader": "^0.5.3", "parallelshell": "^1.2.0", - "react-tools": "^0.13.3", + "rimraf": "^2.4.3", + "source-map-loader": "^0.1.5", "uglifycss": "0.0.15" } } diff --git a/src/Avatar.js b/src/Avatar.js index bdfc20ca8..2f83ebd93 100644 --- a/src/Avatar.js +++ b/src/Avatar.js @@ -16,14 +16,17 @@ limitations under the License. 'use strict'; -var MatrixClientPeg = require('./MatrixClientPeg'); +var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); module.exports = { avatarUrlForMember: function(member, width, height, resizeMethod) { var url = MatrixClientPeg.get().getAvatarUrlForMember( - member, width, height, resizeMethod, false + member, + width, + height, + resizeMethod ); - if (url === null) { + if (!url) { url = this.defaultAvatarUrlForString(member.userId); } return url; @@ -37,13 +40,10 @@ module.exports = { switch (total % 3) { case 0: return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrszQENADAIACB9QjNbxSKP4eagAFnTseHFErFYLBaLxWKxWCwWi8Vi8cX4CzAABSwCRWJw31gAAAAASUVORK5CYII="; - break; case 1: return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrszQENADAIACB9chOaxgCP4eagAFk9seHFErFYLBaLxWKxWCwWi8Vi8cX4CzAAtKMCks/JG8MAAAAASUVORK5CYII="; - break; case 2: return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrszQENADAIACB9YzNayQCP4eagADldseHFErFYLBaLxWKxWCwWi8Vi8cX4CzAAyiACeHwPiu4AAAAASUVORK5CYII="; - break; } } } diff --git a/src/CallHandler.js b/src/CallHandler.js deleted file mode 100644 index 025ece386..000000000 --- a/src/CallHandler.js +++ /dev/null @@ -1,281 +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'; - -/* - * Manages a list of all the currently active calls. - * - * This handler dispatches when voip calls are added/updated/removed from this list: - * { - * action: 'call_state' - * room_id: - * } - * - * To know the state of the call, this handler exposes a getter to - * obtain the call for a room: - * var call = CallHandler.getCall(roomId) - * var state = call.call_state; // ringing|ringback|connected|ended|busy|stop_ringback|stop_ringing - * - * This handler listens for and handles the following actions: - * { - * action: 'place_call', - * type: 'voice|video', - * room_id: - * } - * - * { - * action: 'incoming_call' - * call: MatrixCall - * } - * - * { - * action: 'hangup' - * room_id: - * } - * - * { - * action: 'answer' - * room_id: - * } - */ - -var MatrixClientPeg = require("./MatrixClientPeg"); -var Modal = require("./Modal"); -var ComponentBroker = require('./ComponentBroker'); -var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog"); -var ConferenceCall = require("./ConferenceHandler").ConferenceCall; -var ConferenceHandler = require("./ConferenceHandler"); -var Matrix = require("matrix-js-sdk"); -var dis = require("./dispatcher"); - -var calls = { - //room_id: MatrixCall -}; - -function play(audioId) { - // TODO: Attach an invisible element for this instead - // which listens? - var audio = document.getElementById(audioId); - if (audio) { - audio.load(); - audio.play(); - } -} - -function pause(audioId) { - // TODO: Attach an invisible element for this instead - // which listens? - var audio = document.getElementById(audioId); - if (audio) { - audio.pause(); - } -} - -function _setCallListeners(call) { - call.on("error", function(err) { - console.error("Call error: %s", err); - console.error(err.stack); - call.hangup(); - _setCallState(undefined, call.roomId, "ended"); - }); - call.on("hangup", function() { - _setCallState(undefined, call.roomId, "ended"); - }); - // map web rtc states to dummy UI state - // ringing|ringback|connected|ended|busy|stop_ringback|stop_ringing - call.on("state", function(newState, oldState) { - if (newState === "ringing") { - _setCallState(call, call.roomId, "ringing"); - pause("ringbackAudio"); - } - else if (newState === "invite_sent") { - _setCallState(call, call.roomId, "ringback"); - play("ringbackAudio"); - } - else if (newState === "ended" && oldState === "connected") { - _setCallState(undefined, call.roomId, "ended"); - pause("ringbackAudio"); - play("callendAudio"); - } - else if (newState === "ended" && oldState === "invite_sent" && - (call.hangupParty === "remote" || - (call.hangupParty === "local" && call.hangupReason === "invite_timeout") - )) { - _setCallState(call, call.roomId, "busy"); - pause("ringbackAudio"); - play("busyAudio"); - Modal.createDialog(ErrorDialog, { - title: "Call Timeout", - description: "The remote side failed to pick up." - }); - } - else if (oldState === "invite_sent") { - _setCallState(call, call.roomId, "stop_ringback"); - pause("ringbackAudio"); - } - else if (oldState === "ringing") { - _setCallState(call, call.roomId, "stop_ringing"); - pause("ringbackAudio"); - } - else if (newState === "connected") { - _setCallState(call, call.roomId, "connected"); - pause("ringbackAudio"); - } - }); -} - -function _setCallState(call, roomId, status) { - console.log( - "Call state in %s changed to %s (%s)", roomId, status, (call ? call.state : "-") - ); - calls[roomId] = call; - if (call) { - call.call_state = status; - } - dis.dispatch({ - action: 'call_state', - room_id: roomId - }); -} - -dis.register(function(payload) { - switch (payload.action) { - case 'place_call': - if (module.exports.getAnyActiveCall()) { - Modal.createDialog(ErrorDialog, { - title: "Existing Call", - description: "You are already in a call." - }); - return; // don't allow >1 call to be placed. - } - var room = MatrixClientPeg.get().getRoom(payload.room_id); - if (!room) { - console.error("Room %s does not exist.", payload.room_id); - return; - } - - function placeCall(newCall) { - _setCallListeners(newCall); - _setCallState(newCall, newCall.roomId, "ringback"); - if (payload.type === 'voice') { - newCall.placeVoiceCall(); - } - else if (payload.type === 'video') { - newCall.placeVideoCall( - payload.remote_element, - payload.local_element - ); - } - else { - console.error("Unknown conf call type: %s", payload.type); - } - } - - var members = room.getJoinedMembers(); - if (members.length <= 1) { - Modal.createDialog(ErrorDialog, { - description: "You cannot place a call with yourself." - }); - return; - } - else if (members.length === 2) { - console.log("Place %s call in %s", payload.type, payload.room_id); - var call = Matrix.createNewMatrixCall( - MatrixClientPeg.get(), payload.room_id - ); - placeCall(call); - } - else { // > 2 - console.log("Place conference call in %s", payload.room_id); - var confCall = new ConferenceCall( - MatrixClientPeg.get(), payload.room_id - ); - confCall.setup().done(function(call) { - placeCall(call); - }, function(err) { - console.error("Failed to setup conference call: %s", err); - }); - } - break; - case 'incoming_call': - if (module.exports.getAnyActiveCall()) { - payload.call.hangup("busy"); - return; // don't allow >1 call to be received, hangup newer one. - } - var call = payload.call; - _setCallListeners(call); - _setCallState(call, call.roomId, "ringing"); - break; - case 'hangup': - if (!calls[payload.room_id]) { - return; // no call to hangup - } - calls[payload.room_id].hangup(); - _setCallState(null, payload.room_id, "ended"); - break; - case 'answer': - if (!calls[payload.room_id]) { - return; // no call to answer - } - calls[payload.room_id].answer(); - _setCallState(calls[payload.room_id], payload.room_id, "connected"); - dis.dispatch({ - action: "view_room", - room_id: payload.room_id - }); - break; - } -}); - -module.exports = { - - getCallForRoom: function(roomId) { - return ( - module.exports.getCall(roomId) || - module.exports.getConferenceCall(roomId) - ); - }, - - getCall: function(roomId) { - return calls[roomId] || null; - }, - - getConferenceCall: function(roomId) { - // search for a conference 1:1 call for this group chat room ID - var activeCall = module.exports.getAnyActiveCall(); - if (activeCall && activeCall.confUserId) { - var thisRoomConfUserId = ConferenceHandler.getConferenceUserIdForRoom( - roomId - ); - if (thisRoomConfUserId === activeCall.confUserId) { - return activeCall; - } - } - return null; - }, - - getAnyActiveCall: function() { - var roomsWithCalls = Object.keys(calls); - for (var i = 0; i < roomsWithCalls.length; i++) { - if (calls[roomsWithCalls[i]] && - calls[roomsWithCalls[i]].call_state !== "ended") { - return calls[roomsWithCalls[i]]; - } - } - return null; - } -}; \ No newline at end of file diff --git a/src/ComponentBroker.js b/src/ComponentBroker.js deleted file mode 100644 index 61499defc..000000000 --- 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 fdd29fd58..000000000 --- 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/ContextualMenu.js b/src/ContextualMenu.js index cabab0c37..cdfff952b 100644 --- a/src/ContextualMenu.js +++ b/src/ContextualMenu.js @@ -18,7 +18,6 @@ limitations under the License. 'use strict'; var React = require('react'); -var q = require('q'); // Shamelessly ripped off Modal.js. There's probably a better way // of doing reusable widgets like dialog boxes & menus where we go and diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js deleted file mode 100644 index 36ccd0a7d..000000000 --- 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 fa9f038b0..000000000 --- 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 ba7660bf9..000000000 --- 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 558c7e992..000000000 --- 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 730a0de18..000000000 --- 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 b47b953a1..000000000 --- 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 3d6ba2cf6..000000000 --- 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 4fb539902..000000000 --- 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 5ea4ce8c4..000000000 --- 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 d6638b275..000000000 --- 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/LogoutButton.js b/src/controllers/atoms/LogoutButton.js deleted file mode 100644 index 87cf81480..000000000 --- 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 f29b3544e..000000000 --- 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 8aa688b21..000000000 --- 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 1504a7761..000000000 --- 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 f03dd56c9..000000000 --- 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 bcc2f5148..000000000 --- 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 4b268e902..000000000 --- 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 8aa688b21..000000000 --- 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 72a541b1a..000000000 --- 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 5cc73c5de..000000000 --- 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 8aa688b21..000000000 --- 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 1fb117cee..000000000 --- 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 bd3576e57..000000000 --- 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 8aa688b21..000000000 --- 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 aceb02949..000000000 --- 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 1fb117cee..000000000 --- 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 8aa688b21..000000000 --- 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 21cbe7a54..000000000 --- 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 43db7d1db..000000000 --- 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 3bd0f7f8e..000000000 --- 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 47b616e72..000000000 --- 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 c711650a2..000000000 --- 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 c7e023fc3..000000000 --- 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 fe7cd6343..000000000 --- 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 78927ec55..000000000 --- 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 8aa688b21..000000000 --- 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 3f5dd99bb..000000000 --- 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/UserSelector.js b/src/controllers/molecules/UserSelector.js deleted file mode 100644 index 67a56163f..000000000 --- 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/CallView.js b/src/controllers/molecules/voip/CallView.js index a20e44633..d511b9d41 100644 --- a/src/controllers/molecules/voip/CallView.js +++ b/src/controllers/molecules/voip/CallView.js @@ -15,9 +15,11 @@ limitations under the License. */ 'use strict'; -var dis = require("../../../dispatcher"); -var CallHandler = require("../../../CallHandler"); -var MatrixClientPeg = require("../../../MatrixClientPeg"); +var dis = require("matrix-react-sdk/lib/dispatcher"); +var CallHandler = require("matrix-react-sdk/lib/CallHandler"); +var MatrixClientPeg = require("matrix-react-sdk/lib/MatrixClientPeg"); + +var VectorConferenceHandler = require('../../../modules/VectorConferenceHandler'); /* * State vars: @@ -66,7 +68,10 @@ module.exports = { }, showCall: function(roomId) { - var call = CallHandler.getCallForRoom(roomId); + var call = ( + CallHandler.getCallForRoom(roomId) || + VectorConferenceHandler.getConferenceCallForRoom(roomId) + ); if (call) { call.setLocalVideoElement(this.getVideoView().getLocalVideoElement()); // N.B. the remote video element is used for playback for audio for voice calls diff --git a/src/controllers/molecules/voip/IncomingCallBox.js b/src/controllers/molecules/voip/IncomingCallBox.js deleted file mode 100644 index 809c0833e..000000000 --- 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 8aa688b21..000000000 --- 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 f6404eb23..000000000 --- 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 73f66c87e..000000000 --- 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 8875a55cb..000000000 --- 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 3fb613e05..000000000 --- a/src/controllers/organisms/MemberList.js +++ /dev/null @@ -1,184 +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; - - // Lazy-load in more than the first N members - 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) { - // XXX: evil hack to track the age of this presence info. - // this should be removed once syjs-28 is resolved in the JS SDK itself. - user.lastPresenceTs = Date.now(); - - var tile = self.refs[user.userId]; - - console.log("presence event " + JSON.stringify(event) + " user = " + user + " tile = " + tile); - - if (tile) { - self._updateList(); // reorder the membership list - self.forceUpdate(); // FIXME: is the a more efficient way of reordering with react? - // XXX: do we even need to do this, or is it done by the main list? - tile.forceUpdate(); - } - } - // FIXME: we should probably also reset 'lastActiveAgo' to zero whenever - // we see a typing notif from a user, as we don't get presence updates for those. - 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); - - // XXX: evil hack until SYJS-28 is fixed - all_user_ids.map(function(userId) { - if (all_members[userId].user && !all_members[userId].user.lastPresenceTs) { - all_members[userId].user.lastPresenceTs = Date.now(); - } - }); - - all_user_ids.sort(function(userIdA, userIdB) { - var userA = all_members[userIdA].user; - var userB = all_members[userIdB].user; - - var latA = userA ? (userA.lastPresenceTs - (userA.lastActiveAgo || userA.lastPresenceTs)) : 0; - var latB = userB ? (userB.lastPresenceTs - (userB.lastActiveAgo || userB.lastPresenceTs)) : 0; - - return latB - latA; - }); - - 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') { - // XXX: this is evil, and relies on the fact that Object.keys() iterates - // over the keys of a dict in insertion order (if those keys are strings) - 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 0d493bf34..000000000 --- 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 c890d143a..000000000 --- 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 index 3933f53ec..2602315ac 100644 --- a/src/controllers/organisms/RoomList.js +++ b/src/controllers/organisms/RoomList.js @@ -17,15 +17,13 @@ limitations under the License. 'use strict'; var React = require("react"); -var MatrixClientPeg = require("../../MatrixClientPeg"); -var RoomListSorter = require("../../RoomListSorter"); -var dis = require("../../dispatcher"); +var MatrixClientPeg = require("matrix-react-sdk/lib/MatrixClientPeg"); +var RoomListSorter = require("matrix-react-sdk/lib/RoomListSorter"); +var dis = require("matrix-react-sdk/lib/dispatcher"); -var ComponentBroker = require('../../ComponentBroker'); -var ConferenceHandler = require("../../ConferenceHandler"); -var CallHandler = require("../../CallHandler"); - -var RoomTile = ComponentBroker.get("molecules/RoomTile"); +var sdk = require('matrix-react-sdk'); +var VectorConferenceHandler = require("../../modules/VectorConferenceHandler"); +var CallHandler = require("matrix-react-sdk/lib/CallHandler"); var HIDE_CONFERENCE_CHANS = true; @@ -129,7 +127,7 @@ module.exports = { var otherMember = joinedMembers.filter(function(m) { return m.userId !== me.userId })[0]; - if (ConferenceHandler.isConferenceUser(otherMember)) { + if (VectorConferenceHandler.isConferenceUser(otherMember)) { // console.log("Hiding conference 1:1 room %s", room.roomId); shouldShowRoom = false; } @@ -154,6 +152,7 @@ module.exports = { makeRoomTiles: function() { var self = this; + var RoomTile = sdk.getComponent("molecules.RoomTile"); 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 c6881de36..000000000 --- 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 4eb1fd590..000000000 --- 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 08cc652d9..000000000 --- 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 f3528e33a..000000000 --- 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 5ed5d7dc5..000000000 --- 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 3edb9c694..000000000 --- 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 dea454a3f..000000000 --- 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 178748d72..000000000 --- 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 febf8d0dc..000000000 --- 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 273fe123a..000000000 --- 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/src/ConferenceHandler.js b/src/modules/VectorConferenceHandler.js similarity index 71% rename from src/ConferenceHandler.js rename to src/modules/VectorConferenceHandler.js index c617672eb..637e34f94 100644 --- a/src/ConferenceHandler.js +++ b/src/modules/VectorConferenceHandler.js @@ -1,7 +1,25 @@ +/* +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 Matrix = require("matrix-js-sdk"); var Room = Matrix.Room; +var CallHandler = require('matrix-react-sdk/lib/CallHandler'); // FIXME: This currently forces Vector to try to hit the matrix.org AS for conferencing. // This is bad because it prevents people running their own ASes from being used. @@ -90,5 +108,27 @@ module.exports.getConferenceUserIdForRoom = function(roomId) { return "@" + USER_PREFIX + base64RoomId + ":" + DOMAIN; }; +module.exports.createNewMatrixCall = function(client, roomId) { + var confCall = new ConferenceCall( + client, roomId + ); + return confCall.setup(); +}; + +module.exports.getConferenceCallForRoom = function(roomId) { + // search for a conference 1:1 call for this group chat room ID + var activeCall = CallHandler.getAnyActiveCall(); + if (activeCall && activeCall.confUserId) { + var thisRoomConfUserId = module.exports.getConferenceUserIdForRoom( + roomId + ); + if (thisRoomConfUserId === activeCall.confUserId) { + return activeCall; + } + } + return null; +}; + module.exports.ConferenceCall = ConferenceCall; +module.exports.slot = 'conference'; diff --git a/skins/base/css/atoms/MemberAvatar.css b/src/skins/vector/css/atoms/MemberAvatar.css similarity index 100% rename from skins/base/css/atoms/MemberAvatar.css rename to src/skins/vector/css/atoms/MemberAvatar.css diff --git a/skins/base/css/atoms/MessageTimestamp.css b/src/skins/vector/css/atoms/MessageTimestamp.css similarity index 100% rename from skins/base/css/atoms/MessageTimestamp.css rename to src/skins/vector/css/atoms/MessageTimestamp.css diff --git a/skins/base/css/common.css b/src/skins/vector/css/common.css similarity index 100% rename from skins/base/css/common.css rename to src/skins/vector/css/common.css diff --git a/skins/base/css/hide.css b/src/skins/vector/css/hide.css similarity index 100% rename from skins/base/css/hide.css rename to src/skins/vector/css/hide.css diff --git a/skins/base/css/molecules/MImageTile.css b/src/skins/vector/css/molecules/MImageTile.css similarity index 100% rename from skins/base/css/molecules/MImageTile.css rename to src/skins/vector/css/molecules/MImageTile.css diff --git a/skins/base/css/molecules/MNoticeTile.css b/src/skins/vector/css/molecules/MNoticeTile.css similarity index 100% rename from skins/base/css/molecules/MNoticeTile.css rename to src/skins/vector/css/molecules/MNoticeTile.css diff --git a/skins/base/css/molecules/MTextTile.css b/src/skins/vector/css/molecules/MTextTile.css similarity index 100% rename from skins/base/css/molecules/MTextTile.css rename to src/skins/vector/css/molecules/MTextTile.css diff --git a/skins/base/css/molecules/MatrixToolbar.css b/src/skins/vector/css/molecules/MatrixToolbar.css similarity index 100% rename from skins/base/css/molecules/MatrixToolbar.css rename to src/skins/vector/css/molecules/MatrixToolbar.css diff --git a/skins/base/css/molecules/MemberInfo.css b/src/skins/vector/css/molecules/MemberInfo.css similarity index 100% rename from skins/base/css/molecules/MemberInfo.css rename to src/skins/vector/css/molecules/MemberInfo.css diff --git a/skins/base/css/molecules/MemberTile.css b/src/skins/vector/css/molecules/MemberTile.css similarity index 100% rename from skins/base/css/molecules/MemberTile.css rename to src/skins/vector/css/molecules/MemberTile.css diff --git a/skins/base/css/molecules/MessageComposer.css b/src/skins/vector/css/molecules/MessageComposer.css similarity index 100% rename from skins/base/css/molecules/MessageComposer.css rename to src/skins/vector/css/molecules/MessageComposer.css diff --git a/skins/base/css/molecules/MessageTile.css b/src/skins/vector/css/molecules/MessageTile.css similarity index 100% rename from skins/base/css/molecules/MessageTile.css rename to src/skins/vector/css/molecules/MessageTile.css diff --git a/skins/base/css/molecules/ProgressBar.css b/src/skins/vector/css/molecules/ProgressBar.css similarity index 100% rename from skins/base/css/molecules/ProgressBar.css rename to src/skins/vector/css/molecules/ProgressBar.css diff --git a/skins/base/css/molecules/RoomDropTarget.css b/src/skins/vector/css/molecules/RoomDropTarget.css similarity index 100% rename from skins/base/css/molecules/RoomDropTarget.css rename to src/skins/vector/css/molecules/RoomDropTarget.css diff --git a/skins/base/css/molecules/RoomHeader.css b/src/skins/vector/css/molecules/RoomHeader.css similarity index 100% rename from skins/base/css/molecules/RoomHeader.css rename to src/skins/vector/css/molecules/RoomHeader.css diff --git a/skins/base/css/molecules/RoomSettings.css b/src/skins/vector/css/molecules/RoomSettings.css similarity index 100% rename from skins/base/css/molecules/RoomSettings.css rename to src/skins/vector/css/molecules/RoomSettings.css diff --git a/skins/base/css/molecules/RoomTile.css b/src/skins/vector/css/molecules/RoomTile.css similarity index 100% rename from skins/base/css/molecules/RoomTile.css rename to src/skins/vector/css/molecules/RoomTile.css diff --git a/skins/base/css/molecules/SenderProfile.css b/src/skins/vector/css/molecules/SenderProfile.css similarity index 100% rename from skins/base/css/molecules/SenderProfile.css rename to src/skins/vector/css/molecules/SenderProfile.css diff --git a/skins/base/css/molecules/ServerConfig.css b/src/skins/vector/css/molecules/ServerConfig.css similarity index 100% rename from skins/base/css/molecules/ServerConfig.css rename to src/skins/vector/css/molecules/ServerConfig.css diff --git a/skins/base/css/molecules/voip/CallView.css b/src/skins/vector/css/molecules/voip/CallView.css similarity index 100% rename from skins/base/css/molecules/voip/CallView.css rename to src/skins/vector/css/molecules/voip/CallView.css diff --git a/skins/base/css/molecules/voip/IncomingCallbox.css b/src/skins/vector/css/molecules/voip/IncomingCallbox.css similarity index 100% rename from skins/base/css/molecules/voip/IncomingCallbox.css rename to src/skins/vector/css/molecules/voip/IncomingCallbox.css diff --git a/skins/base/css/molecules/voip/VideoView.css b/src/skins/vector/css/molecules/voip/VideoView.css similarity index 100% rename from skins/base/css/molecules/voip/VideoView.css rename to src/skins/vector/css/molecules/voip/VideoView.css diff --git a/skins/base/css/organisms/CreateRoom.css b/src/skins/vector/css/organisms/CreateRoom.css similarity index 100% rename from skins/base/css/organisms/CreateRoom.css rename to src/skins/vector/css/organisms/CreateRoom.css diff --git a/skins/base/css/organisms/LeftPanel.css b/src/skins/vector/css/organisms/LeftPanel.css similarity index 100% rename from skins/base/css/organisms/LeftPanel.css rename to src/skins/vector/css/organisms/LeftPanel.css diff --git a/skins/base/css/organisms/MemberList.css b/src/skins/vector/css/organisms/MemberList.css similarity index 100% rename from skins/base/css/organisms/MemberList.css rename to src/skins/vector/css/organisms/MemberList.css diff --git a/skins/base/css/organisms/RightPanel.css b/src/skins/vector/css/organisms/RightPanel.css similarity index 100% rename from skins/base/css/organisms/RightPanel.css rename to src/skins/vector/css/organisms/RightPanel.css diff --git a/skins/base/css/organisms/RoomDirectory.css b/src/skins/vector/css/organisms/RoomDirectory.css similarity index 100% rename from skins/base/css/organisms/RoomDirectory.css rename to src/skins/vector/css/organisms/RoomDirectory.css diff --git a/skins/base/css/organisms/RoomList.css b/src/skins/vector/css/organisms/RoomList.css similarity index 100% rename from skins/base/css/organisms/RoomList.css rename to src/skins/vector/css/organisms/RoomList.css diff --git a/skins/base/css/organisms/RoomView.css b/src/skins/vector/css/organisms/RoomView.css similarity index 100% rename from skins/base/css/organisms/RoomView.css rename to src/skins/vector/css/organisms/RoomView.css diff --git a/skins/base/css/organisms/UserSettings.css b/src/skins/vector/css/organisms/UserSettings.css similarity index 100% rename from skins/base/css/organisms/UserSettings.css rename to src/skins/vector/css/organisms/UserSettings.css diff --git a/skins/base/css/pages/MatrixChat.css b/src/skins/vector/css/pages/MatrixChat.css similarity index 100% rename from skins/base/css/pages/MatrixChat.css rename to src/skins/vector/css/pages/MatrixChat.css diff --git a/skins/base/css/templates/Login.css b/src/skins/vector/css/templates/Login.css similarity index 100% rename from skins/base/css/templates/Login.css rename to src/skins/vector/css/templates/Login.css diff --git a/skins/base/fonts/22JRxvfANxSmnAhzbFH8PgLUuEpTyoUstqEm5AMlJo4.woff2 b/src/skins/vector/fonts/22JRxvfANxSmnAhzbFH8PgLUuEpTyoUstqEm5AMlJo4.woff2 similarity index 100% rename from skins/base/fonts/22JRxvfANxSmnAhzbFH8PgLUuEpTyoUstqEm5AMlJo4.woff2 rename to src/skins/vector/fonts/22JRxvfANxSmnAhzbFH8PgLUuEpTyoUstqEm5AMlJo4.woff2 diff --git a/skins/base/fonts/8qcEw_nrk_5HEcCpYdJu8BTbgVql8nDJpwnrE27mub0.woff2 b/src/skins/vector/fonts/8qcEw_nrk_5HEcCpYdJu8BTbgVql8nDJpwnrE27mub0.woff2 similarity index 100% rename from skins/base/fonts/8qcEw_nrk_5HEcCpYdJu8BTbgVql8nDJpwnrE27mub0.woff2 rename to src/skins/vector/fonts/8qcEw_nrk_5HEcCpYdJu8BTbgVql8nDJpwnrE27mub0.woff2 diff --git a/skins/base/fonts/IY9HZVvI1cMoAHxvl0w9LVKPGs1ZzpMvnHX-7fPOuAc.woff2 b/src/skins/vector/fonts/IY9HZVvI1cMoAHxvl0w9LVKPGs1ZzpMvnHX-7fPOuAc.woff2 similarity index 100% rename from skins/base/fonts/IY9HZVvI1cMoAHxvl0w9LVKPGs1ZzpMvnHX-7fPOuAc.woff2 rename to src/skins/vector/fonts/IY9HZVvI1cMoAHxvl0w9LVKPGs1ZzpMvnHX-7fPOuAc.woff2 diff --git a/skins/base/fonts/Lato.css b/src/skins/vector/fonts/Lato.css similarity index 100% rename from skins/base/fonts/Lato.css rename to src/skins/vector/fonts/Lato.css diff --git a/skins/base/fonts/MDadn8DQ_3oT6kvnUq_2r_esZW2xOQ-xsNqO47m55DA.woff2 b/src/skins/vector/fonts/MDadn8DQ_3oT6kvnUq_2r_esZW2xOQ-xsNqO47m55DA.woff2 similarity index 100% rename from skins/base/fonts/MDadn8DQ_3oT6kvnUq_2r_esZW2xOQ-xsNqO47m55DA.woff2 rename to src/skins/vector/fonts/MDadn8DQ_3oT6kvnUq_2r_esZW2xOQ-xsNqO47m55DA.woff2 diff --git a/skins/base/fonts/MgNNr5y1C_tIEuLEmicLmwLUuEpTyoUstqEm5AMlJo4.woff2 b/src/skins/vector/fonts/MgNNr5y1C_tIEuLEmicLmwLUuEpTyoUstqEm5AMlJo4.woff2 similarity index 100% rename from skins/base/fonts/MgNNr5y1C_tIEuLEmicLmwLUuEpTyoUstqEm5AMlJo4.woff2 rename to src/skins/vector/fonts/MgNNr5y1C_tIEuLEmicLmwLUuEpTyoUstqEm5AMlJo4.woff2 diff --git a/skins/base/fonts/rZPI2gHXi8zxUjnybc2ZQFKPGs1ZzpMvnHX-7fPOuAc.woff2 b/src/skins/vector/fonts/rZPI2gHXi8zxUjnybc2ZQFKPGs1ZzpMvnHX-7fPOuAc.woff2 similarity index 100% rename from skins/base/fonts/rZPI2gHXi8zxUjnybc2ZQFKPGs1ZzpMvnHX-7fPOuAc.woff2 rename to src/skins/vector/fonts/rZPI2gHXi8zxUjnybc2ZQFKPGs1ZzpMvnHX-7fPOuAc.woff2 diff --git a/src/controllers/molecules/UnknownMessageTile.js b/src/skins/vector/header similarity index 93% rename from src/controllers/molecules/UnknownMessageTile.js rename to src/skins/vector/header index d0977e004..fd88ee27f 100644 --- a/src/controllers/molecules/UnknownMessageTile.js +++ b/src/skins/vector/header @@ -13,8 +13,3 @@ 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/skins/base/img/attach.png b/src/skins/vector/img/attach.png similarity index 100% rename from skins/base/img/attach.png rename to src/skins/vector/img/attach.png diff --git a/skins/base/img/chevron-left.png b/src/skins/vector/img/chevron-left.png similarity index 100% rename from skins/base/img/chevron-left.png rename to src/skins/vector/img/chevron-left.png diff --git a/skins/base/img/chevron-right.png b/src/skins/vector/img/chevron-right.png similarity index 100% rename from skins/base/img/chevron-right.png rename to src/skins/vector/img/chevron-right.png diff --git a/skins/base/img/chevron.png b/src/skins/vector/img/chevron.png similarity index 100% rename from skins/base/img/chevron.png rename to src/skins/vector/img/chevron.png diff --git a/skins/base/img/close-white.png b/src/skins/vector/img/close-white.png similarity index 100% rename from skins/base/img/close-white.png rename to src/skins/vector/img/close-white.png diff --git a/skins/base/img/create-big.png b/src/skins/vector/img/create-big.png similarity index 100% rename from skins/base/img/create-big.png rename to src/skins/vector/img/create-big.png diff --git a/skins/base/img/create.png b/src/skins/vector/img/create.png similarity index 100% rename from skins/base/img/create.png rename to src/skins/vector/img/create.png diff --git a/skins/base/img/delete.png b/src/skins/vector/img/delete.png similarity index 100% rename from skins/base/img/delete.png rename to src/skins/vector/img/delete.png diff --git a/skins/base/img/directory-big.png b/src/skins/vector/img/directory-big.png similarity index 100% rename from skins/base/img/directory-big.png rename to src/skins/vector/img/directory-big.png diff --git a/skins/base/img/download.png b/src/skins/vector/img/download.png similarity index 100% rename from skins/base/img/download.png rename to src/skins/vector/img/download.png diff --git a/skins/base/img/edit.png b/src/skins/vector/img/edit.png similarity index 100% rename from skins/base/img/edit.png rename to src/skins/vector/img/edit.png diff --git a/skins/base/img/file.png b/src/skins/vector/img/file.png similarity index 100% rename from skins/base/img/file.png rename to src/skins/vector/img/file.png diff --git a/skins/base/img/filegrid.png b/src/skins/vector/img/filegrid.png similarity index 100% rename from skins/base/img/filegrid.png rename to src/skins/vector/img/filegrid.png diff --git a/skins/base/img/filelist.png b/src/skins/vector/img/filelist.png similarity index 100% rename from skins/base/img/filelist.png rename to src/skins/vector/img/filelist.png diff --git a/skins/base/img/hide.png b/src/skins/vector/img/hide.png similarity index 100% rename from skins/base/img/hide.png rename to src/skins/vector/img/hide.png diff --git a/skins/base/img/info.png b/src/skins/vector/img/info.png similarity index 100% rename from skins/base/img/info.png rename to src/skins/vector/img/info.png diff --git a/skins/base/img/logo.png b/src/skins/vector/img/logo.png similarity index 100% rename from skins/base/img/logo.png rename to src/skins/vector/img/logo.png diff --git a/skins/base/img/members.png b/src/skins/vector/img/members.png similarity index 100% rename from skins/base/img/members.png rename to src/skins/vector/img/members.png diff --git a/skins/base/img/menu.png b/src/skins/vector/img/menu.png similarity index 100% rename from skins/base/img/menu.png rename to src/skins/vector/img/menu.png diff --git a/skins/base/img/newmessages.png b/src/skins/vector/img/newmessages.png similarity index 100% rename from skins/base/img/newmessages.png rename to src/skins/vector/img/newmessages.png diff --git a/skins/base/img/p/p0.png b/src/skins/vector/img/p/p0.png similarity index 100% rename from skins/base/img/p/p0.png rename to src/skins/vector/img/p/p0.png diff --git a/skins/base/img/p/p1.png b/src/skins/vector/img/p/p1.png similarity index 100% rename from skins/base/img/p/p1.png rename to src/skins/vector/img/p/p1.png diff --git a/skins/base/img/p/p10.png b/src/skins/vector/img/p/p10.png similarity index 100% rename from skins/base/img/p/p10.png rename to src/skins/vector/img/p/p10.png diff --git a/skins/base/img/p/p11.png b/src/skins/vector/img/p/p11.png similarity index 100% rename from skins/base/img/p/p11.png rename to src/skins/vector/img/p/p11.png diff --git a/skins/base/img/p/p12.png b/src/skins/vector/img/p/p12.png similarity index 100% rename from skins/base/img/p/p12.png rename to src/skins/vector/img/p/p12.png diff --git a/skins/base/img/p/p13.png b/src/skins/vector/img/p/p13.png similarity index 100% rename from skins/base/img/p/p13.png rename to src/skins/vector/img/p/p13.png diff --git a/skins/base/img/p/p14.png b/src/skins/vector/img/p/p14.png similarity index 100% rename from skins/base/img/p/p14.png rename to src/skins/vector/img/p/p14.png diff --git a/skins/base/img/p/p15.png b/src/skins/vector/img/p/p15.png similarity index 100% rename from skins/base/img/p/p15.png rename to src/skins/vector/img/p/p15.png diff --git a/skins/base/img/p/p16.png b/src/skins/vector/img/p/p16.png similarity index 100% rename from skins/base/img/p/p16.png rename to src/skins/vector/img/p/p16.png diff --git a/skins/base/img/p/p17.png b/src/skins/vector/img/p/p17.png similarity index 100% rename from skins/base/img/p/p17.png rename to src/skins/vector/img/p/p17.png diff --git a/skins/base/img/p/p18.png b/src/skins/vector/img/p/p18.png similarity index 100% rename from skins/base/img/p/p18.png rename to src/skins/vector/img/p/p18.png diff --git a/skins/base/img/p/p19.png b/src/skins/vector/img/p/p19.png similarity index 100% rename from skins/base/img/p/p19.png rename to src/skins/vector/img/p/p19.png diff --git a/skins/base/img/p/p2.png b/src/skins/vector/img/p/p2.png similarity index 100% rename from skins/base/img/p/p2.png rename to src/skins/vector/img/p/p2.png diff --git a/skins/base/img/p/p20.png b/src/skins/vector/img/p/p20.png similarity index 100% rename from skins/base/img/p/p20.png rename to src/skins/vector/img/p/p20.png diff --git a/skins/base/img/p/p3.png b/src/skins/vector/img/p/p3.png similarity index 100% rename from skins/base/img/p/p3.png rename to src/skins/vector/img/p/p3.png diff --git a/skins/base/img/p/p4.png b/src/skins/vector/img/p/p4.png similarity index 100% rename from skins/base/img/p/p4.png rename to src/skins/vector/img/p/p4.png diff --git a/skins/base/img/p/p5.png b/src/skins/vector/img/p/p5.png similarity index 100% rename from skins/base/img/p/p5.png rename to src/skins/vector/img/p/p5.png diff --git a/skins/base/img/p/p6.png b/src/skins/vector/img/p/p6.png similarity index 100% rename from skins/base/img/p/p6.png rename to src/skins/vector/img/p/p6.png diff --git a/skins/base/img/p/p7.png b/src/skins/vector/img/p/p7.png similarity index 100% rename from skins/base/img/p/p7.png rename to src/skins/vector/img/p/p7.png diff --git a/skins/base/img/p/p8.png b/src/skins/vector/img/p/p8.png similarity index 100% rename from skins/base/img/p/p8.png rename to src/skins/vector/img/p/p8.png diff --git a/skins/base/img/p/p9.png b/src/skins/vector/img/p/p9.png similarity index 100% rename from skins/base/img/p/p9.png rename to src/skins/vector/img/p/p9.png diff --git a/skins/base/img/p/piechart.pde b/src/skins/vector/img/p/piechart.pde similarity index 100% rename from skins/base/img/p/piechart.pde rename to src/skins/vector/img/p/piechart.pde diff --git a/skins/base/img/placeholder.png b/src/skins/vector/img/placeholder.png similarity index 100% rename from skins/base/img/placeholder.png rename to src/skins/vector/img/placeholder.png diff --git a/skins/base/img/search.png b/src/skins/vector/img/search.png similarity index 100% rename from skins/base/img/search.png rename to src/skins/vector/img/search.png diff --git a/skins/base/img/settings-big.png b/src/skins/vector/img/settings-big.png similarity index 100% rename from skins/base/img/settings-big.png rename to src/skins/vector/img/settings-big.png diff --git a/skins/base/img/settings.png b/src/skins/vector/img/settings.png similarity index 100% rename from skins/base/img/settings.png rename to src/skins/vector/img/settings.png diff --git a/skins/base/img/typing.png b/src/skins/vector/img/typing.png similarity index 100% rename from skins/base/img/typing.png rename to src/skins/vector/img/typing.png diff --git a/skins/base/img/upload-big.png b/src/skins/vector/img/upload-big.png similarity index 100% rename from skins/base/img/upload-big.png rename to src/skins/vector/img/upload-big.png diff --git a/skins/base/img/upload.png b/src/skins/vector/img/upload.png similarity index 100% rename from skins/base/img/upload.png rename to src/skins/vector/img/upload.png diff --git a/skins/base/img/video.png b/src/skins/vector/img/video.png similarity index 100% rename from skins/base/img/video.png rename to src/skins/vector/img/video.png diff --git a/skins/base/img/voip.png b/src/skins/vector/img/voip.png similarity index 100% rename from skins/base/img/voip.png rename to src/skins/vector/img/voip.png diff --git a/src/skins/vector/skindex.js b/src/skins/vector/skindex.js new file mode 100644 index 000000000..4f76ad62a --- /dev/null +++ b/src/skins/vector/skindex.js @@ -0,0 +1,82 @@ +/* +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. +*/ + +/* + * THIS FILE IS AUTO-GENERATED + * You can edit it you like, but your changes will be overwritten, + * so you'd just be trying to swim upstream like a salmon. + * You are not a salmon. + */ + +var skin = {}; + +skin['atoms.EditableText'] = require('./views/atoms/EditableText'); +skin['atoms.EnableNotificationsButton'] = require('./views/atoms/EnableNotificationsButton'); +skin['atoms.ImageView'] = require('./views/atoms/ImageView'); +skin['atoms.LogoutButton'] = require('./views/atoms/LogoutButton'); +skin['atoms.MemberAvatar'] = require('./views/atoms/MemberAvatar'); +skin['atoms.MessageTimestamp'] = require('./views/atoms/MessageTimestamp'); +skin['atoms.RoomAvatar'] = require('./views/atoms/RoomAvatar'); +skin['atoms.create_room.CreateRoomButton'] = require('./views/atoms/create_room/CreateRoomButton'); +skin['atoms.create_room.Presets'] = require('./views/atoms/create_room/Presets'); +skin['atoms.create_room.RoomAlias'] = require('./views/atoms/create_room/RoomAlias'); +skin['atoms.voip.VideoFeed'] = require('./views/atoms/voip/VideoFeed'); +skin['molecules.BottomLeftMenu'] = require('./views/molecules/BottomLeftMenu'); +skin['molecules.ChangeAvatar'] = require('./views/molecules/ChangeAvatar'); +skin['molecules.ChangePassword'] = require('./views/molecules/ChangePassword'); +skin['molecules.DateSeparator'] = require('./views/molecules/DateSeparator'); +skin['molecules.EventAsTextTile'] = require('./views/molecules/EventAsTextTile'); +skin['molecules.MEmoteTile'] = require('./views/molecules/MEmoteTile'); +skin['molecules.MFileTile'] = require('./views/molecules/MFileTile'); +skin['molecules.MImageTile'] = require('./views/molecules/MImageTile'); +skin['molecules.MNoticeTile'] = require('./views/molecules/MNoticeTile'); +skin['molecules.MRoomMemberTile'] = require('./views/molecules/MRoomMemberTile'); +skin['molecules.MTextTile'] = require('./views/molecules/MTextTile'); +skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar'); +skin['molecules.MemberInfo'] = require('./views/molecules/MemberInfo'); +skin['molecules.MemberTile'] = require('./views/molecules/MemberTile'); +skin['molecules.MessageComposer'] = require('./views/molecules/MessageComposer'); +skin['molecules.MessageTile'] = require('./views/molecules/MessageTile'); +skin['molecules.ProgressBar'] = require('./views/molecules/ProgressBar'); +skin['molecules.RoomCreate'] = require('./views/molecules/RoomCreate'); +skin['molecules.RoomDropTarget'] = require('./views/molecules/RoomDropTarget'); +skin['molecules.RoomHeader'] = require('./views/molecules/RoomHeader'); +skin['molecules.RoomSettings'] = require('./views/molecules/RoomSettings'); +skin['molecules.RoomTile'] = require('./views/molecules/RoomTile'); +skin['molecules.SenderProfile'] = require('./views/molecules/SenderProfile'); +skin['molecules.ServerConfig'] = require('./views/molecules/ServerConfig'); +skin['molecules.UnknownMessageTile'] = require('./views/molecules/UnknownMessageTile'); +skin['molecules.UserSelector'] = require('./views/molecules/UserSelector'); +skin['molecules.voip.CallView'] = require('./views/molecules/voip/CallView'); +skin['molecules.voip.IncomingCallBox'] = require('./views/molecules/voip/IncomingCallBox'); +skin['molecules.voip.VideoView'] = require('./views/molecules/voip/VideoView'); +skin['organisms.CreateRoom'] = require('./views/organisms/CreateRoom'); +skin['organisms.ErrorDialog'] = require('./views/organisms/ErrorDialog'); +skin['organisms.LeftPanel'] = require('./views/organisms/LeftPanel'); +skin['organisms.LogoutPrompt'] = require('./views/organisms/LogoutPrompt'); +skin['organisms.MemberList'] = require('./views/organisms/MemberList'); +skin['organisms.Notifier'] = require('./views/organisms/Notifier'); +skin['organisms.QuestionDialog'] = require('./views/organisms/QuestionDialog'); +skin['organisms.RightPanel'] = require('./views/organisms/RightPanel'); +skin['organisms.RoomDirectory'] = require('./views/organisms/RoomDirectory'); +skin['organisms.RoomList'] = require('./views/organisms/RoomList'); +skin['organisms.RoomView'] = require('./views/organisms/RoomView'); +skin['organisms.UserSettings'] = require('./views/organisms/UserSettings'); +skin['pages.MatrixChat'] = require('./views/pages/MatrixChat'); +skin['templates.Login'] = require('./views/templates/Login'); +skin['templates.Register'] = require('./views/templates/Register'); + +module.exports = skin; \ No newline at end of file diff --git a/src/skins/vector/skinfo.json b/src/skins/vector/skinfo.json new file mode 100644 index 000000000..287ff9e23 --- /dev/null +++ b/src/skins/vector/skinfo.json @@ -0,0 +1,3 @@ +{ + "baseSkin": "" +} diff --git a/skins/base/views/atoms/EditableText.js b/src/skins/vector/views/atoms/EditableText.js similarity index 95% rename from skins/base/views/atoms/EditableText.js rename to src/skins/vector/views/atoms/EditableText.js index d4aa28579..1848b029a 100644 --- a/skins/base/views/atoms/EditableText.js +++ b/src/skins/vector/views/atoms/EditableText.js @@ -18,7 +18,7 @@ limitations under the License. var React = require('react'); -var EditableTextController = require("../../../../src/controllers/atoms/EditableText"); +var EditableTextController = require('matrix-react-sdk/lib/controllers/atoms/EditableText') module.exports = React.createClass({ displayName: 'EditableText', diff --git a/skins/base/views/atoms/EnableNotificationsButton.js b/src/skins/vector/views/atoms/EnableNotificationsButton.js similarity index 90% rename from skins/base/views/atoms/EnableNotificationsButton.js rename to src/skins/vector/views/atoms/EnableNotificationsButton.js index 7caebb76c..edef9edc6 100644 --- a/skins/base/views/atoms/EnableNotificationsButton.js +++ b/src/skins/vector/views/atoms/EnableNotificationsButton.js @@ -18,7 +18,7 @@ limitations under the License. var React = require('react'); -var EnableNotificationsButtonController = require("../../../../src/controllers/atoms/EnableNotificationsButton"); +var EnableNotificationsButtonController = require('matrix-react-sdk/lib/controllers/atoms/EnableNotificationsButton') module.exports = React.createClass({ displayName: 'EnableNotificationsButton', diff --git a/skins/base/views/atoms/ImageView.js b/src/skins/vector/views/atoms/ImageView.js similarity index 96% rename from skins/base/views/atoms/ImageView.js rename to src/skins/vector/views/atoms/ImageView.js index 196e92fe9..a0d69bcc0 100644 --- a/skins/base/views/atoms/ImageView.js +++ b/src/skins/vector/views/atoms/ImageView.js @@ -18,7 +18,7 @@ limitations under the License. var React = require('react'); -var ImageViewController = require("../../../../src/controllers/atoms/ImageView"); +var ImageViewController = require('../../../../controllers/atoms/ImageView') module.exports = React.createClass({ displayName: 'ImageView', diff --git a/skins/base/views/atoms/LogoutButton.js b/src/skins/vector/views/atoms/LogoutButton.js similarity index 90% rename from skins/base/views/atoms/LogoutButton.js rename to src/skins/vector/views/atoms/LogoutButton.js index 8cc5b27d5..619160f61 100644 --- a/skins/base/views/atoms/LogoutButton.js +++ b/src/skins/vector/views/atoms/LogoutButton.js @@ -18,7 +18,7 @@ limitations under the License. var React = require('react'); -var LogoutButtonController = require("../../../../src/controllers/atoms/LogoutButton"); +var LogoutButtonController = require('matrix-react-sdk/lib/controllers/atoms/LogoutButton') module.exports = React.createClass({ displayName: 'LogoutButton', diff --git a/skins/base/views/atoms/MemberAvatar.js b/src/skins/vector/views/atoms/MemberAvatar.js similarity index 64% rename from skins/base/views/atoms/MemberAvatar.js rename to src/skins/vector/views/atoms/MemberAvatar.js index dccf0852d..69652e1a2 100644 --- a/skins/base/views/atoms/MemberAvatar.js +++ b/src/skins/vector/views/atoms/MemberAvatar.js @@ -17,13 +17,28 @@ limitations under the License. 'use strict'; var React = require('react'); +var Avatar = require('../../../../Avatar'); -var MemberAvatarController = require("../../../../src/controllers/atoms/MemberAvatar"); +var MemberAvatarController = require('matrix-react-sdk/lib/controllers/atoms/MemberAvatar') module.exports = React.createClass({ displayName: 'MemberAvatar', mixins: [MemberAvatarController], + avatarUrlForMember: function(member) { + return Avatar.avatarUrlForMember( + member, + this.props.member, + this.props.width, + this.props.height, + this.props.resizeMethod + ); + }, + + skinnedDefaultAvatarUrl: function(member, width, height, resizeMethod) { + return Avatar.defaultAvatarUrlForString(member.userId); + }, + render: function() { return ( : null; var text = this.getMemberEventText(); if (!text) return
    ; + var MessageTimestamp = sdk.getComponent('atoms.MessageTimestamp'); + var MemberAvatar = sdk.getComponent('atoms.MemberAvatar'); return (
    diff --git a/skins/base/views/molecules/MTextTile.js b/src/skins/vector/views/molecules/MTextTile.js similarity index 91% rename from skins/base/views/molecules/MTextTile.js rename to src/skins/vector/views/molecules/MTextTile.js index d08f42ed9..50555f949 100644 --- a/skins/base/views/molecules/MTextTile.js +++ b/src/skins/vector/views/molecules/MTextTile.js @@ -18,7 +18,7 @@ limitations under the License. var React = require('react'); -var MTextTileController = require("../../../../src/controllers/molecules/MTextTile"); +var MTextTileController = require('matrix-react-sdk/lib/controllers/molecules/MTextTile') module.exports = React.createClass({ displayName: 'MTextTile', diff --git a/skins/base/views/molecules/MatrixToolbar.js b/src/skins/vector/views/molecules/MatrixToolbar.js similarity index 76% rename from skins/base/views/molecules/MatrixToolbar.js rename to src/skins/vector/views/molecules/MatrixToolbar.js index f72304e1f..0b6c58e0d 100644 --- a/skins/base/views/molecules/MatrixToolbar.js +++ b/src/skins/vector/views/molecules/MatrixToolbar.js @@ -18,23 +18,21 @@ limitations under the License. var React = require('react'); -var ComponentBroker = require('../../../../src/ComponentBroker'); +var sdk = require('matrix-react-sdk') -var LogoutButton = ComponentBroker.get("atoms/LogoutButton"); -var EnableNotificationsButton = ComponentBroker.get("atoms/EnableNotificationsButton"); - -var MatrixToolbarController = require("../../../../src/controllers/molecules/MatrixToolbar"); -var Notifier = ComponentBroker.get('organisms/Notifier'); +var MatrixToolbarController = require('matrix-react-sdk/lib/controllers/molecules/MatrixToolbar') module.exports = React.createClass({ displayName: 'MatrixToolbar', mixins: [MatrixToolbarController], hideToolbar: function() { + var Notifier = sdk.getComponent('organisms.Notifier'); Notifier.setToolbarHidden(true); }, render: function() { + var EnableNotificationsButton = sdk.getComponent("atoms.EnableNotificationsButton"); return (
    You are not receiving desktop notifications. diff --git a/skins/base/views/molecules/MemberInfo.js b/src/skins/vector/views/molecules/MemberInfo.js similarity index 88% rename from skins/base/views/molecules/MemberInfo.js rename to src/skins/vector/views/molecules/MemberInfo.js index b57a5b6fc..cc9a8f2d3 100644 --- a/skins/base/views/molecules/MemberInfo.js +++ b/src/skins/vector/views/molecules/MemberInfo.js @@ -18,10 +18,8 @@ limitations under the License. var React = require('react'); -var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); -var MemberInfoController = require("../../../../src/controllers/molecules/MemberInfo"); -var ComponentBroker = require('../../../../src/ComponentBroker'); -var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar'); +var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); +var MemberInfoController = require('matrix-react-sdk/lib/controllers/molecules/MemberInfo') module.exports = React.createClass({ displayName: 'MemberInfo', diff --git a/skins/base/views/molecules/MemberTile.js b/src/skins/vector/views/molecules/MemberTile.js similarity index 91% rename from skins/base/views/molecules/MemberTile.js rename to src/skins/vector/views/molecules/MemberTile.js index d65cd0ed2..991616d58 100644 --- a/skins/base/views/molecules/MemberTile.js +++ b/src/skins/vector/views/molecules/MemberTile.js @@ -18,14 +18,10 @@ limitations under the License. var React = require('react'); -var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); -var ComponentBroker = require('../../../../src/ComponentBroker'); -var Modal = require("../../../../src/Modal"); -var ContextualMenu = require("../../../../src/ContextualMenu"); -var MemberTileController = require("../../../../src/controllers/molecules/MemberTile"); -var MemberInfo = ComponentBroker.get('molecules/MemberInfo'); -var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog"); -var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar'); +var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); +var sdk = require('matrix-react-sdk') +var ContextualMenu = require('../../../../ContextualMenu'); +var MemberTileController = require('matrix-react-sdk/lib/controllers/molecules/MemberTile') // The Lato WOFF doesn't include sensible combining diacritics, so Chrome chokes on rendering them. // Revert to Arial when this happens, which on OSX works at least. @@ -46,6 +42,7 @@ module.exports = React.createClass({ onClick: function(e) { var self = this; self.setState({ 'menu': true }); + var MemberInfo = sdk.getComponent('molecules.MemberInfo'); ContextualMenu.createMenu(MemberInfo, { member: self.props.member, right: window.innerWidth - e.pageX, @@ -153,6 +150,7 @@ module.exports = React.createClass({
    } + var MemberAvatar = sdk.getComponent('atoms.MemberAvatar'); return (
    diff --git a/skins/base/views/molecules/MessageComposer.js b/src/skins/vector/views/molecules/MessageComposer.js similarity index 86% rename from skins/base/views/molecules/MessageComposer.js rename to src/skins/vector/views/molecules/MessageComposer.js index a8d8a4eba..c94cade5f 100644 --- a/skins/base/views/molecules/MessageComposer.js +++ b/src/skins/vector/views/molecules/MessageComposer.js @@ -18,12 +18,10 @@ limitations under the License. var React = require('react'); -var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); -var MessageComposerController = require("../../../../src/controllers/molecules/MessageComposer"); -var ContentMessages = require("../../../../src/ContentMessages"); +var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); +var MessageComposerController = require('matrix-react-sdk/lib/controllers/molecules/MessageComposer') -var ComponentBroker = require('../../../../src/ComponentBroker'); -var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar'); +var sdk = require('matrix-react-sdk') module.exports = React.createClass({ displayName: 'MessageComposer', @@ -45,6 +43,7 @@ module.exports = React.createClass({ render: function() { var me = this.props.room.getMember(MatrixClientPeg.get().credentials.userId); var uploadInputStyle = {display: 'none'}; + var MemberAvatar = sdk.getComponent('atoms.MemberAvatar'); return (
    diff --git a/skins/base/views/molecules/MessageTile.js b/src/skins/vector/views/molecules/MessageTile.js similarity index 76% rename from skins/base/views/molecules/MessageTile.js rename to src/skins/vector/views/molecules/MessageTile.js index ac6342ac5..386b19d35 100644 --- a/skins/base/views/molecules/MessageTile.js +++ b/src/skins/vector/views/molecules/MessageTile.js @@ -20,30 +20,29 @@ var React = require('react'); var classNames = require("classnames"); -var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); -var ComponentBroker = require('../../../../src/ComponentBroker'); +var sdk = require('matrix-react-sdk') -var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp'); -var SenderProfile = ComponentBroker.get('molecules/SenderProfile'); -var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar'); - -var UnknownMessageTile = ComponentBroker.get('molecules/UnknownMessageTile'); - -var tileTypes = { - 'm.text': ComponentBroker.get('molecules/MTextTile'), - 'm.notice': ComponentBroker.get('molecules/MNoticeTile'), - 'm.emote': ComponentBroker.get('molecules/MEmoteTile'), - 'm.image': ComponentBroker.get('molecules/MImageTile'), - 'm.file': ComponentBroker.get('molecules/MFileTile') -}; - -var MessageTileController = require("../../../../src/controllers/molecules/MessageTile"); +var MessageTileController = require('matrix-react-sdk/lib/controllers/molecules/MessageTile') module.exports = React.createClass({ displayName: 'MessageTile', mixins: [MessageTileController], render: function() { + var MessageTimestamp = sdk.getComponent('atoms.MessageTimestamp'); + var SenderProfile = sdk.getComponent('molecules.SenderProfile'); + var MemberAvatar = sdk.getComponent('atoms.MemberAvatar'); + + var UnknownMessageTile = sdk.getComponent('molecules.UnknownMessageTile'); + + var tileTypes = { + 'm.text': sdk.getComponent('molecules.MTextTile'), + 'm.notice': sdk.getComponent('molecules.MNoticeTile'), + 'm.emote': sdk.getComponent('molecules.MEmoteTile'), + 'm.image': sdk.getComponent('molecules.MImageTile'), + 'm.file': sdk.getComponent('molecules.MFileTile') + }; + var content = this.props.mxEvent.getContent(); var msgtype = content.msgtype; var TileType = UnknownMessageTile; diff --git a/skins/base/views/molecules/ProgressBar.js b/src/skins/vector/views/molecules/ProgressBar.js similarity index 92% rename from skins/base/views/molecules/ProgressBar.js rename to src/skins/vector/views/molecules/ProgressBar.js index 0946ffcc2..18d1440ad 100644 --- a/skins/base/views/molecules/ProgressBar.js +++ b/src/skins/vector/views/molecules/ProgressBar.js @@ -18,7 +18,7 @@ limitations under the License. var React = require('react'); -var ProgressBarController = require("../../../../src/controllers/molecules/ProgressBar"); +var ProgressBarController = require('matrix-react-sdk/lib/controllers/molecules/ProgressBar') module.exports = React.createClass({ displayName: 'ProgressBar', diff --git a/skins/base/views/molecules/RoomCreate.js b/src/skins/vector/views/molecules/RoomCreate.js similarity index 83% rename from skins/base/views/molecules/RoomCreate.js rename to src/skins/vector/views/molecules/RoomCreate.js index 9ad4f428e..d66e014d8 100644 --- a/skins/base/views/molecules/RoomCreate.js +++ b/src/skins/vector/views/molecules/RoomCreate.js @@ -17,15 +17,10 @@ limitations under the License. 'use strict'; var React = require('react'); -var classNames = require('classnames'); - -//var RoomCreateController = require("../../../../src/controllers/molecules/RoomCreateController"); - -var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); module.exports = React.createClass({ displayName: 'RoomCreate', - // mixins: [RoomCreateController], + render: function() { return (
    diff --git a/skins/base/views/molecules/RoomDropTarget.js b/src/skins/vector/views/molecules/RoomDropTarget.js similarity index 80% rename from skins/base/views/molecules/RoomDropTarget.js rename to src/skins/vector/views/molecules/RoomDropTarget.js index 0a076949c..b1e150779 100644 --- a/skins/base/views/molecules/RoomDropTarget.js +++ b/src/skins/vector/views/molecules/RoomDropTarget.js @@ -17,11 +17,8 @@ limitations under the License. 'use strict'; var React = require('react'); -var classNames = require('classnames'); -//var RoomDropTargetController = require("../../../../src/controllers/molecules/RoomDropTargetController"); - -var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); +//var RoomDropTargetController = require('matrix-react-sdk/lib/controllers/molecules/RoomDropTargetController') module.exports = React.createClass({ displayName: 'RoomDropTarget', diff --git a/skins/base/views/molecules/RoomHeader.js b/src/skins/vector/views/molecules/RoomHeader.js similarity index 94% rename from skins/base/views/molecules/RoomHeader.js rename to src/skins/vector/views/molecules/RoomHeader.js index e3003b88c..f7d3fe7e5 100644 --- a/skins/base/views/molecules/RoomHeader.js +++ b/src/skins/vector/views/molecules/RoomHeader.js @@ -17,12 +17,10 @@ limitations under the License. 'use strict'; var React = require('react'); -var ComponentBroker = require('../../../../src/ComponentBroker'); +var sdk = require('matrix-react-sdk') -var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); -var RoomHeaderController = require("../../../../src/controllers/molecules/RoomHeader"); -var EditableText = ComponentBroker.get("atoms/EditableText"); -var RoomAvatar = ComponentBroker.get('atoms/RoomAvatar'); +var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); +var RoomHeaderController = require('matrix-react-sdk/lib/controllers/molecules/RoomHeader') module.exports = React.createClass({ displayName: 'RoomHeader', @@ -39,6 +37,8 @@ module.exports = React.createClass({ }, render: function() { + var EditableText = sdk.getComponent("atoms.EditableText"); + var RoomAvatar = sdk.getComponent('atoms.RoomAvatar'); var header; if (this.props.simpleHeader) { diff --git a/skins/base/views/molecules/RoomSettings.js b/src/skins/vector/views/molecules/RoomSettings.js similarity index 98% rename from skins/base/views/molecules/RoomSettings.js rename to src/skins/vector/views/molecules/RoomSettings.js index 7f48df205..d6d36a13b 100644 --- a/skins/base/views/molecules/RoomSettings.js +++ b/src/skins/vector/views/molecules/RoomSettings.js @@ -17,9 +17,9 @@ limitations under the License. 'use strict'; var React = require('react'); -var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); +var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); -var RoomSettingsController = require("../../../../src/controllers/molecules/RoomSettings"); +var RoomSettingsController = require('matrix-react-sdk/lib/controllers/molecules/RoomSettings') module.exports = React.createClass({ displayName: 'RoomSettings', diff --git a/skins/base/views/molecules/RoomTile.js b/src/skins/vector/views/molecules/RoomTile.js similarity index 89% rename from skins/base/views/molecules/RoomTile.js rename to src/skins/vector/views/molecules/RoomTile.js index b8e41fb8d..61fa0021b 100644 --- a/skins/base/views/molecules/RoomTile.js +++ b/src/skins/vector/views/molecules/RoomTile.js @@ -19,12 +19,11 @@ limitations under the License. var React = require('react'); var classNames = require('classnames'); -var RoomTileController = require("../../../../src/controllers/molecules/RoomTile"); +var RoomTileController = require('matrix-react-sdk/lib/controllers/molecules/RoomTile') -var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); +var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); -var ComponentBroker = require('../../../../src/ComponentBroker'); -var RoomAvatar = ComponentBroker.get('atoms/RoomAvatar'); +var sdk = require('matrix-react-sdk') module.exports = React.createClass({ displayName: 'RoomTile', @@ -58,6 +57,7 @@ module.exports = React.createClass({ nameCell =
    {name}
    ; } */ + var RoomAvatar = sdk.getComponent('atoms.RoomAvatar'); return (
    diff --git a/skins/base/views/molecules/SenderProfile.js b/src/skins/vector/views/molecules/SenderProfile.js similarity index 94% rename from skins/base/views/molecules/SenderProfile.js rename to src/skins/vector/views/molecules/SenderProfile.js index f13b29cf6..8be3adf27 100644 --- a/skins/base/views/molecules/SenderProfile.js +++ b/src/skins/vector/views/molecules/SenderProfile.js @@ -19,7 +19,7 @@ limitations under the License. var React = require('react'); var classNames = require("classnames"); -var SenderProfileController = require("../../../../src/controllers/molecules/SenderProfile"); +var SenderProfileController = require('matrix-react-sdk/lib/controllers/molecules/SenderProfile') // The Lato WOFF doesn't include sensible combining diacritics, so Chrome chokes on rendering them. // Revert to Arial when this happens, which on OSX works at least. diff --git a/skins/base/views/molecules/ServerConfig.js b/src/skins/vector/views/molecules/ServerConfig.js similarity index 88% rename from skins/base/views/molecules/ServerConfig.js rename to src/skins/vector/views/molecules/ServerConfig.js index 56241a2aa..e48487aee 100644 --- a/skins/base/views/molecules/ServerConfig.js +++ b/src/skins/vector/views/molecules/ServerConfig.js @@ -17,18 +17,17 @@ limitations under the License. 'use strict'; var React = require('react'); -var Modal = require('../../../../src/Modal'); -var ComponentBroker = require('../../../../src/ComponentBroker'); +var Modal = require('matrix-react-sdk/lib/Modal'); +var sdk = require('matrix-react-sdk') -var ErrorDialog = ComponentBroker.get('organisms/ErrorDialog'); - -var ServerConfigController = require("../../../../src/controllers/molecules/ServerConfig"); +var ServerConfigController = require('matrix-react-sdk/lib/controllers/molecules/ServerConfig') module.exports = React.createClass({ displayName: 'ServerConfig', mixins: [ServerConfigController], showHelpPopup: function() { + var ErrorDialog = sdk.getComponent('organisms.ErrorDialog'); Modal.createDialog(ErrorDialog, { title: 'Custom Server Options', description: "You can use the custom server options to log into other Matrix servers by specifying a different Home server URL. This allows you to use Vector with an existing Matrix account on a different Home server. You can also set a cutom Identity server but this will affect people ability to find you if you use a server in a group other than tha main Matrix.org group.", diff --git a/skins/base/views/molecules/UnknownMessageTile.js b/src/skins/vector/views/molecules/UnknownMessageTile.js similarity index 89% rename from skins/base/views/molecules/UnknownMessageTile.js rename to src/skins/vector/views/molecules/UnknownMessageTile.js index b965a4a1f..d5a20c878 100644 --- a/skins/base/views/molecules/UnknownMessageTile.js +++ b/src/skins/vector/views/molecules/UnknownMessageTile.js @@ -18,7 +18,7 @@ limitations under the License. var React = require('react'); -var UnknownMessageTileController = require("../../../../src/controllers/molecules/UnknownMessageTile"); +var UnknownMessageTileController = require('matrix-react-sdk/lib/controllers/molecules/UnknownMessageTile') module.exports = React.createClass({ displayName: 'UnknownMessageTile', diff --git a/skins/base/views/molecules/UserSelector.js b/src/skins/vector/views/molecules/UserSelector.js similarity index 94% rename from skins/base/views/molecules/UserSelector.js rename to src/skins/vector/views/molecules/UserSelector.js index 8ec008667..6b2336901 100644 --- a/skins/base/views/molecules/UserSelector.js +++ b/src/skins/vector/views/molecules/UserSelector.js @@ -18,7 +18,7 @@ limitations under the License. var React = require('react'); -var UserSelectorController = require("../../../../src/controllers/molecules/UserSelector"); +var UserSelectorController = require('matrix-react-sdk/lib/controllers/molecules/UserSelector') module.exports = React.createClass({ displayName: 'UserSelector', diff --git a/skins/base/views/molecules/voip/CallView.js b/src/skins/vector/views/molecules/voip/CallView.js similarity index 77% rename from skins/base/views/molecules/voip/CallView.js rename to src/skins/vector/views/molecules/voip/CallView.js index 3642e6b58..07987bd37 100644 --- a/skins/base/views/molecules/voip/CallView.js +++ b/src/skins/vector/views/molecules/voip/CallView.js @@ -18,12 +18,10 @@ limitations under the License. var React = require('react'); -var MatrixClientPeg = require("../../../../../src/MatrixClientPeg"); -var ComponentBroker = require('../../../../../src/ComponentBroker'); +var sdk = require('matrix-react-sdk') var CallViewController = require( - "../../../../../src/controllers/molecules/voip/CallView" + "../../../../../controllers/molecules/voip/CallView" ); -var VideoView = ComponentBroker.get('molecules/voip/VideoView'); module.exports = React.createClass({ displayName: 'CallView', @@ -34,8 +32,9 @@ module.exports = React.createClass({ }, render: function(){ + var VideoView = sdk.getComponent('molecules.voip.VideoView'); return ( ); } -}); \ No newline at end of file +}); diff --git a/skins/base/views/molecules/voip/IncomingCallBox.js b/src/skins/vector/views/molecules/voip/IncomingCallBox.js similarity index 94% rename from skins/base/views/molecules/voip/IncomingCallBox.js rename to src/skins/vector/views/molecules/voip/IncomingCallBox.js index 5becedb19..ee437f0a6 100644 --- a/skins/base/views/molecules/voip/IncomingCallBox.js +++ b/src/skins/vector/views/molecules/voip/IncomingCallBox.js @@ -17,9 +17,9 @@ limitations under the License. 'use strict'; var React = require('react'); -var MatrixClientPeg = require("../../../../../src/MatrixClientPeg"); +var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); var IncomingCallBoxController = require( - "../../../../../src/controllers/molecules/voip/IncomingCallBox" + "matrix-react-sdk/lib/controllers/molecules/voip/IncomingCallBox" ); module.exports = React.createClass({ diff --git a/skins/base/views/molecules/voip/VideoView.js b/src/skins/vector/views/molecules/voip/VideoView.js similarity index 81% rename from skins/base/views/molecules/voip/VideoView.js rename to src/skins/vector/views/molecules/voip/VideoView.js index 19ad17a7a..80160b78c 100644 --- a/skins/base/views/molecules/voip/VideoView.js +++ b/src/skins/vector/views/molecules/voip/VideoView.js @@ -18,10 +18,8 @@ limitations under the License. var React = require('react'); -var MatrixClientPeg = require("../../../../../src/MatrixClientPeg"); -var ComponentBroker = require('../../../../../src/ComponentBroker'); -var VideoViewController = require("../../../../../src/controllers/molecules/voip/VideoView"); -var VideoFeed = ComponentBroker.get('atoms/voip/VideoFeed'); +var sdk = require('matrix-react-sdk') +var VideoViewController = require('matrix-react-sdk/lib/controllers/molecules/voip/VideoView') module.exports = React.createClass({ displayName: 'VideoView', @@ -36,6 +34,7 @@ module.exports = React.createClass({ }, render: function() { + var VideoFeed = sdk.getComponent('atoms.voip.VideoFeed'); return (
    @@ -47,4 +46,4 @@ module.exports = React.createClass({
    ); } -}); \ No newline at end of file +}); diff --git a/skins/base/views/organisms/CreateRoom.js b/src/skins/vector/views/organisms/CreateRoom.js similarity index 89% rename from skins/base/views/organisms/CreateRoom.js rename to src/skins/vector/views/organisms/CreateRoom.js index b362db789..64f5b861b 100644 --- a/skins/base/views/organisms/CreateRoom.js +++ b/src/skins/vector/views/organisms/CreateRoom.js @@ -18,17 +18,11 @@ limitations under the License. var React = require('react'); -var CreateRoomController = require("../../../../src/controllers/organisms/CreateRoom"); +var CreateRoomController = require('matrix-react-sdk/lib/controllers/organisms/CreateRoom') -var ComponentBroker = require('../../../../src/ComponentBroker'); +var sdk = require('matrix-react-sdk') -var PresetValues = require('../../../../src/controllers/atoms/create_room/Presets').Presets; - -var CreateRoomButton = ComponentBroker.get("atoms/create_room/CreateRoomButton"); -var RoomAlias = ComponentBroker.get("atoms/create_room/RoomAlias"); -var Presets = ComponentBroker.get("atoms/create_room/Presets"); -var UserSelector = ComponentBroker.get("molecules/UserSelector"); -var RoomHeader = ComponentBroker.get("molecules/RoomHeader"); +var PresetValues = require('matrix-react-sdk/lib/controllers/atoms/create_room/Presets').Presets; var Loader = require("react-loader"); @@ -140,6 +134,13 @@ module.exports = React.createClass({
    ); } + + var CreateRoomButton = sdk.getComponent("atoms.create_room.CreateRoomButton"); + var RoomAlias = sdk.getComponent("atoms.create_room.RoomAlias"); + var Presets = sdk.getComponent("atoms.create_room.Presets"); + var UserSelector = sdk.getComponent("molecules.UserSelector"); + var RoomHeader = sdk.getComponent("molecules.RoomHeader"); + return (
    diff --git a/skins/base/views/organisms/ErrorDialog.js b/src/skins/vector/views/organisms/ErrorDialog.js similarity index 94% rename from skins/base/views/organisms/ErrorDialog.js rename to src/skins/vector/views/organisms/ErrorDialog.js index 68d597cbb..992ea0505 100644 --- a/skins/base/views/organisms/ErrorDialog.js +++ b/src/skins/vector/views/organisms/ErrorDialog.js @@ -28,7 +28,7 @@ limitations under the License. */ var React = require('react'); -var ErrorDialogController = require("../../../../src/controllers/organisms/ErrorDialog"); +var ErrorDialogController = require('matrix-react-sdk/lib/controllers/organisms/ErrorDialog') module.exports = React.createClass({ displayName: 'ErrorDialog', diff --git a/skins/base/views/organisms/LeftPanel.js b/src/skins/vector/views/organisms/LeftPanel.js similarity index 76% rename from skins/base/views/organisms/LeftPanel.js rename to src/skins/vector/views/organisms/LeftPanel.js index a7c2a8b91..15612704a 100644 --- a/skins/base/views/organisms/LeftPanel.js +++ b/src/skins/vector/views/organisms/LeftPanel.js @@ -17,17 +17,16 @@ limitations under the License. 'use strict'; var React = require('react'); -var ComponentBroker = require('../../../../src/ComponentBroker'); - -var RoomList = ComponentBroker.get('organisms/RoomList'); -var BottomLeftMenu = ComponentBroker.get('molecules/BottomLeftMenu'); -var IncomingCallBox = ComponentBroker.get('molecules/voip/IncomingCallBox'); -var RoomCreate = ComponentBroker.get('molecules/RoomCreate'); +var sdk = require('matrix-react-sdk') module.exports = React.createClass({ displayName: 'LeftPanel', render: function() { + var RoomList = sdk.getComponent('organisms.RoomList'); + var BottomLeftMenu = sdk.getComponent('molecules.BottomLeftMenu'); + var IncomingCallBox = sdk.getComponent('molecules.voip.IncomingCallBox'); + return (