mirror of
https://github.com/SchildiChat/element-web.git
synced 2024-10-01 01:26:12 -04:00
Remove controllers that all come from react-sdk
This commit is contained in:
parent
2f0df6d37e
commit
09b81f46b0
20
package.json
20
package.json
@ -8,18 +8,16 @@
|
|||||||
"url": "https://github.com/vector-im/vector-web"
|
"url": "https://github.com/vector-im/vector-web"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "src/index.js",
|
|
||||||
"style": "bundle.css",
|
"style": "bundle.css",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:skins": "jsx skins build/skins",
|
"reskindex": "reskindex base -h src/skins/base/header",
|
||||||
"build:logic": "jsx src build/src",
|
"build": "NODE_ENV=production browserify --ignore olm -t reactify src/index.js | uglifyjs -c -m -o vector/bundle.js",
|
||||||
"build:js": "npm run build:skins && npm run build:logic",
|
"start": "parallelshell 'watchify --ignore olm -v -d -t reactify src/index.js -o vector/bundle.js' 'npm run start:skins:css' 'http-server vector'",
|
||||||
"start:js": "jsx -w skins/base/views/ build --source-map-inline",
|
"build:skins:js": "babel src/skins -d lib/skins --source-maps",
|
||||||
"build:css": "catw 'skins/base/css/**/*.css' -o bundle.css -c uglifycss --no-watch",
|
"build:skins:css": "catw 'src/skins/base/css/**/*.css' -o vector/bundle.css -c uglifycss --no-watch",
|
||||||
"start:css": "catw 'skins/base/css/**/*.css' -o bundle.css -v",
|
"start:skins:css": "catw 'src/skins/base/css/**/*.css' -o vector/bundle.css",
|
||||||
"build": "npm run build:js && npm run build:css",
|
"clean": "rimraf lib vector/bundle.css vector/bundle.js",
|
||||||
"start": "parallelshell \"npm run start:js\" \"npm run start:css\"",
|
"prepublish": "npm run build:skins"
|
||||||
"prepublish": "npm run build"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"matrix-react-sdk": "^0.0.1",
|
"matrix-react-sdk": "^0.0.1",
|
||||||
@ -32,9 +30,11 @@
|
|||||||
"linkifyjs": "^2.0.0-beta.4"
|
"linkifyjs": "^2.0.0-beta.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"babel": "^5.8.23",
|
||||||
"catw": "^1.0.1",
|
"catw": "^1.0.1",
|
||||||
"parallelshell": "^1.2.0",
|
"parallelshell": "^1.2.0",
|
||||||
"react-tools": "^0.13.3",
|
"react-tools": "^0.13.3",
|
||||||
|
"rimraf": "^2.4.3",
|
||||||
"uglifycss": "0.0.15"
|
"uglifycss": "0.0.15"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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');
|
|
||||||
}
|
|
@ -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
|
|
||||||
};
|
|
@ -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!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
62
src/Modal.js
62
src/Modal.js
@ -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 = (
|
|
||||||
<div className="mx_Dialog_wrapper">
|
|
||||||
<div className="mx_Dialog">
|
|
||||||
<Element {...props} onFinished={closeDialog}/>
|
|
||||||
</div>
|
|
||||||
<div className="mx_Dialog_background" onClick={closeDialog}></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
React.render(dialog, this.getOrCreateContainer());
|
|
||||||
|
|
||||||
return {close: closeDialog};
|
|
||||||
},
|
|
||||||
};
|
|
107
src/Presence.js
107
src/Presence.js
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
@ -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
|
|
||||||
};
|
|
@ -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 <display_name>");
|
|
||||||
},
|
|
||||||
|
|
||||||
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 <on/off>");
|
|
||||||
},
|
|
||||||
|
|
||||||
// Change the room topic
|
|
||||||
topic: function(room_id, args) {
|
|
||||||
if (args) {
|
|
||||||
return success(
|
|
||||||
MatrixClientPeg.get().setRoomTopic(room_id, args)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return reject("Usage: /topic <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 <userId>");
|
|
||||||
},
|
|
||||||
|
|
||||||
// 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 <room_alias>");
|
|
||||||
},
|
|
||||||
|
|
||||||
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 <userId> [<reason>]");
|
|
||||||
},
|
|
||||||
|
|
||||||
// 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 <userId> [<reason>]");
|
|
||||||
},
|
|
||||||
|
|
||||||
// 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 <userId>");
|
|
||||||
},
|
|
||||||
|
|
||||||
// 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 <userId> [<power level>]");
|
|
||||||
},
|
|
||||||
|
|
||||||
// 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 <userId>");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
};
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
},
|
|
||||||
};
|
|
@ -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();
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2015 OpenMarket Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
};
|
|
@ -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'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
@ -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
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
@ -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 = {
|
|
||||||
};
|
|
||||||
|
|
@ -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)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
@ -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();
|
|
||||||
},
|
|
||||||
};
|
|
@ -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() {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
@ -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;
|
|
||||||
},
|
|
||||||
};
|
|
@ -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 = {
|
|
||||||
};
|
|
||||||
|
|
@ -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);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
@ -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()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
@ -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 = {
|
|
||||||
};
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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 = {
|
|
||||||
};
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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 = {
|
|
||||||
};
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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()
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -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<sortedMembers.length; i++) {
|
|
||||||
var member = sortedMembers[i];
|
|
||||||
if (member.name && searchIndex < targetIndex) {
|
|
||||||
if (member.name.toLowerCase().indexOf(search[1].toLowerCase()) === 0) {
|
|
||||||
expansion = member.name;
|
|
||||||
searchIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchIndex < targetIndex) { // then search raw mxids
|
|
||||||
for (var i=0; i<sortedMembers.length; i++) {
|
|
||||||
if (searchIndex >= 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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
|
|
||||||
},
|
|
||||||
};
|
|
@ -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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
@ -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
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
@ -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 = {
|
|
||||||
};
|
|
||||||
|
|
@ -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;
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2015 OpenMarket Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
};
|
|
@ -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;
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
};
|
|
@ -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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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 = {
|
|
||||||
};
|
|
||||||
|
|
@ -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(),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -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,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2015 OpenMarket Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var React = require("react");
|
|
||||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
|
||||||
var Modal = require("../../Modal");
|
|
||||||
var ComponentBroker = require('../../ComponentBroker');
|
|
||||||
var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog");
|
|
||||||
|
|
||||||
var INITIAL_LOAD_NUM_MEMBERS = 50;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getInitialState: function() {
|
|
||||||
var members = this.roomMembers(INITIAL_LOAD_NUM_MEMBERS);
|
|
||||||
return {
|
|
||||||
memberDict: members
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillMount: function() {
|
|
||||||
var cli = MatrixClientPeg.get();
|
|
||||||
cli.on("RoomState.members", this.onRoomStateMember);
|
|
||||||
cli.on("Room", this.onRoom); // invites
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
if (MatrixClientPeg.get()) {
|
|
||||||
MatrixClientPeg.get().removeListener("Room", this.onRoom);
|
|
||||||
MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember);
|
|
||||||
MatrixClientPeg.get().removeListener("User.presence", this.userPresenceFn);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
componentDidMount: function() {
|
|
||||||
var self = this;
|
|
||||||
setTimeout(function() {
|
|
||||||
if (!self.isMounted()) return;
|
|
||||||
self.setState({
|
|
||||||
memberDict: self.roomMembers()
|
|
||||||
});
|
|
||||||
}, 50);
|
|
||||||
|
|
||||||
// Attach a SINGLE listener for global presence changes then locate the
|
|
||||||
// member tile and re-render it. This is more efficient than every tile
|
|
||||||
// evar attaching their own listener.
|
|
||||||
function updateUserState(event, user) {
|
|
||||||
var tile = self.refs[user.userId];
|
|
||||||
if (tile) {
|
|
||||||
// update the whole list to get the order right, not just this cell...
|
|
||||||
self.forceUpdate();
|
|
||||||
// tile.forceUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MatrixClientPeg.get().on("User.presence", updateUserState);
|
|
||||||
this.userPresenceFn = updateUserState;
|
|
||||||
},
|
|
||||||
// Remember to set 'key' on a MemberList to the ID of the room it's for
|
|
||||||
/*componentWillReceiveProps: function(newProps) {
|
|
||||||
},*/
|
|
||||||
|
|
||||||
onRoom: function(room) {
|
|
||||||
if (room.roomId !== this.props.roomId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// We listen for room events because when we accept an invite
|
|
||||||
// we need to wait till the room is fully populated with state
|
|
||||||
// before refreshing the member list else we get a stale list.
|
|
||||||
this._updateList();
|
|
||||||
},
|
|
||||||
|
|
||||||
onRoomStateMember: function(ev, state, member) {
|
|
||||||
this._updateList();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateList: function() {
|
|
||||||
var members = this.roomMembers();
|
|
||||||
this.setState({
|
|
||||||
memberDict: members
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onInvite: function(inputText) {
|
|
||||||
var self = this;
|
|
||||||
// sanity check the input
|
|
||||||
inputText = inputText.trim(); // react requires es5-shim so we know trim() exists
|
|
||||||
if (inputText[0] !== '@' || inputText.indexOf(":") === -1) {
|
|
||||||
console.error("Bad user ID to invite: %s", inputText);
|
|
||||||
Modal.createDialog(ErrorDialog, {
|
|
||||||
title: "Invite Error",
|
|
||||||
description: "Malformed user ID. Should look like '@localpart:domain'"
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.setState({
|
|
||||||
inviting: true
|
|
||||||
});
|
|
||||||
console.log("Invite %s to %s", inputText, this.props.roomId);
|
|
||||||
MatrixClientPeg.get().invite(this.props.roomId, inputText).done(
|
|
||||||
function(res) {
|
|
||||||
console.log("Invited");
|
|
||||||
self.setState({
|
|
||||||
inviting: false
|
|
||||||
});
|
|
||||||
}, function(err) {
|
|
||||||
console.error("Failed to invite: %s", JSON.stringify(err));
|
|
||||||
Modal.createDialog(ErrorDialog, {
|
|
||||||
title: "Server error whilst inviting",
|
|
||||||
description: err.message
|
|
||||||
});
|
|
||||||
self.setState({
|
|
||||||
inviting: false
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
roomMembers: function(limit) {
|
|
||||||
if (!this.props.roomId) return {};
|
|
||||||
var cli = MatrixClientPeg.get();
|
|
||||||
var room = cli.getRoom(this.props.roomId);
|
|
||||||
if (!room) return {};
|
|
||||||
var all_members = room.currentState.members;
|
|
||||||
var all_user_ids = Object.keys(all_members);
|
|
||||||
|
|
||||||
all_user_ids.sort(function(userIdA, userIdB) {
|
|
||||||
var userA = all_members[userIdA].user;
|
|
||||||
var userB = all_members[userIdB].user;
|
|
||||||
|
|
||||||
var latA = userA ? userA.lastActiveAgo || Number.MAX_VALUE : Number.MAX_VALUE;
|
|
||||||
var latB = userB ? userB.lastActiveAgo || Number.MAX_VALUE : Number.MAX_VALUE;
|
|
||||||
|
|
||||||
return latA - latB;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var to_display = {};
|
|
||||||
var count = 0;
|
|
||||||
for (var i = 0; i < all_user_ids.length && (limit === undefined || count < limit); ++i) {
|
|
||||||
var user_id = all_user_ids[i];
|
|
||||||
var m = all_members[user_id];
|
|
||||||
|
|
||||||
if (m.membership == 'join' || m.membership == 'invite') {
|
|
||||||
to_display[user_id] = m;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return to_display;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -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,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,170 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2015 OpenMarket Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var React = require("react");
|
|
||||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
|
||||||
var RoomListSorter = require("../../RoomListSorter");
|
|
||||||
var dis = require("../../dispatcher");
|
|
||||||
|
|
||||||
var ComponentBroker = require('../../ComponentBroker');
|
|
||||||
var ConferenceHandler = require("../../ConferenceHandler");
|
|
||||||
var CallHandler = require("../../CallHandler");
|
|
||||||
|
|
||||||
var RoomTile = ComponentBroker.get("molecules/RoomTile");
|
|
||||||
|
|
||||||
var HIDE_CONFERENCE_CHANS = true;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
componentWillMount: function() {
|
|
||||||
var cli = MatrixClientPeg.get();
|
|
||||||
cli.on("Room", this.onRoom);
|
|
||||||
cli.on("Room.timeline", this.onRoomTimeline);
|
|
||||||
cli.on("Room.name", this.onRoomName);
|
|
||||||
|
|
||||||
var rooms = this.getRoomList();
|
|
||||||
this.setState({
|
|
||||||
roomList: rooms,
|
|
||||||
activityMap: {}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
componentDidMount: function() {
|
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
|
||||||
},
|
|
||||||
|
|
||||||
onAction: function(payload) {
|
|
||||||
switch (payload.action) {
|
|
||||||
// listen for call state changes to prod the render method, which
|
|
||||||
// may hide the global CallView if the call it is tracking is dead
|
|
||||||
case 'call_state':
|
|
||||||
this._recheckCallElement(this.props.selectedRoom);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
dis.unregister(this.dispatcherRef);
|
|
||||||
if (MatrixClientPeg.get()) {
|
|
||||||
MatrixClientPeg.get().removeListener("Room", this.onRoom);
|
|
||||||
MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline);
|
|
||||||
MatrixClientPeg.get().removeListener("Room.name", this.onRoomName);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillReceiveProps: function(newProps) {
|
|
||||||
this.state.activityMap[newProps.selectedRoom] = undefined;
|
|
||||||
this._recheckCallElement(newProps.selectedRoom);
|
|
||||||
this.setState({
|
|
||||||
activityMap: this.state.activityMap
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onRoom: function(room) {
|
|
||||||
this.refreshRoomList();
|
|
||||||
},
|
|
||||||
|
|
||||||
onRoomTimeline: function(ev, room, toStartOfTimeline) {
|
|
||||||
if (toStartOfTimeline) return;
|
|
||||||
|
|
||||||
var newState = {
|
|
||||||
roomList: this.getRoomList()
|
|
||||||
};
|
|
||||||
if (
|
|
||||||
room.roomId != this.props.selectedRoom &&
|
|
||||||
ev.getSender() != MatrixClientPeg.get().credentials.userId)
|
|
||||||
{
|
|
||||||
var hl = 1;
|
|
||||||
|
|
||||||
var actions = MatrixClientPeg.get().getPushActionsForEvent(ev);
|
|
||||||
if (actions && actions.tweaks && actions.tweaks.highlight) {
|
|
||||||
hl = 2;
|
|
||||||
}
|
|
||||||
// obviously this won't deep copy but this shouldn't be necessary
|
|
||||||
var amap = this.state.activityMap;
|
|
||||||
amap[room.roomId] = Math.max(amap[room.roomId] || 0, hl);
|
|
||||||
|
|
||||||
newState.activityMap = amap;
|
|
||||||
}
|
|
||||||
this.setState(newState);
|
|
||||||
},
|
|
||||||
|
|
||||||
onRoomName: function(room) {
|
|
||||||
this.refreshRoomList();
|
|
||||||
},
|
|
||||||
|
|
||||||
refreshRoomList: function() {
|
|
||||||
var rooms = this.getRoomList();
|
|
||||||
this.setState({
|
|
||||||
roomList: rooms
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
getRoomList: function() {
|
|
||||||
return RoomListSorter.mostRecentActivityFirst(
|
|
||||||
MatrixClientPeg.get().getRooms().filter(function(room) {
|
|
||||||
var me = room.getMember(MatrixClientPeg.get().credentials.userId);
|
|
||||||
var shouldShowRoom = (
|
|
||||||
me && (me.membership == "join" || me.membership == "invite")
|
|
||||||
);
|
|
||||||
// hiding conf rooms only ever toggles shouldShowRoom to false
|
|
||||||
if (shouldShowRoom && HIDE_CONFERENCE_CHANS) {
|
|
||||||
// we want to hide the 1:1 conf<->user room and not the group chat
|
|
||||||
var joinedMembers = room.getJoinedMembers();
|
|
||||||
if (joinedMembers.length === 2) {
|
|
||||||
var otherMember = joinedMembers.filter(function(m) {
|
|
||||||
return m.userId !== me.userId
|
|
||||||
})[0];
|
|
||||||
if (ConferenceHandler.isConferenceUser(otherMember)) {
|
|
||||||
// console.log("Hiding conference 1:1 room %s", room.roomId);
|
|
||||||
shouldShowRoom = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return shouldShowRoom;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
_recheckCallElement: function(selectedRoomId) {
|
|
||||||
// if we aren't viewing a room with an ongoing call, but there is an
|
|
||||||
// active call, show the call element - we need to do this to make
|
|
||||||
// audio/video not crap out
|
|
||||||
var activeCall = CallHandler.getAnyActiveCall();
|
|
||||||
var callForRoom = CallHandler.getCallForRoom(selectedRoomId);
|
|
||||||
var showCall = (activeCall && !callForRoom);
|
|
||||||
this.setState({
|
|
||||||
show_call_element: showCall
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
makeRoomTiles: function() {
|
|
||||||
var self = this;
|
|
||||||
return this.state.roomList.map(function(room) {
|
|
||||||
var selected = room.roomId == self.props.selectedRoom;
|
|
||||||
return (
|
|
||||||
<RoomTile
|
|
||||||
room={room}
|
|
||||||
key={room.roomId}
|
|
||||||
selected={selected}
|
|
||||||
unread={self.state.activityMap[room.roomId] === 1}
|
|
||||||
highlight={self.state.activityMap[room.roomId] === 2}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -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 = <DateSeparator key={ts1} ts={ts1}/>;
|
|
||||||
continuation = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!TileType) continue;
|
|
||||||
ret.unshift(
|
|
||||||
// XXX: don't wrap everything in a needless li - make the TileType a li if we must :(
|
|
||||||
<li key={mxEv.getId()}><TileType mxEvent={mxEv} continuation={continuation} last={last}/></li>
|
|
||||||
);
|
|
||||||
if (dateSeparator) {
|
|
||||||
ret.unshift(dateSeparator);
|
|
||||||
}
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
|
|
||||||
uploadNewState: function(new_name, new_topic, new_join_rule, new_history_visibility, new_power_levels) {
|
|
||||||
var old_name = this.state.room.name;
|
|
||||||
|
|
||||||
var old_topic = this.state.room.currentState.getStateEvents('m.room.topic', '');
|
|
||||||
if (old_topic) {
|
|
||||||
old_topic = old_topic.getContent().topic;
|
|
||||||
} else {
|
|
||||||
old_topic = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
var old_join_rule = this.state.room.currentState.getStateEvents('m.room.join_rules', '');
|
|
||||||
if (old_join_rule) {
|
|
||||||
old_join_rule = old_join_rule.getContent().join_rule;
|
|
||||||
} else {
|
|
||||||
old_join_rule = "invite";
|
|
||||||
}
|
|
||||||
|
|
||||||
var old_history_visibility = this.state.room.currentState.getStateEvents('m.room.history_visibility', '');
|
|
||||||
if (old_history_visibility) {
|
|
||||||
old_history_visibility = old_history_visibility.getContent().history_visibility;
|
|
||||||
} else {
|
|
||||||
old_history_visibility = "shared";
|
|
||||||
}
|
|
||||||
|
|
||||||
var deferreds = [];
|
|
||||||
|
|
||||||
if (old_name != new_name && new_name != undefined && new_name) {
|
|
||||||
deferreds.push(
|
|
||||||
MatrixClientPeg.get().setRoomName(this.state.room.roomId, new_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old_topic != new_topic && new_topic != undefined) {
|
|
||||||
deferreds.push(
|
|
||||||
MatrixClientPeg.get().setRoomTopic(this.state.room.roomId, new_topic)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old_join_rule != new_join_rule && new_join_rule != undefined) {
|
|
||||||
deferreds.push(
|
|
||||||
MatrixClientPeg.get().sendStateEvent(
|
|
||||||
this.state.room.roomId, "m.room.join_rules", {
|
|
||||||
join_rule: new_join_rule,
|
|
||||||
}, ""
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old_history_visibility != new_history_visibility && new_history_visibility != undefined) {
|
|
||||||
deferreds.push(
|
|
||||||
MatrixClientPeg.get().sendStateEvent(
|
|
||||||
this.state.room.roomId, "m.room.history_visibility", {
|
|
||||||
history_visibility: new_history_visibility,
|
|
||||||
}, ""
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_power_levels) {
|
|
||||||
deferreds.push(
|
|
||||||
MatrixClientPeg.get().sendStateEvent(
|
|
||||||
this.state.room.roomId, "m.room.power_levels", new_power_levels, ""
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deferreds.length) {
|
|
||||||
var self = this;
|
|
||||||
q.all(deferreds).fail(function(err) {
|
|
||||||
Modal.createDialog(ErrorDialog, {
|
|
||||||
title: "Failed to set state",
|
|
||||||
description: err.toString()
|
|
||||||
});
|
|
||||||
}).finally(function() {
|
|
||||||
self.setState({
|
|
||||||
uploadingRoomSettings: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
editingRoomSettings: false,
|
|
||||||
uploadingRoomSettings: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -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); }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -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'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -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'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -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();
|
|
@ -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,
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
19
src/index.js
19
src/index.js
@ -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");
|
|
@ -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;
|
|
@ -1 +0,0 @@
|
|||||||
../../skins/base/fonts/
|
|
@ -1 +0,0 @@
|
|||||||
../../skins/base/img
|
|
@ -41,6 +41,6 @@
|
|||||||
</audio>
|
</audio>
|
||||||
<section id="matrixchat" style="height: 100%;"></section>
|
<section id="matrixchat" style="height: 100%;"></section>
|
||||||
<script src="bundle.js"></script>
|
<script src="bundle.js"></script>
|
||||||
<link rel="stylesheet" href="node_modules/matrix-react-sdk/bundle.css">
|
<link rel="stylesheet" href="bundle.css">
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -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\""
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user