Compare commits
481 Commits
v0.0.2
...
kegan/time
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80277583db | ||
|
|
7142ea8f1e | ||
|
|
c8f6d46c8b | ||
|
|
5d1ad4d259 | ||
|
|
006f0b00c6 | ||
|
|
fe0707535c | ||
|
|
da6c5653b1 | ||
|
|
79eda12656 | ||
|
|
c74f7c956f | ||
|
|
137439243a | ||
|
|
bb5895c157 | ||
|
|
34ad48a5d3 | ||
|
|
078134d481 | ||
|
|
f882ecc31b | ||
|
|
d302f3eebb | ||
|
|
bdbfc2b6e0 | ||
|
|
f256f79418 | ||
|
|
d1cda75c8b | ||
|
|
530b077a8e | ||
|
|
11aa6f8c37 | ||
|
|
e3e49daddb | ||
|
|
4b904d90f2 | ||
|
|
48924a6106 | ||
|
|
2adb8bac5c | ||
|
|
c0938f270e | ||
|
|
47c1bb35db | ||
|
|
7598be684c | ||
|
|
1dd707775a | ||
|
|
293ee1bbcb | ||
|
|
b5357d3298 | ||
|
|
c561647460 | ||
|
|
f5039ac9af | ||
|
|
353af6c647 | ||
|
|
17c81c1101 | ||
|
|
50ebce69b7 | ||
|
|
191d56673b | ||
|
|
5d962e1feb | ||
|
|
201caed773 | ||
|
|
9be98058b7 | ||
|
|
ba0ae5ba59 | ||
|
|
9a8a9a4ce4 | ||
|
|
b05f3343e2 | ||
|
|
ae506b5b1f | ||
|
|
93de2307c1 | ||
|
|
8bdb5c0745 | ||
|
|
47ed8971e3 | ||
|
|
a8d51cdf58 | ||
|
|
a05437e81f | ||
|
|
93f266a4fa | ||
|
|
aed1fe9bf1 | ||
|
|
7296cbfd5b | ||
|
|
023034ce4f | ||
|
|
c68ef38399 | ||
|
|
ccc5f30c9b | ||
|
|
c22442f6d1 | ||
|
|
fca65a8cdb | ||
|
|
807e947146 | ||
|
|
85636ccdad | ||
|
|
490e56bfbb | ||
|
|
61f951a33e | ||
|
|
53c8b9bcf7 | ||
|
|
df39c3a281 | ||
|
|
050c6cf72f | ||
|
|
2247d951d6 | ||
|
|
7b9cd7c232 | ||
|
|
c687f32f39 | ||
|
|
3845a989f6 | ||
|
|
94a6f856d1 | ||
|
|
c62d97ca04 | ||
|
|
fd6e7663cb | ||
|
|
7d540572fd | ||
|
|
c3f32b74e4 | ||
|
|
588dbf5693 | ||
|
|
91c0df4450 | ||
|
|
3ecf19df49 | ||
|
|
f778f6adf9 | ||
|
|
796f424a3f | ||
|
|
409697b35b | ||
|
|
f020f4397c | ||
|
|
5fe41e28d7 | ||
|
|
a5a6a35122 | ||
|
|
bfa4cda2c6 | ||
|
|
c21dd853f9 | ||
|
|
1901fdf889 | ||
|
|
b11abae8e8 | ||
|
|
7e72ee891a | ||
|
|
40594fc5fa | ||
|
|
dd4cfb25f8 | ||
|
|
148dbc23ed | ||
|
|
682392d02a | ||
|
|
09b81f46b0 | ||
|
|
2f0df6d37e | ||
|
|
616b4fe0f1 | ||
|
|
ef3603cd1a | ||
|
|
61c94d63e7 | ||
|
|
260e22186b | ||
|
|
048260bb1b | ||
|
|
a545007a19 | ||
|
|
56c5f6f46e | ||
|
|
81db1b2360 | ||
|
|
240d5502fe | ||
|
|
7a50166dc6 | ||
|
|
9c8b540d14 | ||
|
|
e991beb900 | ||
|
|
f1120562f3 | ||
|
|
901574b56e | ||
|
|
fe586f6a36 | ||
|
|
01d3f2f119 | ||
|
|
0aec086ebb | ||
|
|
f89fbffe89 | ||
|
|
2b65b4c2dc | ||
|
|
ce2632bbe6 | ||
|
|
370310bf82 | ||
|
|
f384aa7d9e | ||
|
|
353269370f | ||
|
|
7866979c79 | ||
|
|
5e3698de64 | ||
|
|
59986d8b72 | ||
|
|
fc892b3580 | ||
|
|
e3b02a295c | ||
|
|
77401e215e | ||
|
|
ce9fcdbbb5 | ||
|
|
980c71076e | ||
|
|
ee4da24b84 | ||
|
|
737fc74756 | ||
|
|
027ab6ee99 | ||
|
|
8214ee8fad | ||
|
|
ab068cc372 | ||
|
|
5bab440a1f | ||
|
|
ef027706b9 | ||
|
|
2351ad997c | ||
|
|
cb25740961 | ||
|
|
e3798e1b85 | ||
|
|
80c3b2c8a3 | ||
|
|
a2e7c4aa77 | ||
|
|
25a4f1fde0 | ||
|
|
6b72c992c5 | ||
|
|
cb7f1aa916 | ||
|
|
1176168960 | ||
|
|
24630f598f | ||
|
|
316a28838f | ||
|
|
960a38fe43 | ||
|
|
87feb6b076 | ||
|
|
c5e33352b0 | ||
|
|
e1efb165fd | ||
|
|
12e53f5046 | ||
|
|
4851adf3b0 | ||
|
|
9ed5ca3ccb | ||
|
|
88095d4360 | ||
|
|
7bdf612ad5 | ||
|
|
6d390ebd2f | ||
|
|
ca09758210 | ||
|
|
e5099ce3b7 | ||
|
|
a3879b507a | ||
|
|
7a8537f3dc | ||
|
|
001d1c50ef | ||
|
|
fec266f1c0 | ||
|
|
b580fba7db | ||
|
|
8bb836ad49 | ||
|
|
eb36a2b242 | ||
|
|
18be8530fe | ||
|
|
cf77a96ac5 | ||
|
|
5153954a28 | ||
|
|
bf10a03ab1 | ||
|
|
566c0437c0 | ||
|
|
2ffa450e31 | ||
|
|
8fd26509ac | ||
|
|
3fc4aee269 | ||
|
|
a20b4d2d2c | ||
|
|
be5aaeaad7 | ||
|
|
18c56a171e | ||
|
|
b44d19d305 | ||
|
|
a9fc47efd7 | ||
|
|
a45785fe1a | ||
|
|
19d350e876 | ||
|
|
7a1796870a | ||
|
|
96cedc237e | ||
|
|
6ab993f1a9 | ||
|
|
efcc2061b8 | ||
|
|
10053fa770 | ||
|
|
3519555710 | ||
|
|
0eceb737de | ||
|
|
64727cb60e | ||
|
|
711bf583ab | ||
|
|
2771907573 | ||
|
|
68d408bfff | ||
|
|
cdbbf4bfef | ||
|
|
5cffee7ce6 | ||
|
|
9d8d4e4896 | ||
|
|
259d9dc3a2 | ||
|
|
69ac0bd368 | ||
|
|
9f98c4e9f7 | ||
|
|
278a8282fe | ||
|
|
55a4f3e3a1 | ||
|
|
2d1b88e50d | ||
|
|
7017f68db7 | ||
|
|
2391c21eeb | ||
|
|
f5b9f470b2 | ||
|
|
7ac852d1fe | ||
|
|
a24d7a9bce | ||
|
|
65cf8f030c | ||
|
|
05cc604e8d | ||
|
|
dc112e718e | ||
|
|
2f9e3fcaea | ||
|
|
33f2955927 | ||
|
|
674f90f27f | ||
|
|
79c2a5abd6 | ||
|
|
02846c4fff | ||
|
|
cc9123a33d | ||
|
|
5248b0c631 | ||
|
|
e2644e3c13 | ||
|
|
ccaeb43ff3 | ||
|
|
11f5561be6 | ||
|
|
59f380d3fc | ||
|
|
d4efb37b03 | ||
|
|
0781c767ff | ||
|
|
11e1a45ed5 | ||
|
|
6f62211465 | ||
|
|
c2e92045d0 | ||
|
|
9847383ba6 | ||
|
|
772053713a | ||
|
|
7ffd684a9e | ||
|
|
51d2677525 | ||
|
|
c726257e9b | ||
|
|
fbb6775523 | ||
|
|
8b0db49b8b | ||
|
|
b8c18130da | ||
|
|
431c93fc29 | ||
|
|
0016c2ad83 | ||
|
|
ed1cb44deb | ||
|
|
b9fd174f72 | ||
|
|
d4147c1315 | ||
|
|
7e42072952 | ||
|
|
6bfc566d9a | ||
|
|
5835ea0a97 | ||
|
|
e80cf8a133 | ||
|
|
5fb6ea94b2 | ||
|
|
e1aca588b5 | ||
|
|
79e03597b3 | ||
|
|
6b44fa7642 | ||
|
|
772f987489 | ||
|
|
663646f845 | ||
|
|
f6be51bd98 | ||
|
|
538536eb88 | ||
|
|
c8f3f5841c | ||
|
|
0f8686b8cd | ||
|
|
8c25855f38 | ||
|
|
92e346a842 | ||
|
|
904754b20d | ||
|
|
2eba2280d8 | ||
|
|
67d3368e1e | ||
|
|
ceb214f192 | ||
|
|
0b3a9baa44 | ||
|
|
b2130a5295 | ||
|
|
a2f5933417 | ||
|
|
9af09de7d4 | ||
|
|
aaa96f1ac1 | ||
|
|
e03809b224 | ||
|
|
6fc910a259 | ||
|
|
959c0f0669 | ||
|
|
8dc73cb6cc | ||
|
|
2160440ff1 | ||
|
|
f036a10a7d | ||
|
|
6bb6eafdc0 | ||
|
|
e0496305aa | ||
|
|
2698405e2f | ||
|
|
c1de5e9e95 | ||
|
|
ed738b6398 | ||
|
|
e36ca10e6c | ||
|
|
71f5d1f6cb | ||
|
|
4679e005bf | ||
|
|
c5d84562ba | ||
|
|
16846c36fd | ||
|
|
2fe56fd86d | ||
|
|
89f6459915 | ||
|
|
b8e1927e82 | ||
|
|
d81260c92a | ||
|
|
76c014b9ef | ||
|
|
2454a71b38 | ||
|
|
726ee7b50b | ||
|
|
3474f08334 | ||
|
|
13f04f77dc | ||
|
|
085e07c5b1 | ||
|
|
2e2cecdd4f | ||
|
|
0e9074b0de | ||
|
|
2bec7ec981 | ||
|
|
0b1b6057d6 | ||
|
|
af190f286c | ||
|
|
3657029fc7 | ||
|
|
12c824323d | ||
|
|
fe71f69f0a | ||
|
|
e0673eee29 | ||
|
|
36b1280f0c | ||
|
|
dcecdc8260 | ||
|
|
813cf0481e | ||
|
|
0a3cddbd89 | ||
|
|
e9b2cd1364 | ||
|
|
5d59a5b297 | ||
|
|
3a7ebf73eb | ||
|
|
9d110d58e5 | ||
|
|
bcab2f231a | ||
|
|
1b6ca2b0ee | ||
|
|
eae0972820 | ||
|
|
6fe842e130 | ||
|
|
bb06484732 | ||
|
|
05d9afc040 | ||
|
|
04f17c963c | ||
|
|
0039ccf203 | ||
|
|
f2bd802bdc | ||
|
|
28022534f7 | ||
|
|
d8494ff89b | ||
|
|
715db89204 | ||
|
|
19ee75577e | ||
|
|
0baa2141fc | ||
|
|
08c16e0d7a | ||
|
|
87dd9e8bb4 | ||
|
|
46764c3614 | ||
|
|
0fa7f6cb63 | ||
|
|
29b4f59982 | ||
|
|
a477c8be4c | ||
|
|
b82d932a51 | ||
|
|
2121ddc295 | ||
|
|
6eaba4ff04 | ||
|
|
337e6b329f | ||
|
|
caa7f813eb | ||
|
|
e8b944c0e1 | ||
|
|
e1f3c80f19 | ||
|
|
73c8eb7738 | ||
|
|
5aa913f201 | ||
|
|
85748c09cf | ||
|
|
58907e5842 | ||
|
|
202c155788 | ||
|
|
2d25414b57 | ||
|
|
d239070adb | ||
|
|
1e1f7492d8 | ||
|
|
919e1cf84f | ||
|
|
981bcbe74f | ||
|
|
27d19f2ec8 | ||
|
|
ea8737d957 | ||
|
|
c83ff1c623 | ||
|
|
db94a93fde | ||
|
|
fc5f9bb70c | ||
|
|
5b83974edd | ||
|
|
5a12a4a1a3 | ||
|
|
aa4f9abd5c | ||
|
|
97981058f0 | ||
|
|
00d2d82a14 | ||
|
|
4ded74765a | ||
|
|
b685e784f1 | ||
|
|
10cdf46c2c | ||
|
|
0d34728190 | ||
|
|
15edb9a80b | ||
|
|
706abe654a | ||
|
|
d4541f54a3 | ||
|
|
348aa3e5e1 | ||
|
|
6280adc6e7 | ||
|
|
6394978326 | ||
|
|
d09ddc48e0 | ||
|
|
48063608c7 | ||
|
|
aa70dd7b67 | ||
|
|
5f367f7c75 | ||
|
|
5c7bef3107 | ||
|
|
b60a3b61bb | ||
|
|
ddb426095e | ||
|
|
214ef4b4ce | ||
|
|
88167358bb | ||
|
|
7bef6245f7 | ||
|
|
812eb66ed5 | ||
|
|
827e777079 | ||
|
|
ff567faeaa | ||
|
|
782234de6d | ||
|
|
328d5004d8 | ||
|
|
a730804943 | ||
|
|
1df8e65cdf | ||
|
|
383a958abe | ||
|
|
9a79539978 | ||
|
|
5c6b8a4cf9 | ||
|
|
b6f9ca0f95 | ||
|
|
6a76d8ace8 | ||
|
|
8fe6411539 | ||
|
|
b53640f892 | ||
|
|
70fce0989b | ||
|
|
00c45e48a9 | ||
|
|
37108ac56c | ||
|
|
1b03aa8119 | ||
|
|
2bb2295499 | ||
|
|
001372ec39 | ||
|
|
006907e52f | ||
|
|
c8caf34777 | ||
|
|
891ba40114 | ||
|
|
1a95148dae | ||
|
|
a2ca5f2847 | ||
|
|
28dcfb2f12 | ||
|
|
0f39ec580f | ||
|
|
8ccce4d702 | ||
|
|
d08c47a328 | ||
|
|
cfbef0177e | ||
|
|
8feeb93215 | ||
|
|
1126769686 | ||
|
|
789e70f2d6 | ||
|
|
df999fb2f8 | ||
|
|
d4a98b3850 | ||
|
|
ce3dab3c5b | ||
|
|
91943d8a45 | ||
|
|
9aa66c1d8b | ||
|
|
03733e6a0f | ||
|
|
59ca26ee93 | ||
|
|
98160c3947 | ||
|
|
68d60aadd1 | ||
|
|
aa1b763518 | ||
|
|
75f8363be0 | ||
|
|
3a6423dd0a | ||
|
|
6b81022e28 | ||
|
|
47f4c0dfff | ||
|
|
ebedf0b907 | ||
|
|
95968bf619 | ||
|
|
50edc619af | ||
|
|
ebe6072225 | ||
|
|
cd26d1323f | ||
|
|
155dd74a6f | ||
|
|
b043889169 | ||
|
|
1677a3bf3a | ||
|
|
dac94d2293 | ||
|
|
41bab56133 | ||
|
|
42c9766203 | ||
|
|
6fbb7d7da4 | ||
|
|
cf38b8a5bb | ||
|
|
c708976635 | ||
|
|
0a3a3dac1a | ||
|
|
c4379e4827 | ||
|
|
41f659db4c | ||
|
|
a6f857e9d8 | ||
|
|
5f3721f471 | ||
|
|
c056bdf104 | ||
|
|
50f9d34211 | ||
|
|
eedd437ca7 | ||
|
|
7ffd97b5dc | ||
|
|
73a1c2b581 | ||
|
|
5d9db52b32 | ||
|
|
f17a9b14c2 | ||
|
|
3555f35737 | ||
|
|
ca593b8544 | ||
|
|
5d99abf18c | ||
|
|
139b92fcd6 | ||
|
|
ecd1f09095 | ||
|
|
02045858f7 | ||
|
|
edc3302d89 | ||
|
|
bc93aeb50e | ||
|
|
1b4358624f | ||
|
|
4f132c418f | ||
|
|
14a4da54f8 | ||
|
|
37c9c8fbb4 | ||
|
|
6316f1b195 | ||
|
|
2b81f46030 | ||
|
|
dfd54f3b95 | ||
|
|
7e30c0f47b | ||
|
|
28cebab9a3 | ||
|
|
7cbb43fddb | ||
|
|
78bea916e1 | ||
|
|
844a883ad8 | ||
|
|
f94a061fda | ||
|
|
aba103b8e0 | ||
|
|
2fc08aeb12 | ||
|
|
c69606df44 | ||
|
|
8db6c17220 | ||
|
|
b739e7be9e | ||
|
|
ce38d4ea12 | ||
|
|
9b384e52b5 | ||
|
|
c0bd574997 | ||
|
|
9a51cace34 | ||
|
|
77e76972f0 | ||
|
|
dff9353339 | ||
|
|
69d1844773 | ||
|
|
6b0167375c | ||
|
|
341fe868e4 | ||
|
|
a5d24329c2 | ||
|
|
10b3f250ec | ||
|
|
18066d848a | ||
|
|
06dfbbf821 | ||
|
|
20f1c075fc | ||
|
|
bfe0cdcfd1 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
node_modules
|
||||
build
|
||||
bundle.css
|
||||
bundle.js
|
||||
vector/bundle.*
|
||||
lib
|
||||
|
||||
9
AUTHORS.rst
Normal file
9
AUTHORS.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
Vector is written mainly by the Vector team, building upon the Matrix React
|
||||
SDK. Vector also welcomes external contributions. Third party contributors
|
||||
include:
|
||||
|
||||
* Nolan Darilek (https://github.com/ndarilek)
|
||||
Accessibility and semantic markup contributions
|
||||
|
||||
* https://github.com/neko259
|
||||
Improved scrollbar CSS
|
||||
20
CHANGES.rst
Normal file
20
CHANGES.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
Changes in vector v0.1.1 (2015-08-10)
|
||||
======================================
|
||||
|
||||
* Support logging in with an email address
|
||||
* Use the Vector identity server
|
||||
* Fix a bug where the client was not stopped properly on logout
|
||||
* Fix bugs where field values would be forgotten if login or registration failed
|
||||
* Improve URL bar navigation
|
||||
* Add explanatory help text on advanced server options
|
||||
* Fix a bug which caused execptions on malformed VoIP invitations
|
||||
* Remove superfluous scrollbars on Firefox
|
||||
* Numerous CSS fixes
|
||||
* Improved accessibility
|
||||
* Support command-click / middle click to open image in a new tab
|
||||
* Improved room directory
|
||||
* Fix display of text with many combining unicode points
|
||||
|
||||
Changes in vector v0.1.0 (2015-08-10)
|
||||
======================================
|
||||
Initial release
|
||||
4
CONTRIBUTING.rst
Normal file
4
CONTRIBUTING.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
Contributing code to Vector
|
||||
===========================
|
||||
|
||||
Vector follows the same pattern as https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst
|
||||
163
README.md
163
README.md
@@ -1,148 +1,45 @@
|
||||
matrix-react-sdk
|
||||
================
|
||||
Vector/Web
|
||||
==========
|
||||
|
||||
This is a react-based SDK for inserting a Matrix chat/voip client into a web page.
|
||||
It provides reusable and customisable UI components backed by the matrix-js-sdk.
|
||||
Vector is a Matrix web client built using the Matrix React SDK (https://github.com/matrix-org/matrix-react-sdk).
|
||||
|
||||
Getting started with the trivial example
|
||||
========================================
|
||||
Getting started
|
||||
===============
|
||||
|
||||
1. Install or update `node.js` so that your `npm` is at least at version `2.0.0`
|
||||
2. Clone the repo: `git clone https://github.com/matrix-org/matrix-react-sdk.git`
|
||||
3. Switch to the SDK directory: `cd matrix-react-sdk`
|
||||
2. Clone the repo: `git clone https://github.com/vector-im/vector-web.git`
|
||||
3. Switch to the SDK directory: `cd vector-web`
|
||||
4. Install the prerequisites: `npm install`
|
||||
5. Switch to the example directory: `cd examples/trivial`
|
||||
6. Install the example app prerequisites: `npm install`
|
||||
7. Build the example and start a server: `npm start`
|
||||
5. Start the development builder and a testing server: `npm start`
|
||||
6. Wait a few seconds for the initial build to finish.
|
||||
7. Open http://127.0.0.1:8080/ in your browser to see your newly built Vector.
|
||||
|
||||
Now open http://127.0.0.1:8080/ in your browser to see your newly built
|
||||
Matrix client.
|
||||
With `npm start`, any changes you make to the source files will cause a rebuild so
|
||||
your changes will show up when you refresh.
|
||||
|
||||
Using the example app for development
|
||||
=====================================
|
||||
For production use, run `npm run build` to build all the necessary files
|
||||
into the `vector` directory and run your own server.
|
||||
|
||||
To work on the CSS and Javascript and have the bundle files update as you
|
||||
change the source files, you'll need to do two extra things:
|
||||
Development
|
||||
===========
|
||||
You can work on any of the source files within Vector with the setup above,
|
||||
and your changes will cause an instant rebuild. If you also need to make
|
||||
changes to the react sdk, you can:
|
||||
|
||||
1. Link the react sdk package into the example:
|
||||
`cd matrix-react-sdk/examples/trivial; npm link ../../`
|
||||
2. Start a watcher for the CSS files:
|
||||
`cd matrix-react-sdk; npm run start:css`
|
||||
`npm link path/to/your/react/sdk`
|
||||
2. Start the development rebuilder in your react SDK directory:
|
||||
`npm start`
|
||||
|
||||
Note that you may need to restart the CSS builder if you add a new file. Note
|
||||
that `npm start` builds debug versions of the javascript and CSS, which are
|
||||
much larger than the production versions build by the `npm run build` commands.
|
||||
If you add or remove any components from the Vector skin, you will need to rebuild
|
||||
the skin's index by running, `npm run reskindex`.
|
||||
|
||||
IMPORTANT: If you customise components in your application (and hence require
|
||||
react from your app) you must be sure to:
|
||||
You may need to run `npm i source-map-loader` in matrix-js-sdk if you get errors
|
||||
about "Cannot resolve module 'source-map-loader'" due to shortcomings in webpack.
|
||||
|
||||
1. Make your app depend on react directly
|
||||
2. If you `npm link` matrix-react-sdk, manually remove the 'react' directory
|
||||
from matrix-react-sdk's `node_modules` folder, otherwise browserify will
|
||||
pull in both copies of react which causes the app to break.
|
||||
Deployment
|
||||
==========
|
||||
|
||||
How to customise the SDK
|
||||
========================
|
||||
Just run `npm build` and then mount the `vector` directory on your webserver to
|
||||
actually serve up the app, which is entirely static content.
|
||||
|
||||
The matrix-react-sdk provides well-defined reusable UI components which may be
|
||||
customised/replaced by the developer to build into an app. A set of consistent
|
||||
UI components (View + CSS classes) is called a 'skin' - currently the SDK
|
||||
provides a very vanilla whitelabelled 'base skin'. In future the SDK could
|
||||
provide alternative skins (probably by extending the base skin) that provide more
|
||||
specific look and feels (e.g. "IRC-style", "Skype-style") etc. However, unlike
|
||||
Wordpress themes and similar, we don't normally expect app developers to define
|
||||
reusable skins. Instead you just go and incorporate your view customisations
|
||||
into your actual app.
|
||||
|
||||
The SDK uses the 'atomic' design pattern as seen at http://patternlab.io to
|
||||
encourage a very modular and reusable architecture, making it easy to
|
||||
customise and use UI widgets independently of the rest of the SDK and your app.
|
||||
In practice this means:
|
||||
|
||||
* The UI of the app is strictly split up into a hierarchy of components.
|
||||
|
||||
* Each component has its own:
|
||||
* View object defined as a React javascript class containing embedded
|
||||
HTML expressed in React's JSX notation.
|
||||
* CSS file, which defines the styling specific to that component.
|
||||
|
||||
* Components are loosely grouped into the 5 levels outlined by atomic design:
|
||||
* atoms: fundamental building blocks (e.g. a timestamp tag)
|
||||
* molecules: "group of atoms which functions together as a unit"
|
||||
(e.g. a message in a chat timeline)
|
||||
* organisms: "groups of molecules (and atoms) which form a distinct section
|
||||
of a UI" (e.g. a view of a chat room)
|
||||
* templates: "a reusable configuration of organisms" - used to combine and
|
||||
style organisms into a well-defined global look and feel
|
||||
* pages: specific instances of templates.
|
||||
|
||||
Good separation between the components is maintained by adopting various best
|
||||
practices that anyone working with the SDK needs to be be aware of and uphold:
|
||||
|
||||
* Views are named with upper camel case (e.g. molecules/MessageTile.js)
|
||||
|
||||
* The view's CSS file MUST have the same name (e.g. molecules/MessageTile.css)
|
||||
|
||||
* Per-view CSS is optional - it could choose to inherit all its styling from
|
||||
the context of the rest of the app, although this is unusual for any but
|
||||
the simplest atoms and molecules.
|
||||
|
||||
* The view MUST *only* refer to the CSS rules defined in its own CSS file.
|
||||
'Stealing' styling information from other components (including parents)
|
||||
is not cool, as it breaks the independence of the components.
|
||||
|
||||
* CSS classes are named with an app-specific namespacing prefix to try to avoid
|
||||
CSS collisions. The base skin shipped by Matrix.org with the matrix-react-sdk
|
||||
uses the naming prefix "mx_". A company called Yoyodyne Inc might use a
|
||||
prefix like "yy_" for its app-specific classes.
|
||||
|
||||
* CSS classes use upper camel case when they describe React components - e.g.
|
||||
.mx_MessageTile is the selector for the CSS applied to a MessageTile view.
|
||||
|
||||
* CSS classes for DOM elements within a view which aren't components are named
|
||||
by appending a lower camel case identifier to the view's class name - e.g.
|
||||
.mx_MessageTile_randomDiv is how you'd name the class of an arbitrary div
|
||||
within the MessageTile view.
|
||||
|
||||
* We deliberately use vanilla CSS 3.0 to avoid adding any more magic
|
||||
dependencies into the mix than we already have. App developers are welcome
|
||||
to use whatever floats their boat however.
|
||||
|
||||
* The CSS for a component can however override the rules for child components.
|
||||
For instance, .mx_RoomList .mx_RoomTile {} would be the selector to override
|
||||
styles of RoomTiles when viewed in the context of a RoomList view.
|
||||
Overrides *must* be scoped to the View's CSS class - i.e. don't just define
|
||||
.mx_RoomTile {} in RoomList.css - only RoomTile.css is allowed to define its
|
||||
own CSS. Instead, say .mx_RoomList .mx_RoomTile {} to scope the override
|
||||
only to the context of RoomList views. N.B. overrides should be relatively
|
||||
rare as in general CSS inheritence should be enough.
|
||||
|
||||
* Components should render only within the bounding box of their outermost DOM
|
||||
element. Page-absolute positioning and negative CSS margins and similar are
|
||||
generally not cool and stop the component from being reused easily in
|
||||
different places.
|
||||
|
||||
* We don't use the atomify library itself, as React already provides most
|
||||
of the modularity requirements it brings to the table.
|
||||
|
||||
With all this in mind, here's how you go about skinning the react SDK UI
|
||||
components to embed a Matrix client into your app:
|
||||
|
||||
* Create a new NPM project. Be sure to directly depend on react, (otherwise
|
||||
you can end up with two copies of react).
|
||||
* Create an index.js file that sets up react. Add require statements for
|
||||
React, the ComponentBroker and matrix-react-sdk and a call to Render
|
||||
the root React element as in the examples.
|
||||
* Create React classes for any custom components you wish to add. These
|
||||
can be based off the files in `views` in the `matrix-react-sdk` package,
|
||||
modifying the require() statement appropriately.
|
||||
You only need to copy files you want to customise.
|
||||
* Add a ComponentBroker.set() call for each of your custom components. These
|
||||
must come *before* `require("matrix-react-sdk")`.
|
||||
* Add a way to build your project: we suggest copying the browserify calls
|
||||
from the example projects, but you could use grunt or gulp.
|
||||
* Create an index.html file pulling in your compiled index.js file, the
|
||||
CSS bundle from matrix-react-sdk.
|
||||
|
||||
For more specific detail on any of these steps, look at the `custom` example in
|
||||
matrix-react-sdk/examples.
|
||||
|
||||
4
config.json
Normal file
4
config.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"default_hs_url": "https://matrix.org",
|
||||
"default_is_url": "https://vector.im"
|
||||
}
|
||||
52
docs/conferencing.md
Normal file
52
docs/conferencing.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# VoIP Conferencing
|
||||
|
||||
This is a draft proposal for a naive voice/video conferencing implementation for
|
||||
Matrix clients. There are many possible conferencing architectures possible for
|
||||
Matrix (Multipoint Conferencing Unit (MCU); Stream Forwarding Unit (SFU); Peer-
|
||||
to-Peer mesh (P2P), etc; events shared in the group room; events shared 1:1;
|
||||
possibly even out-of-band signalling).
|
||||
|
||||
This is a starting point for a naive MCU implementation which could provide one
|
||||
possible Matrix-wide solution in future, which retains backwards compatibility
|
||||
with standard 1:1 calling.
|
||||
|
||||
* A client chooses to initiate a conference for a given room by starting a
|
||||
voice or video call with a 'conference focus' user. This is a virtual user
|
||||
(typically Application Service) which implements a conferencing bridge. It
|
||||
isn't defined how the client discovers or selects this user.
|
||||
|
||||
* The conference focus user MUST join the room in which the client has
|
||||
initiated the conference - this may require the client to invite the
|
||||
conference focus user to the room, depending on the room's `join_rules`. The
|
||||
conference focus user needs to be in the room to let the bridge eject users
|
||||
from the conference who have left the room in which it was initiated, and aid
|
||||
discovery of the conference by other users in the room. The bridge
|
||||
identifies the room to join based on the user ID by which it was invited.
|
||||
The format of this identifier is implementation dependent for now.
|
||||
|
||||
* If a client leaves the group chat room, they MUST be ejected from the
|
||||
conference. If a client leaves the 1:1 room with the conference focus user,
|
||||
they SHOULD be ejected from the conference.
|
||||
|
||||
* For now, rooms can contain multiple conference focus users - it's left to
|
||||
user or client implementation to select which to converge on. In future this
|
||||
could be mediated using a state event (e.g. `im.vector.call.mcu`), but we
|
||||
can't do that right now as by default normal users can't set arbitrary state
|
||||
events on a room.
|
||||
|
||||
* To participate in the conference, other clients initiates a standard 1:1
|
||||
voice or video call to the conference focus user.
|
||||
|
||||
* For best UX, clients SHOULD show the ongoing voice/video call in the UI
|
||||
context of the group room rather than 1:1 with the focus user. If a client
|
||||
recognises a conference user present in the room, it MAY chose to highlight
|
||||
this in the UI (e.g. with a "conference ongoing" notification, to aid
|
||||
discovery). Clients MAY hide the 1:1 room with the focus user (although in
|
||||
future this room could be used for floor control or other direct
|
||||
communication with the conference focus)
|
||||
|
||||
* When all users have left the conference, the 'conference focus' user SHOULD
|
||||
leave the room.
|
||||
|
||||
* If a conference focus user joins a room but does not receive a 1:1 voice or
|
||||
video call, it SHOULD time out after a period of time and leave the room.
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var MTextTileController = require("matrix-react-sdk/src/controllers/molecules/MTextTile");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MTextTile',
|
||||
mixins: [MTextTileController],
|
||||
|
||||
render: function() {
|
||||
var content = this.props.mxEvent.getContent();
|
||||
return (
|
||||
<span ref="content" className="mx_MTextTile mx_MessageTile_content" onClick={this.onClick}>
|
||||
{content.body}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
|
||||
onClick: function(ev) {
|
||||
global.alert(this.props.mxEvent.getContent().body);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
matrix-react-example
|
||||
====================
|
||||
|
||||
An example of how to use the Matrix React SDK to build a more customised app
|
||||
@@ -1,12 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en" style="height: 100%; overflow: hidden">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Matrix React SDK Custom Example</title>
|
||||
</head>
|
||||
<body style="height: 100%; ">
|
||||
<section id="matrixchat" style="height: 100%; "></section>
|
||||
<script src="bundle.js"></script>
|
||||
<link rel="stylesheet" href="node_modules/matrix-react-sdk/bundle.css">
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// Remember to make your project depend on react directly as soon as
|
||||
// you add a require('react') to any file in your project. Do not rely
|
||||
// on react being pulled in via matrix-react-sdk: browserify breaks
|
||||
// horribly in this situation and can end up pulling in multiple copies
|
||||
// of react.
|
||||
var React = require("react");
|
||||
|
||||
// We pull in the component broker first, separately, as we need to replace
|
||||
// components before the SDK loads.
|
||||
var ComponentBroker = require("matrix-react-sdk/src/ComponentBroker");
|
||||
|
||||
var CustomMTextTile = require('./CustomMTextTile');
|
||||
|
||||
ComponentBroker.set('molecules/MTextTile', CustomMTextTile);
|
||||
|
||||
var MatrixReactSdk = require("matrix-react-sdk");
|
||||
//var MatrixReactSdk = require("../../src/index");
|
||||
|
||||
React.render(
|
||||
<MatrixReactSdk.MatrixChat />,
|
||||
document.getElementById('matrixchat')
|
||||
);
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"name": "matrix-react-example",
|
||||
"version": "0.0.1",
|
||||
"description": "Example usage of matrix-react-sdk",
|
||||
"author": "matrix.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/matrix-org/matrix-react-sdk"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"browserify": "^10.2.3",
|
||||
"envify": "^3.4.0",
|
||||
"http-server": "^0.8.0",
|
||||
"matrix-react-sdk": "../../",
|
||||
"npm-css": "^0.2.3",
|
||||
"parallelshell": "^1.2.0",
|
||||
"reactify": "^1.1.1",
|
||||
"uglify-js": "^2.4.23",
|
||||
"watchify": "^3.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "browserify -t [ envify --NODE_ENV production ] -g reactify index.js | uglifyjs -c -m -o bundle.js",
|
||||
"start": "parallelshell 'watchify -v -d -g reactify index.js -o bundle.js' 'http-server'"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^0.13.3"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
matrix-react-example
|
||||
====================
|
||||
|
||||
A simple example of how to use the Matrix React SDK
|
||||
@@ -1,12 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en" style="height: 100%; overflow: hidden">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Matrix React SDK Example</title>
|
||||
</head>
|
||||
<body style="height: 100%;">
|
||||
<section id="matrixchat" style="height: 100%;"></section>
|
||||
<script src="bundle.js"></script>
|
||||
<link rel="stylesheet" href="node_modules/matrix-react-sdk/bundle.css">
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"name": "matrix-react-example",
|
||||
"version": "0.0.1",
|
||||
"description": "Example usage of matrix-react-sdk",
|
||||
"author": "matrix.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/matrix-org/matrix-react-sdk"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"browserify": "^10.2.3",
|
||||
"envify": "^3.4.0",
|
||||
"http-server": "^0.8.0",
|
||||
"matrix-react-sdk": "../../",
|
||||
"parallelshell": "^1.2.0",
|
||||
"reactify": "^1.1.1",
|
||||
"uglify-js": "^2.4.23",
|
||||
"watchify": "^3.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "browserify -t [ envify --NODE_ENV production ] -t reactify index.js | uglifyjs -c -m -o bundle.js",
|
||||
"start": "parallelshell 'watchify -v -d -t reactify index.js -o bundle.js' 'http-server'"
|
||||
}
|
||||
}
|
||||
46
package.json
46
package.json
@@ -1,40 +1,48 @@
|
||||
{
|
||||
"name": "matrix-react-sdk",
|
||||
"name": "vector-web",
|
||||
"version": "0.0.1",
|
||||
"description": "SDK for matrix.org using React",
|
||||
"description": "Vector webapp",
|
||||
"author": "matrix.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/matrix-org/matrix-react-sdk"
|
||||
"url": "https://github.com/vector-im/vector-web"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"main": "src/index.js",
|
||||
"style": "bundle.css",
|
||||
"scripts": {
|
||||
"build:skins": "jsx skins build/skins",
|
||||
"build:logic": "jsx src build/src",
|
||||
"build:js": "npm run build:skins && npm run build:logic",
|
||||
"start:js": "jsx -w skins/base/views/ build --source-map-inline",
|
||||
"build:css": "catw 'skins/base/css/**/*.css' -o bundle.css -c uglifycss --no-watch",
|
||||
"start:css": "catw 'skins/base/css/**/*.css' -o bundle.css -v",
|
||||
"build": "npm run build:js && npm run build:css",
|
||||
"start": "parallelshell 'npm run start:js' 'npm run start:css'",
|
||||
"prepublish": "npm run build"
|
||||
"reskindex": "reskindex vector -h src/skins/vector/header",
|
||||
"build:css": "catw \"src/skins/vector/css/**/*.css\" -o vector/bundle.css -c uglifycss --no-watch",
|
||||
"build:compile": "babel --source-maps -d lib src",
|
||||
"build:bundle": "NODE_ENV=production webpack -p lib/vector/index.js vector/bundle.js",
|
||||
"build": "npm run build:css && npm run build:compile && npm run build:bundle",
|
||||
"start:js": "webpack -w src/vector/index.js vector/bundle.js",
|
||||
"start:skins:css": "catw \"src/skins/vector/css/**/*.css\" -o vector/bundle.css",
|
||||
"//cache": "Note the -c 1 below due to https://code.google.com/p/chromium/issues/detail?id=508270",
|
||||
"start": "parallelshell \"npm run start:js\" \"npm run start:skins:css\" \"http-server -c 1 vector\"",
|
||||
"clean": "rimraf lib vector/bundle.css vector/bundle.js vector/bundle.js.map",
|
||||
"prepublish": "npm run build:css && npm run build:compile"
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.1.2",
|
||||
"filesize": "^3.1.2",
|
||||
"flux": "^2.0.3",
|
||||
"matrix-js-sdk": "0.1.1",
|
||||
"flux": "~2.0.3",
|
||||
"linkifyjs": "^2.0.0-beta.4",
|
||||
"matrix-js-sdk": "^0.2.2",
|
||||
"matrix-react-sdk": "^0.0.1",
|
||||
"q": "^1.4.1",
|
||||
"react": "^0.13.3",
|
||||
"react-loader": "^1.4.0",
|
||||
"linkifyjs": "^2.0.0-beta.4"
|
||||
"react-loader": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^5.8.23",
|
||||
"babel-core": "^5.8.25",
|
||||
"babel-loader": "^5.3.2",
|
||||
"catw": "^1.0.1",
|
||||
"parallelshell": "^1.1.1",
|
||||
"react-tools": "^0.13.3",
|
||||
"http-server": "^0.8.4",
|
||||
"json-loader": "^0.5.3",
|
||||
"parallelshell": "^1.2.0",
|
||||
"rimraf": "^2.4.3",
|
||||
"source-map-loader": "^0.1.5",
|
||||
"uglifycss": "0.0.15"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +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.
|
||||
*/
|
||||
|
||||
.mx_RoomTile {
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomTile.selected {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.mx_RoomTile_name {
|
||||
}
|
||||
|
||||
.mx_RoomTile div {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_RoomTile.unread {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mx_RoomTile.highlight {
|
||||
background-color: lime;
|
||||
}
|
||||
|
||||
.mx_RoomTile.invited {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mx_RoomTile:hover {
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var RoomNameTextboxController = require("../../../../../src/controllers/atoms/create_room/RoomNameTextbox");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomNameTextbox',
|
||||
mixins: [RoomNameTextboxController],
|
||||
|
||||
onValueChanged: function(ev) {
|
||||
this.setState({room_name: ev.target.value})
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<input type="text" className="mx_RoomNameTextbox" placeholder="ex. MyNewRoom" onChange={this.onValueChanged}/>
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -1,66 +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 classNames = require("classnames");
|
||||
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
|
||||
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');
|
||||
var SenderProfile = ComponentBroker.get('molecules/SenderProfile');
|
||||
|
||||
var UnknownMessageTile = ComponentBroker.get('molecules/UnknownMessageTile');
|
||||
|
||||
var tileTypes = {
|
||||
'm.text': ComponentBroker.get('molecules/MTextTile'),
|
||||
'm.notice': ComponentBroker.get('molecules/MNoticeTile'),
|
||||
'm.emote': ComponentBroker.get('molecules/MEmoteTile'),
|
||||
'm.image': ComponentBroker.get('molecules/MImageTile'),
|
||||
'm.file': ComponentBroker.get('molecules/MFileTile')
|
||||
};
|
||||
|
||||
var MessageTileController = require("../../../../src/controllers/molecules/MessageTile");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MessageTile',
|
||||
mixins: [MessageTileController],
|
||||
|
||||
render: function() {
|
||||
var content = this.props.mxEvent.getContent();
|
||||
var msgtype = content.msgtype;
|
||||
var TileType = UnknownMessageTile;
|
||||
if (msgtype && tileTypes[msgtype]) {
|
||||
TileType = tileTypes[msgtype];
|
||||
}
|
||||
var classes = classNames({
|
||||
mx_MessageTile: true,
|
||||
mx_MessageTile_sending: this.props.mxEvent.status == 'sending',
|
||||
mx_MessageTile_notSent: this.props.mxEvent.status == 'not_sent',
|
||||
mx_MessageTile_highlight: this.shouldHighlight()
|
||||
});
|
||||
return (
|
||||
<div className={classes}>
|
||||
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||
<SenderProfile mxEvent={this.props.mxEvent} />
|
||||
<TileType mxEvent={this.props.mxEvent} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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 React = require('react');
|
||||
var classNames = require('classnames');
|
||||
|
||||
var RoomTileController = require("../../../../src/controllers/molecules/RoomTile");
|
||||
|
||||
var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomTile',
|
||||
mixins: [RoomTileController],
|
||||
render: function() {
|
||||
var myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
var classes = classNames({
|
||||
'mx_RoomTile': true,
|
||||
'selected': this.props.selected,
|
||||
'unread': this.props.unread,
|
||||
'highlight': this.props.highlight,
|
||||
'invited': this.props.room.currentState.members[myUserId].membership == 'invite'
|
||||
});
|
||||
return (
|
||||
<div className={classes} onClick={this.onClick}>
|
||||
<div className="mx_RoomTile_name">{this.props.room.name}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var ServerConfigController = require("../../../../src/controllers/molecules/ServerConfig");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'ServerConfig',
|
||||
mixins: [ServerConfigController],
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="HomeServerTextBox">
|
||||
<table className="serverConfig">
|
||||
<tr>
|
||||
<td>Home Server URL</td>
|
||||
<td><input type="text" value={this.state.hs_url} onChange={this.hsChanged} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Identity Server URL</td>
|
||||
<td><input type="text" value={this.state.is_url} onChange={this.isChanged} /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -1,73 +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 CreateRoomController = require("../../../../src/controllers/organisms/CreateRoom");
|
||||
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
|
||||
var CreateRoomButton = ComponentBroker.get("atoms/create_room/CreateRoomButton");
|
||||
var RoomNameTextbox = ComponentBroker.get("atoms/create_room/RoomNameTextbox");
|
||||
var Presets = ComponentBroker.get("atoms/create_room/Presets");
|
||||
var UserSelector = ComponentBroker.get("molecules/UserSelector");
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'CreateRoom',
|
||||
mixins: [CreateRoomController],
|
||||
|
||||
getPreset: function() {
|
||||
return this.refs.presets.getPreset();
|
||||
},
|
||||
|
||||
getName: function() {
|
||||
return this.refs.name_textbox.getName();
|
||||
},
|
||||
|
||||
getInvitedUsers: function() {
|
||||
return this.refs.user_selector.getUserIds();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var curr_phase = this.state.phase;
|
||||
if (curr_phase == this.phases.CREATING) {
|
||||
return (
|
||||
<div>Creating...</div>
|
||||
);
|
||||
} else {
|
||||
var error_box = "";
|
||||
if (curr_phase == this.phases.ERROR) {
|
||||
error_box = (
|
||||
<div className="mx_Error">
|
||||
An error occured: {this.state.error_string}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="mx_CreateRoom">
|
||||
<label>Room Name <RoomNameTextbox ref="name_textbox" /></label>
|
||||
<Presets ref="presets"/>
|
||||
<UserSelector ref="user_selector"/>
|
||||
<CreateRoomButton onCreateRoom={this.onCreateRoom} />
|
||||
{error_box}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var MemberListController = require("../../../../src/controllers/organisms/MemberList");
|
||||
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
|
||||
var MemberTile = ComponentBroker.get("molecules/MemberTile");
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MemberList',
|
||||
mixins: [MemberListController],
|
||||
|
||||
makeMemberTiles: function() {
|
||||
var that = this;
|
||||
return Object.keys(that.state.memberDict).map(function(userId) {
|
||||
var m = that.state.memberDict[userId];
|
||||
return (
|
||||
<li key={userId}>
|
||||
<MemberTile
|
||||
member={m}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_MemberList">
|
||||
<ul>
|
||||
{this.makeMemberTiles()}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,95 +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("../../../../src/MatrixClientPeg");
|
||||
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
var classNames = require("classnames");
|
||||
|
||||
var MessageTile = ComponentBroker.get('molecules/MessageTile');
|
||||
var RoomHeader = ComponentBroker.get('molecules/RoomHeader');
|
||||
var MemberList = ComponentBroker.get('organisms/MemberList');
|
||||
var MessageComposer = ComponentBroker.get('molecules/MessageComposer');
|
||||
|
||||
var RoomViewController = require("../../../../src/controllers/organisms/RoomView");
|
||||
|
||||
var Loader = require("react-loader");
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomView',
|
||||
mixins: [RoomViewController],
|
||||
|
||||
render: function() {
|
||||
if (!this.state.room) {
|
||||
return (
|
||||
<div />
|
||||
);
|
||||
}
|
||||
|
||||
var myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
if (this.state.room.currentState.members[myUserId].membership == 'invite') {
|
||||
if (this.state.joining) {
|
||||
return (
|
||||
<div className="mx_RoomView">
|
||||
<Loader />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
var inviteEvent = this.state.room.currentState.members[myUserId].events.member.event;
|
||||
// XXX: Leaving this intentionally basic for now because invites are about to change totally
|
||||
var joinErrorText = this.state.joinError ? "Failed to join room!" : "";
|
||||
return (
|
||||
<div className="mx_RoomView">
|
||||
<div className="mx_RoomView_invitePrompt">
|
||||
<div>{inviteEvent.user_id} has invited you to a room</div>
|
||||
<button ref="joinButton" onClick={this.onJoinButtonClicked}>Join</button>
|
||||
<div className="error">{joinErrorText}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
var scrollheader_classes = classNames({
|
||||
mx_RoomView_scrollheader: true,
|
||||
loading: this.state.paginating
|
||||
});
|
||||
return (
|
||||
<div className="mx_RoomView">
|
||||
<RoomHeader room={this.state.room} />
|
||||
<div className="mx_RoomView_roomWrapper">
|
||||
<div className="mx_RoomView_messagePanel">
|
||||
<div ref="messageWrapper" className="mx_RoomView_messageListWrapper" onScroll={this.onMessageListScroll}>
|
||||
<div className="mx_RoomView_MessageList" aria-live="polite">
|
||||
<div className={scrollheader_classes}>
|
||||
</div>
|
||||
{this.getEventTiles()}
|
||||
</div>
|
||||
</div>
|
||||
<MessageComposer roomId={this.props.roomId} />
|
||||
</div>
|
||||
<MemberList roomId={this.props.roomId} key={this.props.roomId} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,70 +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 ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
|
||||
var RoomList = ComponentBroker.get('organisms/RoomList');
|
||||
var RoomView = ComponentBroker.get('organisms/RoomView');
|
||||
var MatrixToolbar = ComponentBroker.get('molecules/MatrixToolbar');
|
||||
var Login = ComponentBroker.get('templates/Login');
|
||||
var Register = ComponentBroker.get('templates/Register');
|
||||
|
||||
var MatrixChatController = require("../../../../src/controllers/pages/MatrixChat");
|
||||
|
||||
// should be atomised
|
||||
var Loader = require("react-loader");
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MatrixChat',
|
||||
mixins: [MatrixChatController],
|
||||
|
||||
render: function() {
|
||||
if (this.state.logged_in && this.state.ready) {
|
||||
return (
|
||||
<div className="mx_MatrixChat">
|
||||
<div className="mx_MatrixChat_chatWrapper">
|
||||
<div className="mx_MatrixChat_leftPanel">
|
||||
<RoomList selectedRoom={this.state.currentRoom} />
|
||||
<MatrixToolbar />
|
||||
</div>
|
||||
<RoomView roomId={this.state.currentRoom} key={this.state.currentRoom} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (this.state.logged_in) {
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
} else if (this.state.screen == 'register') {
|
||||
return (
|
||||
<Register onLoggedIn={this.onLoggedIn} clientSecret={this.state.register_client_secret}
|
||||
sessionId={this.state.register_session_id} idSid={this.state.register_id_sid}
|
||||
hsUrl={this.state.register_hs_url} isUrl={this.state.register_is_url}
|
||||
registrationUrl={this.props.registrationUrl}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Login onLoggedIn={this.onLoggedIn} />
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,102 +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 ComponentBroker = require("../../../../src/ComponentBroker");
|
||||
|
||||
var ProgressBar = ComponentBroker.get("molecules/ProgressBar");
|
||||
var Loader = require("react-loader");
|
||||
|
||||
var LoginController = require("../../../../src/controllers/templates/Login");
|
||||
|
||||
var ServerConfig = ComponentBroker.get("molecules/ServerConfig");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'Login',
|
||||
mixins: [LoginController],
|
||||
|
||||
getHsUrl: function() {
|
||||
return this.refs.serverConfig.getHsUrl();
|
||||
},
|
||||
|
||||
getIsUrl: function() {
|
||||
return this.refs.serverConfig.getIsUrl();
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the form field values for the current login stage
|
||||
*/
|
||||
getFormVals: function() {
|
||||
return {
|
||||
'username': this.refs.user.getDOMNode().value,
|
||||
'password': this.refs.pass.getDOMNode().value
|
||||
};
|
||||
},
|
||||
|
||||
componentForStep: function(step) {
|
||||
switch (step) {
|
||||
case 'choose_hs':
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={this.onHSChosen}>
|
||||
<ServerConfig ref="serverConfig" />
|
||||
<input type="submit" value="Continue" />
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
// XXX: clearly these should be separate organisms
|
||||
case 'stage_m.login.password':
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={this.onUserPassEntered}>
|
||||
<input ref="user" type="text" placeholder="username" /><br />
|
||||
<input ref="pass" type="password" placeholder="password" /><br />
|
||||
<input type="submit" value="Log in" />
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
loginContent: function() {
|
||||
if (this.state.busy) {
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<h1>Please log in:</h1>
|
||||
{this.componentForStep(this.state.step)}
|
||||
<div className="error">{this.state.errorText}</div>
|
||||
<a onClick={this.showRegister} href="#">Create a new account</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_Login">
|
||||
<ProgressBar value={this.state.currentStep} max={this.state.totalSteps} />
|
||||
{this.loginContent()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -1,131 +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 ComponentBroker = require("../../../../src/ComponentBroker");
|
||||
|
||||
var Loader = require("react-loader");
|
||||
|
||||
var RegisterController = require("../../../../src/controllers/templates/Register");
|
||||
|
||||
var ServerConfig = ComponentBroker.get("molecules/ServerConfig");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'Register',
|
||||
mixins: [RegisterController],
|
||||
|
||||
getRegFormVals: function() {
|
||||
return {
|
||||
email: this.refs.email.getDOMNode().value,
|
||||
username: this.refs.username.getDOMNode().value,
|
||||
password: this.refs.password.getDOMNode().value,
|
||||
confirmPassword: this.refs.confirmPassword.getDOMNode().value
|
||||
};
|
||||
},
|
||||
|
||||
getHsUrl: function() {
|
||||
return this.refs.serverConfig.getHsUrl();
|
||||
},
|
||||
|
||||
getIsUrl: function() {
|
||||
return this.refs.serverConfig.getIsUrl();
|
||||
},
|
||||
|
||||
componentForStep: function(step) {
|
||||
switch (step) {
|
||||
case 'initial':
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={this.onInitialStageSubmit}>
|
||||
Email: <input type="text" ref="email" defaultValue={this.savedParams.email} /><br />
|
||||
Username: <input type="text" ref="username" defaultValue={this.savedParams.username} /><br />
|
||||
Password: <input type="password" ref="password" defaultValue={this.savedParams.password} /><br />
|
||||
Confirm Password: <input type="password" ref="confirmPassword" defaultValue={this.savedParams.confirmPassword} /><br />
|
||||
<ServerConfig ref="serverConfig" />
|
||||
<input type="submit" value="Continue" />
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
// XXX: clearly these should be separate organisms
|
||||
case 'stage_m.login.email.identity':
|
||||
return (
|
||||
<div>
|
||||
Please check your email to continue registration.
|
||||
</div>
|
||||
);
|
||||
case 'stage_m.login.recaptcha':
|
||||
return (
|
||||
<div ref="recaptchaContainer">
|
||||
This Home Server would like to make sure you're not a robot
|
||||
<div id="mx_recaptcha"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
registerContent: function() {
|
||||
if (this.state.busy) {
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<h1>Create a new account:</h1>
|
||||
{this.componentForStep(this.state.step)}
|
||||
<div className="error">{this.state.errorText}</div>
|
||||
<a onClick={this.showLogin} href="#">Sign in with existing account</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
onBadFields: function(bad) {
|
||||
var keys = Object.keys(bad);
|
||||
var strings = [];
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
switch (bad[keys[i]]) {
|
||||
case this.FieldErrors.PasswordMismatch:
|
||||
strings.push("Passwords don't match");
|
||||
break;
|
||||
case this.FieldErrors.Missing:
|
||||
strings.push("Missing "+keys[i]);
|
||||
break;
|
||||
case this.FieldErrors.TooShort:
|
||||
strings.push(keys[i]+" is too short");
|
||||
break;
|
||||
case this.FieldErrors.InUse:
|
||||
strings.push(keys[i]+" is already taken");
|
||||
break;
|
||||
}
|
||||
}
|
||||
var errtxt = strings.join(', ');
|
||||
this.setState({
|
||||
errorText: errtxt
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_Register">
|
||||
{this.registerContent()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
53
src/Avatar.js
Normal file
53
src/Avatar.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
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('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
|
||||
module.exports = {
|
||||
avatarUrlForMember: function(member, width, height, resizeMethod) {
|
||||
var url = member.getAvatarUrl(
|
||||
MatrixClientPeg.get().getHomeserverUrl(),
|
||||
width,
|
||||
height,
|
||||
resizeMethod
|
||||
);
|
||||
if (!url) {
|
||||
// member can be null here currently since on invites, the JS SDK
|
||||
// does not have enough info to build a RoomMember object for
|
||||
// the inviter.
|
||||
url = this.defaultAvatarUrlForString(member ? member.userId : '');
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
defaultAvatarUrlForString: function(s) {
|
||||
var total = 0;
|
||||
for (var i = 0; i < s.length; ++i) {
|
||||
total += s.charCodeAt(i);
|
||||
}
|
||||
switch (total % 3) {
|
||||
case 0:
|
||||
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrszQENADAIACB9QjNbxSKP4eagAFnTseHFErFYLBaLxWKxWCwWi8Vi8cX4CzAABSwCRWJw31gAAAAASUVORK5CYII=";
|
||||
case 1:
|
||||
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrszQENADAIACB9chOaxgCP4eagAFk9seHFErFYLBaLxWKxWCwWi8Vi8cX4CzAAtKMCks/JG8MAAAAASUVORK5CYII=";
|
||||
case 2:
|
||||
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrszQENADAIACB9YzNayQCP4eagADldseHFErFYLBaLxWKxWCwWi8Vi8cX4CzAAyiACeHwPiu4AAAAASUVORK5CYII=";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,92 +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/RoomNameTextbox');
|
||||
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/MRoomMemberTile');
|
||||
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');
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
71
src/ContextualMenu.js
Normal file
71
src/ContextualMenu.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
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');
|
||||
|
||||
// Shamelessly ripped off Modal.js. There's probably a better way
|
||||
// of doing reusable widgets like dialog boxes & menus where we go and
|
||||
// pass in a custom control as the actual body.
|
||||
|
||||
module.exports = {
|
||||
ContextualMenuContainerId: "mx_ContextualMenu_Container",
|
||||
|
||||
getOrCreateContainer: function() {
|
||||
var container = document.getElementById(this.ContextualMenuContainerId);
|
||||
|
||||
if (!container) {
|
||||
container = document.createElement("div");
|
||||
container.id = this.ContextualMenuContainerId;
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
createMenu: function (Element, props) {
|
||||
var self = this;
|
||||
|
||||
var closeMenu = function() {
|
||||
React.unmountComponentAtNode(self.getOrCreateContainer());
|
||||
|
||||
if (props && props.onFinished) props.onFinished.apply(null, arguments);
|
||||
};
|
||||
|
||||
var position = {
|
||||
top: props.top - 20,
|
||||
right: props.right + 8,
|
||||
};
|
||||
|
||||
// FIXME: If a menu uses getDefaultProps it clobbers the onFinished
|
||||
// property set here so you can't close the menu from a button click!
|
||||
var menu = (
|
||||
<div className="mx_ContextualMenu_wrapper">
|
||||
<div className="mx_ContextualMenu" style={position}>
|
||||
<img className="mx_ContextualMenu_chevron" src="img/chevron-right.png" width="9" height="16" />
|
||||
<Element {...props} onFinished={closeMenu}/>
|
||||
</div>
|
||||
<div className="mx_ContextualMenu_background" onClick={closeMenu}></div>
|
||||
</div>
|
||||
);
|
||||
|
||||
React.render(menu, this.getOrCreateContainer());
|
||||
|
||||
return {close: closeMenu};
|
||||
},
|
||||
};
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// A thing that holds your Matrix Client
|
||||
var Matrix = require("matrix-js-sdk");
|
||||
|
||||
var matrixClient = null;
|
||||
|
||||
var localStorage = window.localStorage;
|
||||
|
||||
function createClient(hs_url, is_url, user_id, access_token) {
|
||||
var opts = {
|
||||
baseUrl: hs_url,
|
||||
idBaseUrl: is_url,
|
||||
accessToken: access_token,
|
||||
userId: user_id
|
||||
};
|
||||
|
||||
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;
|
||||
},
|
||||
|
||||
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) {
|
||||
createClient(hs_url, is_url, user_id, access_token);
|
||||
if (localStorage) {
|
||||
try {
|
||||
localStorage.clear();
|
||||
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,68 +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,
|
||||
initalValue: React.PropTypes.string,
|
||||
},
|
||||
|
||||
Phases: {
|
||||
Display: "display",
|
||||
Edit: "edit",
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
onValueChanged: function() {},
|
||||
initalValue: '',
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
value: this.props.initalValue,
|
||||
phase: this.Phases.Display,
|
||||
}
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
return this.state.value;
|
||||
},
|
||||
|
||||
setValue: function(val) {
|
||||
this.setState({
|
||||
value: val,
|
||||
phase: this.Phases.Display,
|
||||
});
|
||||
|
||||
this.onValueChanged();
|
||||
},
|
||||
|
||||
cancelEdit: function() {
|
||||
this.setState({
|
||||
phase: this.Phases.Display,
|
||||
});
|
||||
},
|
||||
|
||||
onValueChanged: function() {
|
||||
this.props.onValueChanged(this.state.value);
|
||||
},
|
||||
};
|
||||
@@ -1,67 +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 = {
|
||||
notificationsAvailable: function() {
|
||||
return !!global.Notification;
|
||||
},
|
||||
|
||||
havePermission: function() {
|
||||
return global.Notification.permission == 'granted';
|
||||
},
|
||||
|
||||
enabled: 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';
|
||||
},
|
||||
|
||||
disable: function() {
|
||||
if (!global.localStorage) return;
|
||||
global.localStorage.setItem('notifications_enabled', 'false');
|
||||
this.forceUpdate();
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
if (!this.havePermission()) {
|
||||
var that = this;
|
||||
global.Notification.requestPermission(function() {
|
||||
that.forceUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
if (!global.localStorage) return;
|
||||
global.localStorage.setItem('notifications_enabled', 'true');
|
||||
this.forceUpdate();
|
||||
},
|
||||
|
||||
onClick: function() {
|
||||
if (!this.notificationsAvailable()) {
|
||||
return;
|
||||
}
|
||||
if (!this.enabled()) {
|
||||
this.enable();
|
||||
} else {
|
||||
this.disable();
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -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,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,41 +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: {
|
||||
default_preset: React.PropTypes.string
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
default_preset: 'private_chat',
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
preset: this.props.default_preset,
|
||||
}
|
||||
},
|
||||
|
||||
getPreset: function() {
|
||||
return this.state.preset;
|
||||
},
|
||||
};
|
||||
@@ -1,41 +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: {
|
||||
default_name: React.PropTypes.string
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
default_name: '',
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
room_name: this.props.default_name,
|
||||
}
|
||||
},
|
||||
|
||||
getName: function() {
|
||||
return this.state.room_name;
|
||||
},
|
||||
};
|
||||
@@ -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,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,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,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 dis = require("../../dispatcher");
|
||||
|
||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
||||
|
||||
module.exports = {
|
||||
onClick: function() {
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
user_id: this.props.member.userId
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -1,67 +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");
|
||||
|
||||
module.exports = {
|
||||
componentDidMount: function() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
dis.unregister(this.dispatcherRef);
|
||||
},
|
||||
|
||||
onAction: function(payload) {
|
||||
switch (payload.action) {
|
||||
case 'focus_composer':
|
||||
this.refs.textarea.getDOMNode().focus();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onKeyDown: function (ev) {
|
||||
if (ev.keyCode == 13) {
|
||||
var contentText = this.refs.textarea.getDOMNode().value;
|
||||
|
||||
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.roomId, content).then(function() {
|
||||
dis.dispatch({
|
||||
action: 'message_sent'
|
||||
});
|
||||
});
|
||||
this.refs.textarea.getDOMNode().value = '';
|
||||
ev.preventDefault();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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,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 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,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");
|
||||
|
||||
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() {},
|
||||
default_hs_url: 'https://matrix.org/',
|
||||
default_is_url: 'https://matrix.org/'
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
hs_url: this.props.default_hs_url,
|
||||
is_url: this.props.default_is_url,
|
||||
}
|
||||
},
|
||||
|
||||
hsChanged: function(ev) {
|
||||
this.setState({hs_url: ev.target.value});
|
||||
this.props.onHsUrlChanged(this.state.hs_url);
|
||||
},
|
||||
|
||||
isChanged: function(ev) {
|
||||
this.setState({is_url: ev.target.value});
|
||||
this.props.onIsUrlChanged(this.state.is_url);
|
||||
},
|
||||
|
||||
getHsUrl: function() {
|
||||
return this.state.hs_url;
|
||||
},
|
||||
|
||||
getIsUrl: function() {
|
||||
return this.state.is_url;
|
||||
},
|
||||
};
|
||||
@@ -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 React = require('react');
|
||||
|
||||
module.exports = {
|
||||
propTypes: {
|
||||
initially_selected: React.PropTypes.arrayOf(React.PropTypes.string),
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
initially_selected: [],
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
selected_users: this.props.initially_selected,
|
||||
}
|
||||
},
|
||||
|
||||
addUser: function(user_id) {
|
||||
if (this.state.selected_users.indexOf(user_id == -1)) {
|
||||
this.setState({
|
||||
selected_users: this.state.selected_users.concat([user_id]),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
removeUser: function(user_id) {
|
||||
this.setState({
|
||||
selected_users: this.state.selected_users.filter(function(e) {
|
||||
return e != user_id;
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
||||
getUserIds: function() {
|
||||
return this.state.selected_users;
|
||||
}
|
||||
};
|
||||
96
src/controllers/molecules/voip/CallView.js
Normal file
96
src/controllers/molecules/voip/CallView.js
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
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("matrix-react-sdk/lib/dispatcher");
|
||||
var CallHandler = require("matrix-react-sdk/lib/CallHandler");
|
||||
var MatrixClientPeg = require("matrix-react-sdk/lib/MatrixClientPeg");
|
||||
|
||||
var VectorConferenceHandler = require('../../../modules/VectorConferenceHandler');
|
||||
|
||||
/*
|
||||
* State vars:
|
||||
* this.state.call = MatrixCall|null
|
||||
*
|
||||
* Props:
|
||||
* this.props.room = Room (JS SDK)
|
||||
*
|
||||
* Internal state:
|
||||
* this._trackedRoom = (either from props.room or programatically set)
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
|
||||
componentDidMount: function() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
this._trackedRoom = null;
|
||||
if (this.props.room) {
|
||||
this._trackedRoom = this.props.room;
|
||||
this.showCall(this._trackedRoom.roomId);
|
||||
}
|
||||
else {
|
||||
var call = CallHandler.getAnyActiveCall();
|
||||
if (call) {
|
||||
console.log(
|
||||
"Global CallView is now tracking active call in room %s",
|
||||
call.roomId
|
||||
);
|
||||
this._trackedRoom = MatrixClientPeg.get().getRoom(call.roomId);
|
||||
this.showCall(call.roomId);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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;
|
||||
}
|
||||
this.showCall(payload.room_id);
|
||||
},
|
||||
|
||||
showCall: function(roomId) {
|
||||
var call = (
|
||||
CallHandler.getCallForRoom(roomId) ||
|
||||
VectorConferenceHandler.getConferenceCallForRoom(roomId)
|
||||
);
|
||||
if (call) {
|
||||
call.setLocalVideoElement(this.getVideoView().getLocalVideoElement());
|
||||
call.setRemoteVideoElement(this.getVideoView().getRemoteVideoElement());
|
||||
// give a separate element for audio stream playback - both for voice calls
|
||||
// and for the voice stream of screen captures
|
||||
call.setRemoteAudioElement(this.getVideoView().getRemoteAudioElement());
|
||||
}
|
||||
if (call && call.type === "video" && call.state !== 'ended') {
|
||||
// if this call is a conf call, don't display local video as the
|
||||
// conference will have us in it
|
||||
this.getVideoView().getLocalVideoElement().style.display = (
|
||||
call.confUserId ? "none" : "initial"
|
||||
);
|
||||
this.getVideoView().getRemoteVideoElement().style.display = "initial";
|
||||
}
|
||||
else {
|
||||
this.getVideoView().getLocalVideoElement().style.display = "none";
|
||||
this.getVideoView().getRemoteVideoElement().style.display = "none";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,92 +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");
|
||||
|
||||
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: "",
|
||||
};
|
||||
},
|
||||
|
||||
onCreateRoom: function() {
|
||||
var options = {};
|
||||
|
||||
var room_name = this.getName();
|
||||
if (room_name) {
|
||||
options.name = room_name;
|
||||
}
|
||||
|
||||
var preset = this.getPreset();
|
||||
if (preset) {
|
||||
options.preset = preset;
|
||||
}
|
||||
|
||||
var invited_users = this.getInvitedUsers();
|
||||
if (invited_users) {
|
||||
options.invite = invited_users;
|
||||
}
|
||||
|
||||
var cli = MatrixClientPeg.get();
|
||||
if (!cli) {
|
||||
// TODO: Error.
|
||||
console.error("Cannot create room: No matrix client.");
|
||||
return;
|
||||
}
|
||||
|
||||
var deferred = MatrixClientPeg.get().createRoom(options);
|
||||
|
||||
this.setState({
|
||||
phase: this.phases.CREATING,
|
||||
});
|
||||
|
||||
var self = this;
|
||||
|
||||
deferred.then(function () {
|
||||
self.setState({
|
||||
phase: self.phases.CREATED,
|
||||
});
|
||||
self.props.onRoomCreated();
|
||||
}, function(err) {
|
||||
self.setState({
|
||||
phase: self.phases.ERROR,
|
||||
error_string: err.toString(),
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require("react");
|
||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
||||
|
||||
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);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
if (MatrixClientPeg.get()) {
|
||||
MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember);
|
||||
}
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
var that = this;
|
||||
setTimeout(function() {
|
||||
if (!that.isMounted()) return;
|
||||
that.setState({
|
||||
memberDict: that.roomMembers()
|
||||
});
|
||||
}, 50);
|
||||
},
|
||||
|
||||
// Remember to set 'key' on a MemberList to the ID of the room it's for
|
||||
/*componentWillReceiveProps: function(newProps) {
|
||||
},*/
|
||||
|
||||
onRoomStateMember: function(ev, state, member) {
|
||||
var members = this.roomMembers();
|
||||
this.setState({
|
||||
memberDict: members
|
||||
});
|
||||
},
|
||||
|
||||
roomMembers: function(limit) {
|
||||
var cli = MatrixClientPeg.get();
|
||||
var all_members = cli.getRoom(this.props.roomId).currentState.members;
|
||||
var all_user_ids = Object.keys(all_members);
|
||||
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,46 +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 = {
|
||||
start: function() {
|
||||
this.boundOnRoomTimeline = this.onRoomTimeline.bind(this);
|
||||
MatrixClientPeg.get().on('Room.timeline', this.boundOnRoomTimeline);
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
if (MatrixClientPeg.get()) {
|
||||
MatrixClientPeg.get().removeListener('Room.timeline', this.boundOnRoomTimeline);
|
||||
}
|
||||
},
|
||||
|
||||
onRoomTimeline: function(ev, room, toStartOfTimeline) {
|
||||
if (toStartOfTimeline) return;
|
||||
if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) return;
|
||||
|
||||
var enabled = global.localStorage.getItem('notifications_enabled');
|
||||
if (enabled === 'false') return;
|
||||
|
||||
var actions = MatrixClientPeg.get().getPushActionsForEvent(ev);
|
||||
if (actions && actions.notify) {
|
||||
this.displayNotification(ev, room);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -17,12 +17,15 @@ limitations under the License.
|
||||
'use strict';
|
||||
|
||||
var React = require("react");
|
||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
||||
var RoomListSorter = require("../../RoomListSorter");
|
||||
var MatrixClientPeg = require("matrix-react-sdk/lib/MatrixClientPeg");
|
||||
var RoomListSorter = require("matrix-react-sdk/lib/RoomListSorter");
|
||||
var dis = require("matrix-react-sdk/lib/dispatcher");
|
||||
|
||||
var ComponentBroker = require('../../ComponentBroker');
|
||||
var sdk = require('matrix-react-sdk');
|
||||
var VectorConferenceHandler = require("../../modules/VectorConferenceHandler");
|
||||
var CallHandler = require("matrix-react-sdk/lib/CallHandler");
|
||||
|
||||
var RoomTile = ComponentBroker.get("molecules/RoomTile");
|
||||
var HIDE_CONFERENCE_CHANS = true;
|
||||
|
||||
module.exports = {
|
||||
componentWillMount: function() {
|
||||
@@ -38,7 +41,27 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
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;
|
||||
case 'view_tooltip':
|
||||
this.tooltip = payload.tooltip;
|
||||
this._repositionTooltip();
|
||||
if (this.tooltip) this.tooltip.style.display = 'block';
|
||||
break
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
dis.unregister(this.dispatcherRef);
|
||||
if (MatrixClientPeg.get()) {
|
||||
MatrixClientPeg.get().removeListener("Room", this.onRoom);
|
||||
MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline);
|
||||
@@ -48,6 +71,7 @@ module.exports = {
|
||||
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
this.state.activityMap[newProps.selectedRoom] = undefined;
|
||||
this._recheckCallElement(newProps.selectedRoom);
|
||||
this.setState({
|
||||
activityMap: this.state.activityMap
|
||||
});
|
||||
@@ -73,13 +97,11 @@ module.exports = {
|
||||
if (actions && actions.tweaks && actions.tweaks.highlight) {
|
||||
hl = 2;
|
||||
}
|
||||
if (actions.notify) {
|
||||
// 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);
|
||||
// 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;
|
||||
}
|
||||
newState.activityMap = amap;
|
||||
}
|
||||
this.setState(newState);
|
||||
},
|
||||
@@ -96,23 +118,65 @@ module.exports = {
|
||||
},
|
||||
|
||||
getRoomList: function() {
|
||||
return RoomListSorter.mostRecentActivityFirst(MatrixClientPeg.get().getRooms());
|
||||
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 (VectorConferenceHandler.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
|
||||
});
|
||||
},
|
||||
|
||||
_repositionTooltip: function(e) {
|
||||
if (this.tooltip && this.tooltip.parentElement) {
|
||||
var scroll = this.getDOMNode();
|
||||
this.tooltip.style.top = (scroll.parentElement.offsetTop + this.tooltip.parentElement.offsetTop - scroll.scrollTop) + "px";
|
||||
}
|
||||
},
|
||||
|
||||
makeRoomTiles: function() {
|
||||
var that = this;
|
||||
var self = this;
|
||||
var RoomTile = sdk.getComponent("molecules.RoomTile");
|
||||
return this.state.roomList.map(function(room) {
|
||||
var selected = room.roomId == that.props.selectedRoom;
|
||||
var selected = room.roomId == self.props.selectedRoom;
|
||||
return (
|
||||
<RoomTile
|
||||
room={room}
|
||||
key={room.roomId}
|
||||
collapsed={self.props.collapsed}
|
||||
selected={selected}
|
||||
unread={that.state.activityMap[room.roomId] === 1}
|
||||
highlight={that.state.activityMap[room.roomId] === 2}
|
||||
unread={self.state.activityMap[room.roomId] === 1}
|
||||
highlight={self.state.activityMap[room.roomId] === 2}
|
||||
/>
|
||||
);
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -14,36 +14,39 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
||||
var MatrixClientPeg = require("matrix-react-sdk/lib/MatrixClientPeg");
|
||||
var React = require("react");
|
||||
var q = require("q");
|
||||
var ContentMessages = require("../../ContentMessages");
|
||||
var ContentMessages = require("matrix-react-sdk/lib//ContentMessages");
|
||||
var WhoIsTyping = require("matrix-react-sdk/lib/WhoIsTyping");
|
||||
var Modal = require("matrix-react-sdk/lib/Modal");
|
||||
var sdk = require('matrix-react-sdk/lib/index');
|
||||
var CallHandler = require('matrix-react-sdk/lib/CallHandler');
|
||||
var VectorConferenceHandler = require('../../modules/VectorConferenceHandler');
|
||||
|
||||
var dis = require("../../dispatcher");
|
||||
var dis = require("matrix-react-sdk/lib/dispatcher");
|
||||
|
||||
var PAGINATE_SIZE = 20;
|
||||
var INITIAL_SIZE = 100;
|
||||
|
||||
var ComponentBroker = require('../../ComponentBroker');
|
||||
|
||||
var tileTypes = {
|
||||
'm.room.message': ComponentBroker.get('molecules/MessageTile'),
|
||||
'm.room.member': ComponentBroker.get('molecules/MRoomMemberTile')
|
||||
};
|
||||
var INITIAL_SIZE = 20;
|
||||
|
||||
module.exports = {
|
||||
getInitialState: function() {
|
||||
return {
|
||||
room: this.props.roomId ? MatrixClientPeg.get().getRoom(this.props.roomId) : null,
|
||||
messageCap: INITIAL_SIZE
|
||||
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;
|
||||
},
|
||||
|
||||
@@ -51,19 +54,46 @@ module.exports = {
|
||||
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);
|
||||
}
|
||||
},
|
||||
|
||||
onAction: function(payload) {
|
||||
switch (payload.action) {
|
||||
case 'message_send_failed':
|
||||
case 'message_sent':
|
||||
case 'message_resend_started':
|
||||
this.setState({
|
||||
room: MatrixClientPeg.get().getRoom(this.props.roomId)
|
||||
});
|
||||
this.forceUpdate();
|
||||
break;
|
||||
case 'notifier_enabled':
|
||||
this.forceUpdate();
|
||||
break;
|
||||
case 'call_state':
|
||||
if (CallHandler.getCallForRoom(this.props.roomId)) {
|
||||
// Call state has changed so we may be loading video elements
|
||||
// which will obscure the message log.
|
||||
// scroll to bottom
|
||||
var messageWrapper = this.refs.messageWrapper;
|
||||
if (messageWrapper) {
|
||||
messageWrapper = messageWrapper.getDOMNode();
|
||||
messageWrapper.scrollTop = messageWrapper.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// possibly remove the conf call notification if we're now in
|
||||
// the conf
|
||||
this._updateConfCallNotification();
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -87,13 +117,31 @@ module.exports = {
|
||||
// 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;
|
||||
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)
|
||||
room: MatrixClientPeg.get().getRoom(this.props.roomId),
|
||||
numUnreadMessages: currentUnread
|
||||
});
|
||||
|
||||
if (toStartOfTimeline && !this.state.paginating) {
|
||||
@@ -101,17 +149,63 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
onRoomName: function(room) {
|
||||
if (room.roomId == this.props.roomId) {
|
||||
this.setState({
|
||||
room: room
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onRoomMemberTyping: function(ev, member) {
|
||||
this.forceUpdate();
|
||||
},
|
||||
|
||||
onRoomStateMember: function(ev, state, member) {
|
||||
if (member.roomId !== this.props.roomId ||
|
||||
member.userId !== VectorConferenceHandler.getConferenceUserIdForRoom(member.roomId)) {
|
||||
return;
|
||||
}
|
||||
this._updateConfCallNotification();
|
||||
},
|
||||
|
||||
_updateConfCallNotification: function() {
|
||||
var room = MatrixClientPeg.get().getRoom(this.props.roomId);
|
||||
if (!room) return;
|
||||
var confMember = room.getMember(
|
||||
VectorConferenceHandler.getConferenceUserIdForRoom(this.props.roomId)
|
||||
);
|
||||
|
||||
if (!confMember) {
|
||||
return;
|
||||
}
|
||||
var confCall = VectorConferenceHandler.getConferenceCallForRoom(confMember.roomId);
|
||||
|
||||
// A conf call notification should be displayed if there is an ongoing
|
||||
// conf call but this cilent isn't a part of it.
|
||||
this.setState({
|
||||
displayConfCallNotification: (
|
||||
(!confCall || confCall.call_state === "ended") &&
|
||||
confMember.membership === "join"
|
||||
)
|
||||
});
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
if (this.refs.messageWrapper) {
|
||||
var messageWrapper = this.refs.messageWrapper.getDOMNode();
|
||||
|
||||
messageWrapper.addEventListener('drop', this.onDrop);
|
||||
messageWrapper.addEventListener('dragover', this.onDragOver);
|
||||
messageWrapper.addEventListener('dragleave', this.onDragLeaveOrEnd);
|
||||
messageWrapper.addEventListener('dragend', this.onDragLeaveOrEnd);
|
||||
|
||||
messageWrapper.scrollTop = messageWrapper.scrollHeight;
|
||||
|
||||
this.fillSpace();
|
||||
}
|
||||
|
||||
this._updateConfCallNotification();
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
@@ -128,10 +222,14 @@ module.exports = {
|
||||
}
|
||||
} 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});
|
||||
@@ -146,12 +244,12 @@ module.exports = {
|
||||
this.waiting_for_paginate = true;
|
||||
var cap = this.state.messageCap + PAGINATE_SIZE;
|
||||
this.setState({messageCap: cap, paginating: true});
|
||||
var that = this;
|
||||
var self = this;
|
||||
MatrixClientPeg.get().scrollback(this.state.room, PAGINATE_SIZE).finally(function() {
|
||||
that.waiting_for_paginate = false;
|
||||
if (that.isMounted()) {
|
||||
that.setState({
|
||||
room: MatrixClientPeg.get().getRoom(that.props.roomId)
|
||||
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
|
||||
@@ -164,14 +262,14 @@ module.exports = {
|
||||
},
|
||||
|
||||
onJoinButtonClicked: function(ev) {
|
||||
var that = this;
|
||||
var self = this;
|
||||
MatrixClientPeg.get().joinRoom(this.props.roomId).then(function() {
|
||||
that.setState({
|
||||
self.setState({
|
||||
joining: false,
|
||||
room: MatrixClientPeg.get().getRoom(that.props.roomId)
|
||||
room: MatrixClientPeg.get().getRoom(self.props.roomId)
|
||||
});
|
||||
}, function(error) {
|
||||
that.setState({
|
||||
self.setState({
|
||||
joining: false,
|
||||
joinError: error
|
||||
});
|
||||
@@ -184,7 +282,11 @@ module.exports = {
|
||||
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();
|
||||
},
|
||||
@@ -198,6 +300,7 @@ module.exports = {
|
||||
var items = ev.dataTransfer.items;
|
||||
if (items.length == 1) {
|
||||
if (items[0].kind == 'file') {
|
||||
this.setState({ draggingFile : true });
|
||||
ev.dataTransfer.dropEffect = 'copy';
|
||||
}
|
||||
}
|
||||
@@ -206,33 +309,198 @@ module.exports = {
|
||||
onDrop: function(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
this.setState({ draggingFile : false });
|
||||
var files = ev.dataTransfer.files;
|
||||
|
||||
if (files.length == 1) {
|
||||
ContentMessages.sendContentToRoom(
|
||||
files[0], this.props.roomId, MatrixClientPeg.get()
|
||||
).progress(function(ev) {
|
||||
//console.log("Upload: "+ev.loaded+" / "+ev.total);
|
||||
}).done(undefined, function() {
|
||||
// display error message
|
||||
});
|
||||
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 tileTypes = {
|
||||
'm.room.message': sdk.getComponent('molecules.MessageTile'),
|
||||
'm.room.member' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
'm.call.invite' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
'm.call.answer' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
'm.call.hangup' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
'm.room.topic' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
};
|
||||
|
||||
var DateSeparator = sdk.getComponent('molecules.DateSeparator');
|
||||
|
||||
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 (i === 1) { // n.b. 1, not 0, as the 0th event is an m.room.create and so doesn't show on the timeline
|
||||
var ts1 = this.state.room.timeline[i].getTs();
|
||||
dateSeparator = <DateSeparator key={ts1} ts={ts1}/>;
|
||||
continuation = false;
|
||||
}
|
||||
|
||||
if (!TileType) continue;
|
||||
ret.unshift(
|
||||
<TileType key={mxEv.getId()} mxEvent={mxEv} />
|
||||
<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) {
|
||||
var ErrorDialog = sdk.getComponent("organisms.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to set state",
|
||||
description: err.toString()
|
||||
});
|
||||
}).finally(function() {
|
||||
self.setState({
|
||||
uploadingRoomSettings: false,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
editingRoomSettings: false,
|
||||
uploadingRoomSettings: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,202 +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 dis = require("../../dispatcher");
|
||||
|
||||
var ComponentBroker = require('../../ComponentBroker');
|
||||
|
||||
var Notifier = ComponentBroker.get('organisms/Notifier');
|
||||
|
||||
module.exports = {
|
||||
getInitialState: function() {
|
||||
return {
|
||||
logged_in: !!(MatrixClientPeg.get() && MatrixClientPeg.get().credentials),
|
||||
ready: false
|
||||
};
|
||||
},
|
||||
|
||||
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);
|
||||
},
|
||||
|
||||
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();
|
||||
MatrixClientPeg.get().removeAllListeners();
|
||||
MatrixClientPeg.replace(null);
|
||||
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
|
||||
});
|
||||
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;
|
||||
this.setState({
|
||||
currentRoom: allRooms[roomIndex].roomId
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onLoggedIn: function() {
|
||||
this.setState({
|
||||
screen: undefined,
|
||||
logged_in: true
|
||||
});
|
||||
this.startMatrixClient();
|
||||
this.notifyNewScreen('');
|
||||
},
|
||||
|
||||
startMatrixClient: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
var that = this;
|
||||
cli.on('syncComplete', function() {
|
||||
var firstRoom = null;
|
||||
if (cli.getRooms() && cli.getRooms().length) {
|
||||
firstRoom = RoomListSorter.mostRecentActivityFirst(
|
||||
cli.getRooms()
|
||||
)[0].roomId;
|
||||
}
|
||||
that.setState({ready: true, currentRoom: firstRoom});
|
||||
dis.dispatch({action: 'focus_composer'});
|
||||
});
|
||||
Notifier.start();
|
||||
cli.startClient();
|
||||
},
|
||||
|
||||
onKeyDown: function(ev) {
|
||||
if (ev.altKey) {
|
||||
switch (ev.keyCode) {
|
||||
case 38:
|
||||
dis.dispatch({action: 'view_prev_room'});
|
||||
ev.stopPropagation();
|
||||
break;
|
||||
case 40:
|
||||
dis.dispatch({action: 'view_next_room'});
|
||||
ev.stopPropagation();
|
||||
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
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
notifyNewScreen: function(screen) {
|
||||
if (this.props.onNewScreen) {
|
||||
this.props.onNewScreen(screen);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,98 +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, errorText: '', busy: false });
|
||||
},
|
||||
|
||||
onHSChosen: function(ev) {
|
||||
ev.preventDefault();
|
||||
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});
|
||||
var that = this;
|
||||
cli.loginFlows().done(function(result) {
|
||||
that.setState({
|
||||
flows: result.flows,
|
||||
currentStep: 1,
|
||||
totalSteps: result.flows.length+1
|
||||
});
|
||||
that.setStep('stage_'+result.flows[0].type);
|
||||
}, function(error) {
|
||||
that.setStep("choose_hs");
|
||||
that.setState({errorText: 'Unable to contact the given Home Server'});
|
||||
});
|
||||
},
|
||||
|
||||
onUserPassEntered: function(ev) {
|
||||
ev.preventDefault();
|
||||
this.setState({busy: true});
|
||||
var that = this;
|
||||
|
||||
var formVals = this.getFormVals();
|
||||
|
||||
MatrixClientPeg.get().login('m.login.password', {
|
||||
'user': formVals.username,
|
||||
'password': formVals.password
|
||||
}).done(function(data) {
|
||||
MatrixClientPeg.replaceUsingAccessToken(
|
||||
that.state.hs_url, that.state.is_url,
|
||||
data.user_id, data.access_token
|
||||
);
|
||||
if (that.props.onLoggedIn) {
|
||||
that.props.onLoggedIn();
|
||||
}
|
||||
}, function(error) {
|
||||
that.setStep("stage_m.login.password");
|
||||
that.setState({errorText: 'Login failed.'});
|
||||
});
|
||||
},
|
||||
|
||||
showRegister: function(ev) {
|
||||
ev.preventDefault();
|
||||
dis.dispatch({
|
||||
action: 'start_registration'
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -16,326 +16,43 @@ limitations under the License.
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var extend = require('matrix-react-sdk/lib/extend');
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
var BaseRegisterController = require('matrix-react-sdk/lib/controllers/templates/Register.js');
|
||||
|
||||
var MatrixClientPeg = require("../../MatrixClientPeg");
|
||||
var Matrix = require("matrix-js-sdk");
|
||||
var dis = require("../../dispatcher");
|
||||
var RegisterController = {};
|
||||
extend(RegisterController, BaseRegisterController);
|
||||
|
||||
var ComponentBroker = require("../../ComponentBroker");
|
||||
RegisterController.onRegistered = function(user_id, access_token) {
|
||||
MatrixClientPeg.replaceUsingAccessToken(
|
||||
this.state.hs_url, this.state.is_url, user_id, access_token
|
||||
);
|
||||
|
||||
module.exports = {
|
||||
FieldErrors: {
|
||||
PasswordMismatch: 'PasswordMismatch',
|
||||
TooShort: 'TooShort',
|
||||
Missing: 'Missing',
|
||||
InUse: 'InUse'
|
||||
},
|
||||
this.setState({
|
||||
step: 'profile',
|
||||
busy: true
|
||||
});
|
||||
|
||||
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.savedParams = {
|
||||
email: formVals.email,
|
||||
username: formVals.username,
|
||||
password: formVals.password
|
||||
};
|
||||
|
||||
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.setState({
|
||||
busy: false,
|
||||
errorText: 'Unable to contact the given Home Server'
|
||||
});
|
||||
});
|
||||
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
|
||||
var self = this;
|
||||
var cli = MatrixClientPeg.get();
|
||||
cli.getProfileInfo(cli.credentials.userId).done(function(result) {
|
||||
self.setState({
|
||||
avatarUrl: result.avatar_url,
|
||||
busy: false
|
||||
});
|
||||
},
|
||||
|
||||
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!";
|
||||
}
|
||||
self.setState(newState);
|
||||
}
|
||||
function(err) {
|
||||
console.err(err);
|
||||
self.setState({
|
||||
busy: false
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
showLogin: function(ev) {
|
||||
ev.preventDefault();
|
||||
dis.dispatch({
|
||||
action: 'start_login'
|
||||
});
|
||||
RegisterController.onAccountReady = function() {
|
||||
if (this.props.onLoggedIn) {
|
||||
this.props.onLoggedIn();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = RegisterController;
|
||||
|
||||
@@ -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,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;
|
||||
134
src/modules/VectorConferenceHandler.js
Normal file
134
src/modules/VectorConferenceHandler.js
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var q = require("q");
|
||||
var Matrix = require("matrix-js-sdk");
|
||||
var Room = Matrix.Room;
|
||||
var CallHandler = require('matrix-react-sdk/lib/CallHandler');
|
||||
|
||||
// FIXME: This currently forces Vector to try to hit the matrix.org AS for conferencing.
|
||||
// This is bad because it prevents people running their own ASes from being used.
|
||||
// This isn't permanent and will be customisable in the future: see the proposal
|
||||
// at docs/conferencing.md for more info.
|
||||
var USER_PREFIX = "fs_";
|
||||
var DOMAIN = "matrix.org";
|
||||
|
||||
function ConferenceCall(matrixClient, groupChatRoomId) {
|
||||
this.client = matrixClient;
|
||||
this.groupRoomId = groupChatRoomId;
|
||||
this.confUserId = module.exports.getConferenceUserIdForRoom(this.groupRoomId);
|
||||
}
|
||||
|
||||
ConferenceCall.prototype.setup = function() {
|
||||
var self = this;
|
||||
return this._joinConferenceUser().then(function() {
|
||||
return self._getConferenceUserRoom();
|
||||
}).then(function(room) {
|
||||
// return a call for *this* room to be placed. We also tack on
|
||||
// confUserId to speed up lookups (else we'd need to loop every room
|
||||
// looking for a 1:1 room with this conf user ID!)
|
||||
var call = Matrix.createNewMatrixCall(self.client, room.roomId);
|
||||
call.confUserId = self.confUserId;
|
||||
return call;
|
||||
});
|
||||
};
|
||||
|
||||
ConferenceCall.prototype._joinConferenceUser = function() {
|
||||
// Make sure the conference user is in the group chat room
|
||||
var groupRoom = this.client.getRoom(this.groupRoomId);
|
||||
if (!groupRoom) {
|
||||
return q.reject("Bad group room ID");
|
||||
}
|
||||
var member = groupRoom.getMember(this.confUserId);
|
||||
if (member && member.membership === "join") {
|
||||
return q();
|
||||
}
|
||||
return this.client.invite(this.groupRoomId, this.confUserId);
|
||||
};
|
||||
|
||||
ConferenceCall.prototype._getConferenceUserRoom = function() {
|
||||
// Use an existing 1:1 with the conference user; else make one
|
||||
var rooms = this.client.getRooms();
|
||||
var confRoom = null;
|
||||
for (var i = 0; i < rooms.length; i++) {
|
||||
var confUser = rooms[i].getMember(this.confUserId);
|
||||
if (confUser && confUser.membership === "join" &&
|
||||
rooms[i].getJoinedMembers().length === 2) {
|
||||
confRoom = rooms[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (confRoom) {
|
||||
return q(confRoom);
|
||||
}
|
||||
return this.client.createRoom({
|
||||
preset: "private_chat",
|
||||
invite: [this.confUserId]
|
||||
}).then(function(res) {
|
||||
return new Room(res.room_id);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this room member is in fact a conference bot.
|
||||
* @param {RoomMember} The room member to check
|
||||
* @return {boolean} True if it is a conference bot.
|
||||
*/
|
||||
module.exports.isConferenceUser = function(roomMember) {
|
||||
if (roomMember.userId.indexOf("@" + USER_PREFIX) !== 0) {
|
||||
return false;
|
||||
}
|
||||
var base64part = roomMember.userId.split(":")[0].substring(1 + USER_PREFIX.length);
|
||||
if (base64part) {
|
||||
var decoded = new Buffer(base64part, "base64").toString();
|
||||
// ! $STUFF : $STUFF
|
||||
return /^!.+:.+/.test(decoded);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
module.exports.getConferenceUserIdForRoom = function(roomId) {
|
||||
// abuse browserify's core node Buffer support (strip padding ='s)
|
||||
var base64RoomId = new Buffer(roomId).toString("base64").replace(/=/g, "");
|
||||
return "@" + USER_PREFIX + base64RoomId + ":" + DOMAIN;
|
||||
};
|
||||
|
||||
module.exports.createNewMatrixCall = function(client, roomId) {
|
||||
var confCall = new ConferenceCall(
|
||||
client, roomId
|
||||
);
|
||||
return confCall.setup();
|
||||
};
|
||||
|
||||
module.exports.getConferenceCallForRoom = function(roomId) {
|
||||
// search for a conference 1:1 call for this group chat room ID
|
||||
var activeCall = CallHandler.getAnyActiveCall();
|
||||
if (activeCall && activeCall.confUserId) {
|
||||
var thisRoomConfUserId = module.exports.getConferenceUserIdForRoom(
|
||||
roomId
|
||||
);
|
||||
if (thisRoomConfUserId === activeCall.confUserId) {
|
||||
return activeCall;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
module.exports.ConferenceCall = ConferenceCall;
|
||||
|
||||
module.exports.slot = 'conference';
|
||||
@@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_Login {
|
||||
width: 600px;
|
||||
height: 350px;
|
||||
position: relative;
|
||||
.mx_MemberAvatar {
|
||||
z-index: 20;
|
||||
border-radius: 20px;
|
||||
background-color: #dbdbdb;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MessageTimestamp {
|
||||
display: table-cell;
|
||||
white-space: pre;
|
||||
}
|
||||
160
src/skins/vector/css/common.css
Normal file
160
src/skins/vector/css/common.css
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
html {
|
||||
/* hack to stop overscroll bounce on OSX and iOS.
|
||||
N.B. Breaks things when we have legitimate horizontal overscroll */
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Lato', Helvetica, Arial, Sans-Serif;
|
||||
font-size: 16px;
|
||||
color: #454545;
|
||||
border: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
div.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #80cef4;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:link,
|
||||
a:visited {
|
||||
color: #80CEF4;
|
||||
}
|
||||
|
||||
.mx_ContextualMenu_background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 1.0;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.mx_ContextualMenu {
|
||||
border: 1px solid #a9dbf4;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
color: #747474;
|
||||
position: fixed;
|
||||
z-index: 2001;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.mx_ContextualMenu_chevron {
|
||||
padding: 12px;
|
||||
position: absolute;
|
||||
right: -21px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.mx_ContextualMenu_field {
|
||||
padding: 3px 6px 3px 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.mx_Dialog_background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #000;
|
||||
opacity: 0.2;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.mx_Dialog_wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mx_Dialog {
|
||||
background-color: #fff;
|
||||
color: #747474;
|
||||
text-align: center;
|
||||
z-index: 2010;
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
.mx_ImageView {
|
||||
margin: 6px;
|
||||
/* hack: flexbox bug? */
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.mx_Dialog_content {
|
||||
margin: 24px;
|
||||
}
|
||||
|
||||
.mx_Dialog_buttons {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.mx_Dialog button {
|
||||
border: 0px;
|
||||
height: 36px;
|
||||
border-radius: 36px;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background-color: #80cef4;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.mx_ErrorDialogTitle,
|
||||
.mx_QuestionDialogTitle {
|
||||
min-height: 16px;
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid #a9dbf4;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
10
src/skins/vector/css/hide.css
Normal file
10
src/skins/vector/css/hide.css
Normal file
@@ -0,0 +1,10 @@
|
||||
.mx_RoomDropTarget,
|
||||
.mx_RoomList_favourites_label,
|
||||
.mx_RoomList_archive_label,
|
||||
.mx_RoomHeader_search,
|
||||
.mx_RoomSettings_encrypt,
|
||||
.mx_CreateRoom_encrypt,
|
||||
.mx_RightPanel_filebutton
|
||||
{
|
||||
display: none !important;
|
||||
}
|
||||
37
src/skins/vector/css/molecules/MImageTile.css
Normal file
37
src/skins/vector/css/molecules/MImageTile.css
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_MImageTile_thumbnail {
|
||||
/*
|
||||
background-color: #fff;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 1px;
|
||||
*/
|
||||
}
|
||||
|
||||
.mx_MImageTile_download {
|
||||
color: #80cef4;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_MImageTile_download a {
|
||||
color: #80cef4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mx_MImageTile_download img {
|
||||
padding-right: 8px;
|
||||
}
|
||||
@@ -15,4 +15,5 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MNoticeTile {
|
||||
opacity: 0.5;
|
||||
}
|
||||
34
src/skins/vector/css/molecules/MatrixToolbar.css
Normal file
34
src/skins/vector/css/molecules/MatrixToolbar.css
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MatrixToolbar {
|
||||
text-align: center;
|
||||
background-color: #ff0064;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.mx_MatrixToolbar button {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.mx_MatrixToolbar_close {
|
||||
float: right;
|
||||
margin-top: 3px;
|
||||
margin-right: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -14,5 +14,3 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_RoomList {
|
||||
}
|
||||
134
src/skins/vector/css/molecules/MemberTile.css
Normal file
134
src/skins/vector/css/molecules/MemberTile.css
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_MemberTile {
|
||||
display: table-row;
|
||||
height: 49px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_MemberTile_avatar {
|
||||
display: table-cell;
|
||||
padding-left: 14px;
|
||||
padding-right: 12px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
vertical-align: middle;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_MemberTile_inviteTile {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_MemberTile_inviteEditing {
|
||||
display: initial ! important;
|
||||
}
|
||||
|
||||
.mx_MemberTile_inviteEditing .mx_MemberTile_avatar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_MemberTile_inviteEditing .mx_MemberTile_name {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.mx_MemberTile_inviteEditing .mx_MemberTile_name input {
|
||||
border-radius: 3px;
|
||||
border: 1px solid #c7c7c7;
|
||||
font-weight: 300;
|
||||
font-size: 14px;
|
||||
padding: 9px;
|
||||
margin-top: 6px;
|
||||
margin-left: 14px;
|
||||
}
|
||||
|
||||
.mx_MemberTile_power {
|
||||
position: absolute;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
left: 10px;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.mx_MemberTile_name {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_MemberTile_details {
|
||||
display: table-cell;
|
||||
padding-right: 14px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_MemberTile_hover {
|
||||
background-color: #f0f0f0;
|
||||
font-size: 12px;
|
||||
color: #747474;
|
||||
}
|
||||
|
||||
.mx_MemberTile_userId {
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_MemberTile_leave {
|
||||
cursor: pointer;
|
||||
margin-top: 8px;
|
||||
margin-right: -4px;
|
||||
margin-left: 6px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
/*
|
||||
.mx_MemberTile_nameWrapper {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_MemberTile_nameSpan {
|
||||
}
|
||||
*/
|
||||
|
||||
.mx_MemberTile_unavailable .mx_MemberTile_avatar,
|
||||
.mx_MemberTile_unavailable .mx_MemberTile_name,
|
||||
.mx_MemberTile_unavailable .mx_MemberTile_nameSpan
|
||||
{
|
||||
opacity: 0.66;
|
||||
}
|
||||
|
||||
.mx_MemberTile_offline .mx_MemberTile_avatar,
|
||||
.mx_MemberTile_offline .mx_MemberTile_name,
|
||||
.mx_MemberTile_offline .mx_MemberTile_nameSpan
|
||||
{
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.mx_MemberTile_zalgo {
|
||||
font-family: Helvetica, Arial, Sans-Serif;
|
||||
}
|
||||
|
||||
.mx_MemberTile:hover .mx_MessageTimestamp {
|
||||
display: block;
|
||||
}
|
||||
84
src/skins/vector/css/molecules/MessageComposer.css
Normal file
84
src/skins/vector/css/molecules/MessageComposer.css
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_MessageComposer_wrapper {
|
||||
max-width: 720px;
|
||||
height: 50px;
|
||||
vertical-align: middle;
|
||||
margin: auto;
|
||||
background-color: #fff;
|
||||
border-radius: 25px;
|
||||
border: 1px solid #a9dbf4;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_row {
|
||||
display: table-row;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer .mx_MessageComposer_avatar {
|
||||
display: table-cell;
|
||||
padding-left: 5px;
|
||||
padding-right: 10px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer .mx_MessageComposer_avatar img {
|
||||
margin-top: 5px;
|
||||
border-radius: 20px;
|
||||
background-color: #dbdbdb;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input {
|
||||
display: table-cell;
|
||||
width: 100%;
|
||||
vertical-align: middle;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input textarea {
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
height: 1.2em;
|
||||
padding-top: 0.7em;
|
||||
padding-bottom: 0.7em;
|
||||
border: 0px;
|
||||
resize: none;
|
||||
outline: none;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
|
||||
/* needed for FF */
|
||||
font-family: 'Lato', Helvetica, Arial, Sans-Serif;
|
||||
}
|
||||
|
||||
/* hack for FF as vertical alignment of custom placeholder text is broken */
|
||||
.mx_MessageComposer_input textarea::-moz-placeholder {
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_upload {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
padding-right: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_upload img {
|
||||
margin-top: 5px;
|
||||
}
|
||||
111
src/skins/vector/css/molecules/MessageTile.css
Normal file
111
src/skins/vector/css/molecules/MessageTile.css
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_MessageTile {
|
||||
max-width: 100%;
|
||||
clear: both;
|
||||
margin-top: 32px;
|
||||
margin-left: 56px;
|
||||
}
|
||||
|
||||
.mx_MessageTile_avatar {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
margin-left: -64px;
|
||||
margin-top: -7px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.mx_MessageTile_avatar img {
|
||||
background-color: #dbdbdb;
|
||||
border-radius: 20px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.mx_MessageTile_continuation {
|
||||
margin-top: 8px ! important;
|
||||
}
|
||||
|
||||
.mx_MessageTile .mx_SenderProfile {
|
||||
color: #454545;
|
||||
opacity: 0.5;
|
||||
font-size: 14px;
|
||||
margin-bottom: 4px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mx_MessageTile .mx_MessageTimestamp {
|
||||
color: #454545;
|
||||
opacity: 0.5;
|
||||
font-size: 14px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.mx_MessageTile_content {
|
||||
padding-right: 100px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mx_MessageTile_notice .mx_MessageTile_content {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.mx_MessageTile_sending {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.mx_MessageTile_notSent {
|
||||
color: #f11;
|
||||
}
|
||||
|
||||
.mx_MessageTile_highlight {
|
||||
color: #FF0064;
|
||||
}
|
||||
|
||||
.mx_MessageTile_msgOption {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.mx_MessageTimestamp {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_MessageTile_last .mx_MessageTimestamp {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mx_MessageTile:hover .mx_MessageTimestamp {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mx_MessageTile_editButton {
|
||||
float: right;
|
||||
display: none;
|
||||
border: 0px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.mx_MessageTile:hover .mx_MessageTile_editButton {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.mx_MessageTile.menu .mx_MessageTile_editButton {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.mx_MessageTile.menu .mx_MessageTimestamp {
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -14,10 +14,14 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
body {
|
||||
font-family: Helvetica, Arial, Sans-Serif;
|
||||
}
|
||||
|
||||
div.error {
|
||||
color: red;
|
||||
.mx_RoomDropTarget {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
background-color: #fbfbfb;
|
||||
border: 1px dashed #d7d7d7;
|
||||
border-radius: 8px;
|
||||
}
|
||||
173
src/skins/vector/css/molecules/RoomHeader.css
Normal file
173
src/skins/vector/css/molecules/RoomHeader.css
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_RoomHeader {
|
||||
}
|
||||
|
||||
.mx_RoomHeader_wrapper {
|
||||
max-width: 720px;
|
||||
margin: auto;
|
||||
height: 88px;
|
||||
border-bottom: 1px solid #a8dbf3;
|
||||
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_leftRow {
|
||||
height: 48px;
|
||||
margin-top: 18px;
|
||||
|
||||
-webkit-box-ordinal-group: 1;
|
||||
-moz-box-ordinal-group: 1;
|
||||
-ms-flex-order: 1;
|
||||
-webkit-order: 1;
|
||||
order: 1;
|
||||
|
||||
-webkit-flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_textButton {
|
||||
height: 48px;
|
||||
margin-top: 18px;
|
||||
background-color: #80cef4;
|
||||
border-radius: 48px;
|
||||
margin-right: 8px;
|
||||
color: #fff;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-moz-box-ordinal-group: 2;
|
||||
-ms-flex-order: 2;
|
||||
-webkit-order: 2;
|
||||
order: 2;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
/*
|
||||
-webkit-flex: 0 0 90px;
|
||||
flex: 0 0 90px;
|
||||
*/
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_rightRow {
|
||||
height: 48px;
|
||||
margin-top: 18px;
|
||||
background-color: #fff;
|
||||
border-radius: 48px;
|
||||
border: 1px solid #a9dbf4;
|
||||
|
||||
-webkit-box-ordinal-group: 3;
|
||||
-moz-box-ordinal-group: 3;
|
||||
-ms-flex-order: 3;
|
||||
-webkit-order: 3;
|
||||
order: 3;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_info {
|
||||
display: table-cell;
|
||||
height: 48px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_simpleHeader {
|
||||
line-height: 88px;
|
||||
color: #80cef4;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_name {
|
||||
vertical-align: middle;
|
||||
height: 28px;
|
||||
color: #80cef4;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_nameEditing {
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_name input, .mx_RoomHeader_nameInput {
|
||||
border-radius: 3px;
|
||||
width: 260px;
|
||||
border: 1px solid #c7c7c7;
|
||||
font-weight: 300;
|
||||
font-size: 14px;
|
||||
padding: 9px;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_nameInput {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_topic {
|
||||
vertical-align: bottom;
|
||||
float: left;
|
||||
max-height: 38px;
|
||||
color: #70b5d7;
|
||||
font-weight: 300;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_avatar {
|
||||
display: table-cell;
|
||||
width: 48px;
|
||||
height: 50px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_avatar img {
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_button {
|
||||
height: 48px;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_button img {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_voipButton {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_voipButtons {
|
||||
margin-top: 18px;
|
||||
}
|
||||
70
src/skins/vector/css/molecules/RoomSettings.css
Normal file
70
src/skins/vector/css/molecules/RoomSettings.css
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_RoomSettings {
|
||||
max-height: 250px;
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_settings {
|
||||
display: table;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_settings > div {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_settings > div > * {
|
||||
display: table-cell;
|
||||
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.mx_RoomSettings input,
|
||||
.mx_RoomSettings textarea {
|
||||
border-radius: 3px;
|
||||
border: 1px solid #c7c7c7;
|
||||
font-weight: 300;
|
||||
font-size: 14px;
|
||||
padding: 9px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_description {
|
||||
width: 330px;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_buttons {
|
||||
text-align: right;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_button {
|
||||
display: inline;
|
||||
border: 0px;
|
||||
height: 36px;
|
||||
border-radius: 36px;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background-color: #80cef4;
|
||||
width: auto;
|
||||
margin: auto;
|
||||
padding: 6px;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
104
src/skins/vector/css/molecules/RoomTile.css
Normal file
104
src/skins/vector/css/molecules/RoomTile.css
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_RoomTile {
|
||||
cursor: pointer;
|
||||
display: table-row;
|
||||
color: #818794;
|
||||
}
|
||||
|
||||
.mx_RoomTile_avatar {
|
||||
display: table-cell;
|
||||
padding-right: 10px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 10px;
|
||||
vertical-align: middle;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_RoomTile_avatar img {
|
||||
border-radius: 20px;
|
||||
background-color: #dbdbdb;
|
||||
}
|
||||
|
||||
.mx_RoomTile_name {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomTile_name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
.mx_RoomTile_nameBadge {
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.mx_RoomTile_badgeCell {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
width: 26px;
|
||||
}
|
||||
|
||||
.mx_RoomTile_badge {
|
||||
background-color: #80cef4;
|
||||
color: #fff;
|
||||
border-radius: 26px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
text-align: center;
|
||||
}
|
||||
*/
|
||||
|
||||
.mx_RoomTile_badge {
|
||||
background-color: #ff0064;
|
||||
border: 3px solid #fff;
|
||||
border-radius: 16px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
position: absolute;
|
||||
right: 9px;
|
||||
bottom: 3px;
|
||||
}
|
||||
|
||||
.mx_RoomTile_unread,
|
||||
.mx_RoomTile_highlight,
|
||||
.mx_RoomTile_invited
|
||||
{
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.mx_RoomTile_selected {
|
||||
background-color: #f3f8fa;
|
||||
color: #80cef4;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mx_RoomTile:hover {
|
||||
}
|
||||
33
src/skins/vector/css/molecules/RoomTooltip.css
Normal file
33
src/skins/vector/css/molecules/RoomTooltip.css
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_RoomTooltip {
|
||||
display: none;
|
||||
position: fixed;
|
||||
border: 1px solid #a9dbf4;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
z-index: 1000;
|
||||
margin-top: 6px;
|
||||
left: 64px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.mx_RoomTooltip_chevron {
|
||||
position: absolute;
|
||||
left: -9px;
|
||||
top: 8px;
|
||||
}
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_SenderProfile {
|
||||
display: table-cell;
|
||||
padding: 0px 1em 0em 1em;
|
||||
.mx_SenderProfile_zalgo {
|
||||
font-family: Helvetica, Arial, Sans-Serif;
|
||||
display: table-row ! important;
|
||||
}
|
||||
@@ -14,22 +14,18 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MessageTile {
|
||||
display: table-row;
|
||||
.mx_ServerConfig {
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.mx_MessageTile_content {
|
||||
display: table-cell;
|
||||
.mx_ServerConfig .mx_Login_field {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.mx_MessageTile_sending {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.mx_MessageTile_notSent {
|
||||
color: #f11;
|
||||
}
|
||||
|
||||
.mx_MessageTile_highlight {
|
||||
color: #00f;
|
||||
}
|
||||
.mx_ServerConfig_help:link {
|
||||
opacity: 0.8;
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
color: #4a4a4a;
|
||||
}
|
||||
@@ -12,10 +12,4 @@ 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 = {
|
||||
};
|
||||
|
||||
*/
|
||||
68
src/skins/vector/css/molecules/voip/IncomingCallbox.css
Normal file
68
src/skins/vector/css/molecules/voip/IncomingCallbox.css
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_IncomingCallBox {
|
||||
text-align: center;
|
||||
border: 1px solid #a9dbf4;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
left: 235px;
|
||||
top: 155px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.mx_IncomingCallBox_chevron {
|
||||
padding: 12px;
|
||||
position: absolute;
|
||||
left: -21px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.mx_IncomingCallBox_title {
|
||||
padding: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mx_IncomingCallBox_buttons {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.mx_IncomingCallBox_buttons_cell {
|
||||
vertical-align: middle;
|
||||
display: table-cell;
|
||||
padding: 6px;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.mx_IncomingCallBox_buttons_decline,
|
||||
.mx_IncomingCallBox_buttons_accept {
|
||||
vertical-align: middle;
|
||||
width: 80px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
border-radius: 36px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.mx_IncomingCallBox_buttons_decline {
|
||||
background-color: #f48080;
|
||||
}
|
||||
|
||||
.mx_IncomingCallBox_buttons_accept {
|
||||
background-color: #80f480;
|
||||
}
|
||||
@@ -14,18 +14,26 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function tsOfNewestEvent(room) {
|
||||
return room.timeline[room.timeline.length - 1].getTs();
|
||||
.mx_VideoView {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
z-index: 30;
|
||||
}
|
||||
|
||||
function mostRecentActivityFirst(roomList) {
|
||||
return roomList.sort(function(a,b) {
|
||||
return tsOfNewestEvent(b) - tsOfNewestEvent(a);
|
||||
});
|
||||
.mx_VideoView video {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mostRecentActivityFirst: mostRecentActivityFirst
|
||||
};
|
||||
.mx_VideoView_remoteVideoFeed {
|
||||
width: 100%;
|
||||
background-color: #000;
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
.mx_VideoView_localVideoFeed {
|
||||
width: 20%;
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
bottom: 28px;
|
||||
z-index: 100;
|
||||
}
|
||||
37
src/skins/vector/css/organisms/CreateRoom.css
Normal file
37
src/skins/vector/css/organisms/CreateRoom.css
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_CreateRoom {
|
||||
width: 720px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
.mx_CreateRoom input,
|
||||
.mx_CreateRoom textarea {
|
||||
border-radius: 3px;
|
||||
border: 1px solid #c7c7c7;
|
||||
font-weight: 300;
|
||||
font-size: 14px;
|
||||
padding: 9px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.mx_CreateRoom_description {
|
||||
width: 330px;
|
||||
}
|
||||
|
||||
69
src/skins/vector/css/organisms/LeftPanel.css
Normal file
69
src/skins/vector/css/organisms/LeftPanel.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_LeftPanel {
|
||||
position: relative;
|
||||
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
}
|
||||
|
||||
.mx_LeftPanel_hideButton {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 0px;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_RoomList {
|
||||
-webkit-box-ordinal-group: 1;
|
||||
-moz-box-ordinal-group: 1;
|
||||
-ms-flex-order: 1;
|
||||
-webkit-order: 1;
|
||||
order: 1;
|
||||
|
||||
overflow-y: auto;
|
||||
-webkit-flex: 1 1 0;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_BottomLeftMenu {
|
||||
-webkit-box-ordinal-group: 3;
|
||||
-moz-box-ordinal-group: 3;
|
||||
-ms-flex-order: 3;
|
||||
-webkit-order: 3;
|
||||
order: 3;
|
||||
|
||||
-webkit-flex: 0 0 170px;
|
||||
flex: 0 0 170px;
|
||||
|
||||
border-top: 1px solid #f3f8fa;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_BottomLeftMenu .mx_RoomTile {
|
||||
color: #378bb4;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_BottomLeftMenu .mx_BottomLeftMenu_options {
|
||||
margin-top: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
60
src/skins/vector/css/organisms/MemberList.css
Normal file
60
src/skins/vector/css/organisms/MemberList.css
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_MemberList {
|
||||
height: 100%;
|
||||
margin-bottom: 100px;
|
||||
padding: 8px;
|
||||
|
||||
-webkit-flex: 1;
|
||||
flex: 1;
|
||||
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
}
|
||||
|
||||
.mx_MemberList_chevron {
|
||||
position: absolute;
|
||||
right: 35px;
|
||||
margin-top: -15px;
|
||||
}
|
||||
|
||||
.mx_MemberList_border {
|
||||
border: 1px solid #a9dbf4;
|
||||
overflow-y: auto;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
|
||||
order: 1;
|
||||
-webkit-flex: 1 1 0;
|
||||
flex: 1 1 0px;
|
||||
}
|
||||
|
||||
.mx_MemberList_wrapper {
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mx_MemberList h2 {
|
||||
margin: 14px;
|
||||
}
|
||||
@@ -14,69 +14,54 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_RoomView {
|
||||
word-wrap: break-word;
|
||||
.mx_RightPanel {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_RoomView .mx_RoomHeader {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.mx_RoomView_roomWrapper {
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 32px;
|
||||
bottom: 0px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
}
|
||||
|
||||
.mx_RoomView_messagePanel {
|
||||
.mx_RightPanel_header {
|
||||
-webkit-box-ordinal-group: 1;
|
||||
-moz-box-ordinal-group: 1;
|
||||
-ms-flex-order: 1;
|
||||
-webkit-order: 1;
|
||||
order: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* background-color: #ff0; */
|
||||
|
||||
-webkit-flex: 0 0 66px;
|
||||
flex: 0 0 66px;
|
||||
}
|
||||
|
||||
.mx_RoomView_messageListWrapper {
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
/** Fixme - factor this out with the main header **/
|
||||
|
||||
.mx_RightPanel_headerButtonGroup {
|
||||
margin-top: 18px;
|
||||
height: 48px;
|
||||
float: right;
|
||||
background-color: #fff;
|
||||
border-radius: 48px;
|
||||
border: 1px solid #a9dbf4;
|
||||
margin-right: 22px;
|
||||
}
|
||||
|
||||
.mx_RoomView_MessageList {
|
||||
display: table;
|
||||
.mx_RightPanel_headerButton {
|
||||
cursor: pointer;
|
||||
height: 48px;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.mx_RoomView_invitePrompt {
|
||||
}
|
||||
|
||||
.mx_RoomView .mx_MemberList {
|
||||
.mx_RightPanel .mx_MemberList {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-moz-box-ordinal-group: 2;
|
||||
-ms-flex-order: 2;
|
||||
-webkit-order: 2;
|
||||
order: 2;
|
||||
|
||||
/* background-color: #0f0; */
|
||||
width: 250px;
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mx_RoomView .mx_MemberList ul {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.mx_RoomView .mx_MessageComposer {
|
||||
width: 100%;
|
||||
bottom: 0px;
|
||||
}
|
||||
99
src/skins/vector/css/organisms/RoomDirectory.css
Normal file
99
src/skins/vector/css/organisms/RoomDirectory.css
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_RoomDirectory {
|
||||
width: 720px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 12px;
|
||||
color: #4a4a4a;
|
||||
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_list {
|
||||
-webkit-flex: 1;
|
||||
flex: 1;
|
||||
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_input {
|
||||
margin: auto;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #c7c7c7;
|
||||
font-weight: 300;
|
||||
font-size: 14px;
|
||||
padding: 9px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_tableWrapper {
|
||||
overflow-y: auto;
|
||||
-webkit-flex: 1 1 0;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_table {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_table th {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_table tbody {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_table td {
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_table .mx_RoomDirectory_name {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_table .mx_RoomDirectory_topic {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_table td,
|
||||
.mx_RoomDirectory_table th, {
|
||||
padding: 6px;
|
||||
}
|
||||
@@ -14,7 +14,18 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MessageComposer textarea {
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
.mx_RoomList {
|
||||
}
|
||||
|
||||
.mx_RoomList_recents {
|
||||
margin-top: -12px;
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mx_RoomList h2 {
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
255
src/skins/vector/css/organisms/RoomView.css
Normal file
255
src/skins/vector/css/organisms/RoomView.css
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
.mx_RoomView {
|
||||
word-wrap: break-word;
|
||||
position: relative;
|
||||
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
}
|
||||
|
||||
.mx_RoomView .mx_RoomHeader {
|
||||
-webkit-box-ordinal-group: 1;
|
||||
-moz-box-ordinal-group: 1;
|
||||
-ms-flex-order: 1;
|
||||
-webkit-order: 1;
|
||||
order: 1;
|
||||
|
||||
-webkit-flex: 0 0 88px;
|
||||
flex: 0 0 88px;
|
||||
}
|
||||
|
||||
.mx_RoomView_fileDropTarget {
|
||||
min-width: 0px;
|
||||
max-width: 720px;
|
||||
width: 100%;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
margin-left: -12px;
|
||||
|
||||
-webkit-border-top-left-radius: 10px;
|
||||
-webkit-border-top-right-radius: 10px;
|
||||
-moz-border-radius-topleft: 10px;
|
||||
-moz-border-radius-topright: 10px;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
border: 2px dashed #80cef4;
|
||||
border-bottom: none;
|
||||
position: absolute;
|
||||
top: 88px;
|
||||
bottom: 0px;
|
||||
z-index: 3000;
|
||||
}
|
||||
|
||||
.mx_RoomView_fileDropTargetLabel {
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
margin-top: -50px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.mx_RoomView_auxPanel {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-moz-box-ordinal-group: 2;
|
||||
-ms-flex-order: 2;
|
||||
-webkit-order: 2;
|
||||
order: 2;
|
||||
|
||||
min-width: 0px;
|
||||
max-width: 720px;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
|
||||
overflow: auto;
|
||||
border-bottom: 1px solid #a8dbf3;
|
||||
|
||||
-webkit-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.mx_RoomView_messagePanel {
|
||||
-webkit-box-ordinal-group: 3;
|
||||
-moz-box-ordinal-group: 3;
|
||||
-ms-flex-order: 3;
|
||||
-webkit-order: 3;
|
||||
order: 3;
|
||||
|
||||
-webkit-flex: 1 1 0;
|
||||
flex: 1 1 0;
|
||||
|
||||
width: 100%;
|
||||
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mx_RoomView_messageListWrapper {
|
||||
max-width: 720px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.mx_RoomView_MessageList {
|
||||
width: 100%;
|
||||
list-style-type: none;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.mx_RoomView_MessageList li {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.mx_RoomView_MessageList h2 {
|
||||
clear: both;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px solid #a8dbf3;
|
||||
}
|
||||
|
||||
.mx_RoomView_invitePrompt {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-moz-box-ordinal-group: 2;
|
||||
-ms-flex-order: 2;
|
||||
-webkit-order: 2;
|
||||
order: 2;
|
||||
|
||||
min-width: 0px;
|
||||
max-width: 720px;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.mx_RoomView_statusArea {
|
||||
-webkit-box-ordinal-group: 4;
|
||||
-moz-box-ordinal-group: 4;
|
||||
-ms-flex-order: 4;
|
||||
-webkit-order: 4;
|
||||
order: 4;
|
||||
|
||||
width: 100%;
|
||||
-webkit-flex: 0 0 58px;
|
||||
flex: 0 0 58px;
|
||||
}
|
||||
|
||||
.mx_RoomView_statusAreaBox {
|
||||
max-width: 720px;
|
||||
margin: auto;
|
||||
border-top: 1px solid #a8dbf3;
|
||||
}
|
||||
|
||||
.mx_RoomView_unreadMessagesBar {
|
||||
margin-top: 13px;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
background-color: #ff0064;
|
||||
border-radius: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomView_unreadMessagesBar img {
|
||||
padding-left: 22px;
|
||||
padding-right: 22px;
|
||||
}
|
||||
|
||||
.mx_RoomView_typingBar {
|
||||
margin-top: 17px;
|
||||
margin-left: 56px;
|
||||
color: #818794;
|
||||
}
|
||||
|
||||
.mx_RoomView_typingBar img {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
margin-left: -64px;
|
||||
margin-top: -7px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.mx_RoomView .mx_MessageComposer {
|
||||
-webkit-box-ordinal-group: 5;
|
||||
-moz-box-ordinal-group: 5;
|
||||
-ms-flex-order: 5;
|
||||
-webkit-order: 5;
|
||||
order: 5;
|
||||
|
||||
width: 100%;
|
||||
-webkit-flex: 0 0 63px;
|
||||
flex: 0 0 63px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.mx_RoomView_uploadProgressOuter {
|
||||
width: 100%;
|
||||
background-color: rgba(169, 219, 244, 0.5);
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
.mx_RoomView_uploadProgressInner {
|
||||
background-color: #80cef4;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
.mx_RoomView_uploadFilename {
|
||||
margin-top: 15px;
|
||||
margin-left: 56px;
|
||||
}
|
||||
|
||||
.mx_RoomView_uploadIcon {
|
||||
float: left;
|
||||
margin-top: 6px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.mx_RoomView_uploadCancel {
|
||||
float: right;
|
||||
margin-top: 6px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.mx_RoomView_uploadBytes {
|
||||
float: right;
|
||||
opacity: 0.5;
|
||||
margin-top: 15px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.mx_RoomView_ongoingConfCallNotification {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
background-color: #ff0064;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
padding: 6px;
|
||||
}
|
||||
@@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_RoomHeader {
|
||||
height: 1em;
|
||||
padding: 0px;
|
||||
.mx_UserSettings {
|
||||
width: 720px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user