Compare commits
432 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59fe9279d1 | ||
|
|
046c9ef920 | ||
|
|
bca22f26c5 | ||
|
|
2b68b88b14 | ||
|
|
97cedfc712 | ||
|
|
86cb3e9376 | ||
|
|
42993a78ed | ||
|
|
2a5ca9d3df | ||
|
|
323bd79d0e | ||
|
|
60adbffacf | ||
|
|
f827a2963e | ||
|
|
5e293c0f45 | ||
|
|
cd7adfed0a | ||
|
|
902bf3a0a6 | ||
|
|
f736e5243c | ||
|
|
fb2c2ed09a | ||
|
|
ea38968be9 | ||
|
|
562b047362 | ||
|
|
381c9009fb | ||
|
|
c0a4574069 | ||
|
|
de9bf4bb47 | ||
|
|
c57bfccb9e | ||
|
|
52cae92dd7 | ||
|
|
b80b08f04f | ||
|
|
304e5b997a | ||
|
|
6b4dbfbd62 | ||
|
|
000ca35727 | ||
|
|
776fe2ad70 | ||
|
|
602727b7ad | ||
|
|
56deea9f10 | ||
|
|
8e0be29c13 | ||
|
|
b71b1b5535 | ||
|
|
5b3524f174 | ||
|
|
f9a70a8b04 | ||
|
|
b652ea5024 | ||
|
|
2a37a0cb19 | ||
|
|
761600f325 | ||
|
|
65f14c7d21 | ||
|
|
864ba52bc5 | ||
|
|
fdb5020c0c | ||
|
|
62344b5194 | ||
|
|
0db12fcd22 | ||
|
|
455ee4f91b | ||
|
|
5ca391f914 | ||
|
|
a32abae5a3 | ||
|
|
b2dd3ecf3a | ||
|
|
cc7017b62d | ||
|
|
f852e8a01d | ||
|
|
6ff1c30a4b | ||
|
|
85ea45a64a | ||
|
|
7b258bc229 | ||
|
|
5ba3499f56 | ||
|
|
f4a6a3c4b2 | ||
|
|
5967dc4983 | ||
|
|
bf58c340bc | ||
|
|
dc0b15bdfa | ||
|
|
be6fbc2432 | ||
|
|
51a5542446 | ||
|
|
3938abc5dd | ||
|
|
4961a97ed4 | ||
|
|
fb477fad1e | ||
|
|
a070bccffb | ||
|
|
8e1105b12a | ||
|
|
93e4a04118 | ||
|
|
6e3313b461 | ||
|
|
2e77b0a3c7 | ||
|
|
16c22e07b8 | ||
|
|
99b0f9eb7c | ||
|
|
5248bdd974 | ||
|
|
157ae836c0 | ||
|
|
2639d10f97 | ||
|
|
cc5c636fa5 | ||
|
|
c4a2df75eb | ||
|
|
06c4cae016 | ||
|
|
3eed711b34 | ||
|
|
d9c51832ab | ||
|
|
5011d3b158 | ||
|
|
c10b11a22c | ||
|
|
a5ee48d857 | ||
|
|
343fc1b164 | ||
|
|
55fde43d5d | ||
|
|
940eaf2b7d | ||
|
|
855ecbe11d | ||
|
|
fc8f3eb0ee | ||
|
|
df90921d6c | ||
|
|
0f2c41dddc | ||
|
|
1c76870dcf | ||
|
|
a99c9f4db2 | ||
|
|
7e5373e194 | ||
|
|
560174b99f | ||
|
|
d2947a637a | ||
|
|
8e4dcd9b41 | ||
|
|
9391dc6c2a | ||
|
|
f19044fef2 | ||
|
|
60179aab52 | ||
|
|
de38a32969 | ||
|
|
5f6cc9b37b | ||
|
|
e2fc2b1b09 | ||
|
|
1d97272874 | ||
|
|
69da6a6dd8 | ||
|
|
6cb7ffcd3b | ||
|
|
0ab1dacb1e | ||
|
|
af230b5fa8 | ||
|
|
4720da3f8e | ||
|
|
e2b3fc3519 | ||
|
|
ab3c1509c5 | ||
|
|
91dd029483 | ||
|
|
53fd3f52fa | ||
|
|
d0618c4f49 | ||
|
|
0bce7f3102 | ||
|
|
3d97061d78 | ||
|
|
50f05db29e | ||
|
|
2fdec51a5b | ||
|
|
6d332256b5 | ||
|
|
2b6fbb038a | ||
|
|
48fb578952 | ||
|
|
7fc4b1cb35 | ||
|
|
4725fa4c2d | ||
|
|
5acb6b0b37 | ||
|
|
838608afab | ||
|
|
a11516a984 | ||
|
|
196b352b9a | ||
|
|
e8a12e7ddc | ||
|
|
135c22c99d | ||
|
|
6a13155013 | ||
|
|
6e2a371017 | ||
|
|
de26d1a8ce | ||
|
|
7af765976b | ||
|
|
8f6d98886c | ||
|
|
72e108c4f9 | ||
|
|
e2b695827e | ||
|
|
4b50a8a56e | ||
|
|
737d1d8843 | ||
|
|
eea9e366b8 | ||
|
|
24d0b95cb2 | ||
|
|
77085882fa | ||
|
|
9375ebfb75 | ||
|
|
e2f94c8722 | ||
|
|
b0fd65f442 | ||
|
|
f56a6039e8 | ||
|
|
c44994c0ee | ||
|
|
eeb91374cf | ||
|
|
cd4564d3d3 | ||
|
|
190cd884b5 | ||
|
|
1741cc915e | ||
|
|
37fc73b1ea | ||
|
|
c1e83da35d | ||
|
|
5282796d84 | ||
|
|
866164c4d9 | ||
|
|
5ceb1e641f | ||
|
|
f3cbb9fe90 | ||
|
|
fe4371bf45 | ||
|
|
cde3f33db3 | ||
|
|
82e257b4ea | ||
|
|
3907da064e | ||
|
|
f43530e1ef | ||
|
|
f6fb1561d7 | ||
|
|
a1e3ec1d19 | ||
|
|
43b87e1f82 | ||
|
|
2a85b2271c | ||
|
|
cb2c2c1b36 | ||
|
|
c5a52d89be | ||
|
|
efa574c452 | ||
|
|
66ef5213b8 | ||
|
|
370612135f | ||
|
|
ec05d1b9bd | ||
|
|
089951012b | ||
|
|
c6a9614372 | ||
|
|
a623430c2b | ||
|
|
b247c8a87f | ||
|
|
56606c01a0 | ||
|
|
eb2a55445c | ||
|
|
3fe8b503e5 | ||
|
|
bdee2d3b28 | ||
|
|
15ee2578c5 | ||
|
|
f8c9a28194 | ||
|
|
768f11fe58 | ||
|
|
acdcb21830 | ||
|
|
1530568354 | ||
|
|
7b25f4e069 | ||
|
|
cbab2c142b | ||
|
|
81bbc05028 | ||
|
|
f59dbe40ec | ||
|
|
562c3b0e04 | ||
|
|
f119a57952 | ||
|
|
c6fa1e2e21 | ||
|
|
0bdc026b05 | ||
|
|
20eb28f052 | ||
|
|
bfd3ef0e44 | ||
|
|
abda8c77ad | ||
|
|
9e5d090ddb | ||
|
|
906be376c9 | ||
|
|
695930efa5 | ||
|
|
7f2c74e7a8 | ||
|
|
f299572dc7 | ||
|
|
d65b791b2b | ||
|
|
2bf177dbcc | ||
|
|
5775552bab | ||
|
|
dd4617a7c6 | ||
|
|
64dedef2c7 | ||
|
|
89f8ff4988 | ||
|
|
3a8c94de5a | ||
|
|
dd39813cc2 | ||
|
|
e6c4273404 | ||
|
|
e1c32536ff | ||
|
|
013f68519e | ||
|
|
ab9786cc02 | ||
|
|
57804f4e02 | ||
|
|
c4421f6bc7 | ||
|
|
965d9aaf47 | ||
|
|
2476f87e1d | ||
|
|
cd36800426 | ||
|
|
18eb9d9330 | ||
|
|
7e379e9877 | ||
|
|
f2ca249b44 | ||
|
|
09ce3a79ec | ||
|
|
bfa59c6c04 | ||
|
|
e75148e799 | ||
|
|
8376f0d75a | ||
|
|
bf02a21c7d | ||
|
|
ac365622b8 | ||
|
|
7cb48e0d2d | ||
|
|
38ac520e1e | ||
|
|
6182ce48c9 | ||
|
|
9e771ddd07 | ||
|
|
74aef1fdad | ||
|
|
8860c9c7fd | ||
|
|
a8d7d23dd6 | ||
|
|
f5ce053f42 | ||
|
|
d833c7632d | ||
|
|
22bf6e7969 | ||
|
|
a1f8116e3b | ||
|
|
1d32dd72ed | ||
|
|
a3b77475c7 | ||
|
|
761552430c | ||
|
|
cc720b9797 | ||
|
|
75c81b369f | ||
|
|
7c74b0124b | ||
|
|
48501d91d2 | ||
|
|
aefef2ba56 | ||
|
|
31dd49ffd7 | ||
|
|
ace0e01d86 | ||
|
|
c0ce7663a9 | ||
|
|
e3d5ca34c8 | ||
|
|
1fb53565ef | ||
|
|
a41a8d32b8 | ||
|
|
835d13c696 | ||
|
|
6153e795bf | ||
|
|
d12498f418 | ||
|
|
c0eb69963d | ||
|
|
1f19ee88c6 | ||
|
|
24351537d2 | ||
|
|
d309a7a67b | ||
|
|
f6f68bc348 | ||
|
|
d6a324ede7 | ||
|
|
7378904f00 | ||
|
|
059f5198e5 | ||
|
|
2acbad36a6 | ||
|
|
519dd16135 | ||
|
|
fb103cb9e1 | ||
|
|
5e9a95fdfe | ||
|
|
b8610ab466 | ||
|
|
ee3fdbee5b | ||
|
|
2d827a75a6 | ||
|
|
50bb4edd1c | ||
|
|
e52f5b5d08 | ||
|
|
fd81ce126b | ||
|
|
7ae821e2b5 | ||
|
|
cb98e2421e | ||
|
|
5417385c83 | ||
|
|
c2d8067523 | ||
|
|
52bd61a2f0 | ||
|
|
aee56a5bd1 | ||
|
|
7f52fa74a4 | ||
|
|
d1dd4bd3d8 | ||
|
|
ab9f48cd47 | ||
|
|
c597f05e71 | ||
|
|
80e6cd6d7c | ||
|
|
cb101b0a3b | ||
|
|
bf4e3364b4 | ||
|
|
0494dff545 | ||
|
|
d5865421bd | ||
|
|
8578203073 | ||
|
|
e63e6e7016 | ||
|
|
dec62ab92c | ||
|
|
67d38bfab8 | ||
|
|
d2e2c726eb | ||
|
|
00d53e4824 | ||
|
|
4ce80a0837 | ||
|
|
9aa59fa358 | ||
|
|
6c8a492637 | ||
|
|
9709a38250 | ||
|
|
06ca94c1e6 | ||
|
|
67255e3f84 | ||
|
|
a20962ac14 | ||
|
|
b4cf86a362 | ||
|
|
bf8d7050cc | ||
|
|
49e5fa41ad | ||
|
|
e069d808f8 | ||
|
|
e85674711c | ||
|
|
7a89328ccb | ||
|
|
e77e6c2af0 | ||
|
|
ad26631874 | ||
|
|
cc75eb8b0e | ||
|
|
735da3c15e | ||
|
|
56dfdbeb6b | ||
|
|
eaf47ea05c | ||
|
|
37c46cf02f | ||
|
|
9d72a7cb35 | ||
|
|
a047f81b84 | ||
|
|
a2694113d3 | ||
|
|
0aae88d753 | ||
|
|
c7eba0f292 | ||
|
|
1bc1fc7e55 | ||
|
|
b91a0dd7a5 | ||
|
|
45a813b795 | ||
|
|
7b7a77bad0 | ||
|
|
ff3ad47be7 | ||
|
|
f2e8607433 | ||
|
|
b96ab58eb3 | ||
|
|
5f233d75f2 | ||
|
|
eb88245fe7 | ||
|
|
45c013f2f2 | ||
|
|
05f8b49eec | ||
|
|
ef8f9ecbf3 | ||
|
|
93fff53e29 | ||
|
|
4ae424f37a | ||
|
|
36a608952d | ||
|
|
900b4b4cf8 | ||
|
|
b782e7b9ad | ||
|
|
8d4268754e | ||
|
|
9b8e127e23 | ||
|
|
88dba1bf6c | ||
|
|
8d7daf61b9 | ||
|
|
ee1fae8ced | ||
|
|
13983900c0 | ||
|
|
881739b478 | ||
|
|
e06caa9ca1 | ||
|
|
efc5462131 | ||
|
|
2199fe5cbf | ||
|
|
30f774cf9c | ||
|
|
be9aa44ca8 | ||
|
|
dc4459083f | ||
|
|
2f375e4f67 | ||
|
|
879c325b83 | ||
|
|
7ad3f4a577 | ||
|
|
5b9d3b119f | ||
|
|
5467fd89d8 | ||
|
|
d2937c2aed | ||
|
|
a0236a9b76 | ||
|
|
c6d4eb7fd3 | ||
|
|
4cb1f8a226 | ||
|
|
abca5faf78 | ||
|
|
21ffe22375 | ||
|
|
64bbebb135 | ||
|
|
ebad3da6dd | ||
|
|
4633d16a6b | ||
|
|
df026aede2 | ||
|
|
d495a5b747 | ||
|
|
042a6b58c4 | ||
|
|
d87cf6c02b | ||
|
|
0c99c5563f | ||
|
|
3934e37f77 | ||
|
|
2ee4fa484e | ||
|
|
bc7948d75f | ||
|
|
5348b8a980 | ||
|
|
f2936dc15c | ||
|
|
864f9747f0 | ||
|
|
3ea62eb73a | ||
|
|
2fae966884 | ||
|
|
f888ec6e81 | ||
|
|
d2e8201d79 | ||
|
|
65d7d01dfa | ||
|
|
2cf2df20f6 | ||
|
|
1d1f89e0de | ||
|
|
ee73bc3aa4 | ||
|
|
d3fa680373 | ||
|
|
ef9d6d45b6 | ||
|
|
a980864886 | ||
|
|
ca4d506391 | ||
|
|
554c33a883 | ||
|
|
56813eb11e | ||
|
|
4d5e3bc22b | ||
|
|
ff55a951c9 | ||
|
|
895172d498 | ||
|
|
71f73d8df2 | ||
|
|
97daca4b31 | ||
|
|
e9eafc3380 | ||
|
|
600a1cae79 | ||
|
|
0b1fc1b925 | ||
|
|
bdaa9faea0 | ||
|
|
dbadb07adf | ||
|
|
4a2c899d05 | ||
|
|
85084f5fd7 | ||
|
|
78692c83a6 | ||
|
|
173e6011e8 | ||
|
|
9e542ba232 | ||
|
|
5005675561 | ||
|
|
29759ca71e | ||
|
|
be28a96d8d | ||
|
|
9b5e5c9acb | ||
|
|
fbbbd44dc3 | ||
|
|
0bb3eaaf67 | ||
|
|
e48d68a449 | ||
|
|
67175c5a72 | ||
|
|
6b0aeefc66 | ||
|
|
9a7f5388d9 | ||
|
|
d1649771cc | ||
|
|
08e5f61b10 | ||
|
|
012f085f33 | ||
|
|
9f570152e5 | ||
|
|
3099ef68a9 | ||
|
|
f0bac3a3b0 | ||
|
|
cd0ed879e3 | ||
|
|
95418089f3 | ||
|
|
650a0f1c1f | ||
|
|
757e885abc | ||
|
|
2c8e7782c5 | ||
|
|
d3eccc1d6f | ||
|
|
40aee5b03d | ||
|
|
4c9ade5ecb | ||
|
|
1d435890af | ||
|
|
8a2b2daad7 | ||
|
|
21334cab28 | ||
|
|
a17df609f3 | ||
|
|
0afdf5d8e4 | ||
|
|
17733a66f9 | ||
|
|
3a819a29b7 | ||
|
|
9d77fab18f | ||
|
|
3650c3f08b | ||
|
|
5512fd4220 | ||
|
|
678393e2bd |
6
.travis.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 6 # node v6, to match jenkins
|
||||
install:
|
||||
- npm install
|
||||
- (cd node_modules/matrix-react-sdk && npm run build)
|
||||
164
CHANGELOG.md
@@ -1,3 +1,167 @@
|
||||
Changes in [0.8.3](https://github.com/vector-im/vector-web/releases/tag/v0.8.3) (2016-10-12)
|
||||
============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.8.2...v0.8.3)
|
||||
|
||||
* Centre images in dialog buttons
|
||||
[\#2453](https://github.com/vector-im/vector-web/pull/2453)
|
||||
* Only show quote option if RTE is enabled
|
||||
[\#2448](https://github.com/vector-im/vector-web/pull/2448)
|
||||
* Fix join button for 'matrix' networks
|
||||
[\#2443](https://github.com/vector-im/vector-web/pull/2443)
|
||||
* Don't stop paginating if no rooms match
|
||||
[\#2422](https://github.com/vector-im/vector-web/pull/2422)
|
||||
|
||||
Changes in [0.8.2](https://github.com/vector-im/vector-web/releases/tag/v0.8.2) (2016-10-05)
|
||||
============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.8.1...v0.8.2)
|
||||
|
||||
* Add native joining of 3p networks to room dir
|
||||
[\#2379](https://github.com/vector-im/vector-web/pull/2379)
|
||||
* Update to linkify 2.1.3
|
||||
[\#2406](https://github.com/vector-im/vector-web/pull/2406)
|
||||
* Use 'Sign In' / 'Sign Out' universally
|
||||
[\#2383](https://github.com/vector-im/vector-web/pull/2383)
|
||||
* Prevent network dropdown resizing slightly
|
||||
[\#2382](https://github.com/vector-im/vector-web/pull/2382)
|
||||
* Room directory: indicate when there are no results
|
||||
[\#2380](https://github.com/vector-im/vector-web/pull/2380)
|
||||
* Room dir: New filtering & 3rd party networks
|
||||
[\#2362](https://github.com/vector-im/vector-web/pull/2362)
|
||||
* Update linkify version
|
||||
[\#2359](https://github.com/vector-im/vector-web/pull/2359)
|
||||
* Directory search join button
|
||||
[\#2339](https://github.com/vector-im/vector-web/pull/2339)
|
||||
|
||||
Changes in [0.8.1](https://github.com/vector-im/vector-web/releases/tag/v0.8.1) (2016-09-21)
|
||||
============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.8.0...v0.8.1)
|
||||
|
||||
|
||||
Changes in [0.8.0](https://github.com/vector-im/vector-web/releases/tag/v0.8.0) (2016-09-21)
|
||||
============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.7.5-r3...v0.8.0)
|
||||
|
||||
* Dbkr/rebrand
|
||||
[\#2285](https://github.com/vector-im/vector-web/pull/2285)
|
||||
* Listen for close_scalar and close the dialog box when received
|
||||
[\#2282](https://github.com/vector-im/vector-web/pull/2282)
|
||||
* Revert "improve lipstick and support scalar logout"
|
||||
[\#2281](https://github.com/vector-im/vector-web/pull/2281)
|
||||
* improve lipstick and support scalar logout
|
||||
[\#2280](https://github.com/vector-im/vector-web/pull/2280)
|
||||
* Fix changelog links
|
||||
[\#2071](https://github.com/vector-im/vector-web/pull/2071)
|
||||
* Paginate Room Directory
|
||||
[\#2241](https://github.com/vector-im/vector-web/pull/2241)
|
||||
* Make redeploy script symlink config
|
||||
[\#2240](https://github.com/vector-im/vector-web/pull/2240)
|
||||
* Update the version of olm to 1.3.0
|
||||
[\#2210](https://github.com/vector-im/vector-web/pull/2210)
|
||||
* Directory network selector
|
||||
[\#2219](https://github.com/vector-im/vector-web/pull/2219)
|
||||
* Wmwragg/two state sublist headers
|
||||
[\#2235](https://github.com/vector-im/vector-web/pull/2235)
|
||||
* Wmwragg/correct incoming call positioning
|
||||
[\#2222](https://github.com/vector-im/vector-web/pull/2222)
|
||||
* Wmwragg/remove old filter
|
||||
[\#2211](https://github.com/vector-im/vector-web/pull/2211)
|
||||
* Wmwragg/multi invite bugfix
|
||||
[\#2198](https://github.com/vector-im/vector-web/pull/2198)
|
||||
* Wmwragg/chat multi invite
|
||||
[\#2181](https://github.com/vector-im/vector-web/pull/2181)
|
||||
* shuffle bottomleftmenu around a bit
|
||||
[\#2182](https://github.com/vector-im/vector-web/pull/2182)
|
||||
* Improve autocomplete behaviour (styling)
|
||||
[\#2175](https://github.com/vector-im/vector-web/pull/2175)
|
||||
* First wave of E2E visuals
|
||||
[\#2163](https://github.com/vector-im/vector-web/pull/2163)
|
||||
* FilePanel and NotificationPanel support
|
||||
[\#2113](https://github.com/vector-im/vector-web/pull/2113)
|
||||
* Cursor: pointer on member info create room button
|
||||
[\#2151](https://github.com/vector-im/vector-web/pull/2151)
|
||||
* Support for adding DM rooms to the MemberInfo Panel
|
||||
[\#2147](https://github.com/vector-im/vector-web/pull/2147)
|
||||
* Wmwragg/one to one indicators
|
||||
[\#2139](https://github.com/vector-im/vector-web/pull/2139)
|
||||
* Added back the Directory listing button, with new tootlip
|
||||
[\#2136](https://github.com/vector-im/vector-web/pull/2136)
|
||||
* wmwragg/chat invite dialog fix
|
||||
[\#2134](https://github.com/vector-im/vector-web/pull/2134)
|
||||
* Wmwragg/one to one chat
|
||||
[\#2110](https://github.com/vector-im/vector-web/pull/2110)
|
||||
* Support toggling DM status of rooms
|
||||
[\#2111](https://github.com/vector-im/vector-web/pull/2111)
|
||||
* Formatting toolbar for RTE message composer.
|
||||
[\#2082](https://github.com/vector-im/vector-web/pull/2082)
|
||||
* jenkins.sh: install olm from jenkins artifacts
|
||||
[\#2092](https://github.com/vector-im/vector-web/pull/2092)
|
||||
* e2e device CSS
|
||||
[\#2085](https://github.com/vector-im/vector-web/pull/2085)
|
||||
* Bump to olm 1.1.0
|
||||
[\#2069](https://github.com/vector-im/vector-web/pull/2069)
|
||||
* Improve readability of the changelog dialog
|
||||
[\#2056](https://github.com/vector-im/vector-web/pull/2056)
|
||||
* Turn react consistency checks back on in develop builds
|
||||
[\#2009](https://github.com/vector-im/vector-web/pull/2009)
|
||||
* Wmwragg/direct chat sublist
|
||||
[\#2028](https://github.com/vector-im/vector-web/pull/2028)
|
||||
|
||||
Changes in [0.7.5-r3](https://github.com/vector-im/vector-web/releases/tag/v0.7.5-r3) (2016-09-02)
|
||||
==================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.7.5-r2...v0.7.5-r3)
|
||||
|
||||
* Bump to matrix-react-sdk 0.6.5-r3 in order to fix bug #2020 (tightloop when flooded with join events)
|
||||
|
||||
|
||||
Changes in [0.7.5-r2](https://github.com/vector-im/vector-web/releases/tag/v0.7.5-r2) (2016-09-01)
|
||||
==================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.7.5-r1...v0.7.5-r2)
|
||||
|
||||
* Bump to matrix-react-sdk 0.6.5-r1 in order to fix guest access
|
||||
|
||||
Changes in [0.7.5-r1](https://github.com/vector-im/vector-web/releases/tag/v0.7.5-r1) (2016-08-28)
|
||||
==================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.7.5...v0.7.5-r1)
|
||||
|
||||
* Correctly pin deps :(
|
||||
|
||||
Changes in [0.7.5](https://github.com/vector-im/vector-web/releases/tag/v0.7.5) (2016-08-28)
|
||||
============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.7.4-r1...v0.7.5)
|
||||
|
||||
* re-add leave button in RoomSettings
|
||||
* add /user URLs
|
||||
* recognise matrix.to links and other vector links
|
||||
* fix linkify dependency
|
||||
* fix avatar clicking in MemberInfo
|
||||
* fix RoomTagContextMenu so it works on historical rooms
|
||||
* warn people to put their Matrix HS on a separate domain to Vector
|
||||
* fix zalgos again
|
||||
* Add .travis.yml
|
||||
[\#2007](https://github.com/vector-im/vector-web/pull/2007)
|
||||
* add fancy changelog dialog
|
||||
[\#1972](https://github.com/vector-im/vector-web/pull/1972)
|
||||
* Update autocomplete design
|
||||
[\#1978](https://github.com/vector-im/vector-web/pull/1978)
|
||||
* Update encryption info in README
|
||||
[\#2001](https://github.com/vector-im/vector-web/pull/2001)
|
||||
* Added event/info message avatars back in
|
||||
[\#2000](https://github.com/vector-im/vector-web/pull/2000)
|
||||
* Wmwragg/chat message presentation
|
||||
[\#1987](https://github.com/vector-im/vector-web/pull/1987)
|
||||
* Make the notification slider work
|
||||
[\#1982](https://github.com/vector-im/vector-web/pull/1982)
|
||||
* Use cpx to copy olm.js, and add watcher
|
||||
[\#1966](https://github.com/vector-im/vector-web/pull/1966)
|
||||
* Make up a device display name
|
||||
[\#1959](https://github.com/vector-im/vector-web/pull/1959)
|
||||
|
||||
Changes in [0.7.4-r1](https://github.com/vector-im/vector-web/releases/tag/v0.7.4-r1) (2016-08-12)
|
||||
==================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.7.4...v0.7.4-r1)
|
||||
* Update to matrix-react-sdk 0.6.4-r1 to fix inviting multiple people
|
||||
|
||||
|
||||
Changes in [0.7.4](https://github.com/vector-im/vector-web/releases/tag/v0.7.4) (2016-08-11)
|
||||
============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/vector-web/compare/v0.7.3...v0.7.4)
|
||||
|
||||
72
README.md
@@ -8,7 +8,7 @@ Getting Started
|
||||
|
||||
The easiest way to test Vector is to just use the hosted copy at https://vector.im/beta.
|
||||
The develop branch is continuously deployed by Jenkins at https://vector.im/develop for
|
||||
those who like living dangerously.
|
||||
those who like living dangerously.
|
||||
|
||||
To host your own copy of Vector, the quickest bet is to use a pre-built released version
|
||||
of Vector:
|
||||
@@ -20,6 +20,19 @@ of Vector:
|
||||
as desired. See below for details.
|
||||
1. Enter the URL into your browser and log into vector!
|
||||
|
||||
Important Security Note
|
||||
=======================
|
||||
|
||||
We do not recommend running Vector from the same domain name as your Matrix
|
||||
homeserver. The reason is the risk of XSS (cross-site-scripting) vulnerabilities
|
||||
that could occur if someone caused Vector to load and render malicious user generated
|
||||
content from a Matrix API which then had trusted access to Vector (or other apps) due
|
||||
to sharing the same domain.
|
||||
|
||||
We have put some coarse mitigations into place to try to protect against this situation,
|
||||
but it's still not good practice to do it in the first place.
|
||||
See https://github.com/vector-im/vector-web/issues/1977 for more details.
|
||||
|
||||
Building From Source
|
||||
====================
|
||||
|
||||
@@ -55,11 +68,36 @@ You can configure the app by copying `vector/config.sample.json` to
|
||||
for verifying third party identifiers like email addresses). If this is blank,
|
||||
registering with an email address, adding an email address to your account,
|
||||
or inviting users via email address will not work. Matrix identity servers are
|
||||
very simple web services which map third party identifiers (currently only email
|
||||
very simple web services which map third party identifiers (currently only email
|
||||
addresses) to matrix IDs: see http://matrix.org/docs/spec/identity_service/unstable.html
|
||||
for more details. Currently the only public matrix identity servers are https://matrix.org
|
||||
and https://vector.im. In future identity servers will be decentralised.
|
||||
|
||||
1. `roomDirectory`: config for the public room directory. This section encodes behaviour
|
||||
on the room directory screen for filtering the list by server / network type and joining
|
||||
third party networks. This config section will disappear once APIs are available to
|
||||
get this information for home servers. This section is optional.
|
||||
1. `roomDirectory.servers`: List of other Home Servers' directories to include in the drop
|
||||
down list. Optional.
|
||||
1. `roomDirectory.serverConfig`: Config for each server in `roomDirectory.servers`. Optional.
|
||||
1. `roomDirectory.serverConfig.<server_name>.networks`: List of networks (named
|
||||
in `roomDirectory.networks`) to include for this server. Optional.
|
||||
1. `roomDirectory.networks`: config for each network type. Optional.
|
||||
1. `roomDirectory.<network_type>.name`: Human-readable name for the network. Required.
|
||||
1. `roomDirectory.<network_type>.protocol`: Protocol as given by the server in
|
||||
`/_matrix/client/unstable/thirdparty/protocols` response. Required to be able to join
|
||||
this type of third party network.
|
||||
1. `roomDirectory.<network_type>.domain`: Domain as given by the server in
|
||||
`/_matrix/client/unstable/thirdparty/protocols` response, if present. Required to be
|
||||
able to join this type of third party network, if present in `thirdparty/protocols`.
|
||||
1. `roomDirectory.<network_type>.portalRoomPattern`: Regular expression matching aliases
|
||||
for portal rooms to locations on this network. Required.
|
||||
1. `roomDirectory.<network_type>.icon`: URL to an icon to be displayed for this network. Required.
|
||||
1. `roomDirectory.<network_type>.example`: Textual example of a location on this network,
|
||||
eg. '#channel' for an IRC network. Optional.
|
||||
1. `roomDirectory.<network_type>.nativePattern`: Regular expression that matches a
|
||||
valid location on this network. This is used as a hint to the user to indicate
|
||||
when a valid location has been entered so it's not necessary for this to be
|
||||
exactly correct. Optional.
|
||||
|
||||
Running as a Desktop app
|
||||
========================
|
||||
@@ -75,7 +113,9 @@ nativefier https://vector.im/beta/
|
||||
```
|
||||
|
||||
krisa has a dedicated electron project at https://github.com/krisak/vector-electron-desktop
|
||||
(although you should swap out the 'vector' folder for the latest vector tarball you want to run)
|
||||
(although you should swap out the 'vector' folder for the latest vector tarball you want to run.
|
||||
Get a tarball from https://vector.im/packages or build your own - see Building From Source
|
||||
above).
|
||||
|
||||
There's also a (much) older electron distribution at https://github.com/stevenhammerton/vector-desktop
|
||||
|
||||
@@ -173,6 +213,10 @@ will watch for changes to the files and rebuild automatically.
|
||||
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`.
|
||||
|
||||
If any of these steps error with, `file table overflow`, you are probably on a mac
|
||||
which has a very low limit on max open files. Run `ulimit -Sn 1024` and try again.
|
||||
You'll need to do this in each new terminal you open before building vector.
|
||||
|
||||
Filing issues
|
||||
=============
|
||||
|
||||
@@ -212,20 +256,14 @@ day-to-day use; it is experimental and should be considered only as a
|
||||
proof-of-concept. See https://matrix.org/jira/browse/SPEC-162 for an overview
|
||||
of the current progress.
|
||||
|
||||
Vector is built with support for end-to-end encryption by default.
|
||||
|
||||
To enable encryption for a room, type
|
||||
|
||||
```
|
||||
/encrypt on
|
||||
```
|
||||
|
||||
in the message bar in that room. Vector will then generate a set of keys, and
|
||||
encrypt all outgoing messages in that room. (Note that other people in that
|
||||
room will send messages in the clear unless they also `/encrypt on`.)
|
||||
To enable the (very experimental) support, check the 'End-to-End Encryption'
|
||||
box in the 'Labs' section of the user settings (note that the labs are disabled
|
||||
on http://vector.im/beta: you will need to use http://vector.im/develop or your
|
||||
own deployment of vector). The Room Settings dialog will then show an
|
||||
'Encryption' setting; rooms for which you are an administrator will offer you
|
||||
the option of enabling encryption. Any messages sent in that room will then be
|
||||
encrypted.
|
||||
|
||||
Note that historical encrypted messages cannot currently be decoded - history
|
||||
is therefore lost when the page is reloaded.
|
||||
|
||||
There is currently no visual indication of whether encryption is enabled for a
|
||||
room.
|
||||
|
||||
@@ -5,8 +5,8 @@ from urlparse import urljoin
|
||||
from flask import Flask, jsonify, request, abort
|
||||
app = Flask(__name__)
|
||||
|
||||
arg_jenkins_url, arg_extract_path, arg_should_clean, arg_symlink = (
|
||||
None, None, None, None
|
||||
arg_jenkins_url, arg_extract_path, arg_should_clean, arg_symlink, arg_config_location = (
|
||||
None, None, None, None, None
|
||||
)
|
||||
|
||||
def download_file(url):
|
||||
@@ -122,6 +122,9 @@ def on_receive_jenkins_poke():
|
||||
|
||||
create_symlink(source=os.path.join(untar_location, "vector"), linkname=arg_symlink)
|
||||
|
||||
if arg_config_location:
|
||||
create_symlink(source=arg_config_location, linkname=os.path.join(untar_location, "vector", 'config.json'))
|
||||
|
||||
return jsonify({})
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -154,6 +157,12 @@ if __name__ == "__main__":
|
||||
to the /vector directory INSIDE the tarball."
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"--config", dest="config", help=(
|
||||
"Write a symlink to config.json in the extracted tarball. \
|
||||
To this location."
|
||||
)
|
||||
)
|
||||
args = parser.parse_args()
|
||||
if args.jenkins.endswith("/"): # important for urljoin
|
||||
arg_jenkins_url = args.jenkins
|
||||
@@ -162,9 +171,10 @@ if __name__ == "__main__":
|
||||
arg_extract_path = args.extract
|
||||
arg_should_clean = args.clean
|
||||
arg_symlink = args.symlink
|
||||
arg_config_location = args.config
|
||||
print(
|
||||
"Listening on port %s. Extracting to %s%s. Symlinking to %s. Jenkins URL: %s" %
|
||||
"Listening on port %s. Extracting to %s%s. Symlinking to %s. Jenkins URL: %s. Config location: %s" %
|
||||
(args.port, arg_extract_path,
|
||||
" (clean after)" if arg_should_clean else "", arg_symlink, arg_jenkins_url)
|
||||
" (clean after)" if arg_should_clean else "", arg_symlink, arg_jenkins_url, arg_config_location)
|
||||
)
|
||||
app.run(host="0.0.0.0", port=args.port, debug=True)
|
||||
|
||||
11
jenkins.sh
@@ -4,12 +4,21 @@ set -e
|
||||
|
||||
export NVM_DIR="/home/jenkins/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
||||
nvm use 4
|
||||
nvm use 6
|
||||
|
||||
set -x
|
||||
|
||||
npm install
|
||||
|
||||
# apparently npm 3.10.3 on node 6.4.0 doesn't upgrade #develop target with npm install unless explicitly asked.
|
||||
npm install matrix-react-sdk matrix-js-sdk
|
||||
|
||||
# install olm. A naive 'npm i ./olm/olm-*.tgz' fails because it uses the url
|
||||
# from our package.json (or even matrix-js-sdk's) in preference.
|
||||
tar -C olm -xz < olm/olm-*.tgz
|
||||
rm -r node_modules/olm
|
||||
cp -r olm/package node_modules/olm
|
||||
|
||||
# we may be using a dev branch of react-sdk, in which case we need to build it
|
||||
(cd node_modules/matrix-react-sdk && npm run build)
|
||||
|
||||
|
||||
25
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vector-web",
|
||||
"version": "0.7.4",
|
||||
"version": "0.8.3",
|
||||
"description": "Vector webapp",
|
||||
"author": "matrix.org",
|
||||
"repository": {
|
||||
@@ -17,8 +17,8 @@
|
||||
"build:css": "catw \"src/skins/vector/css/**/*.css\" -o vector/components.css --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:bundle:dev": "NODE_ENV=production webpack --optimize-occurence-order lib/vector/index.js vector/bundle.js",
|
||||
"build:staticfiles": "scripts/staticfiles.js",
|
||||
"build:bundle:dev": "webpack --optimize-occurence-order lib/vector/index.js vector/bundle.js",
|
||||
"build:staticfiles": "cpx -v node_modules/olm/olm.js vector/",
|
||||
"build": "npm run build:staticfiles && npm run build:emojione && npm run build:css && npm run build:compile && npm run build:bundle",
|
||||
"build:dev": "npm run build:staticfiles && npm run build:emojione && npm run build:css && npm run build:compile && npm run build:bundle:dev",
|
||||
"package": "scripts/package.sh",
|
||||
@@ -26,9 +26,10 @@
|
||||
"start:js": "webpack -w src/vector/index.js vector/bundle.js",
|
||||
"start:js:prod": "NODE_ENV=production webpack -w src/vector/index.js vector/bundle.js",
|
||||
"start:skins:css": "catw \"src/skins/vector/css/**/*.css\" -o vector/components.css",
|
||||
"start:staticfiles": "cpx -Lwv node_modules/olm/olm.js vector/",
|
||||
"//cache": "Note the -c 1 below due to https://code.google.com/p/chromium/issues/detail?id=508270",
|
||||
"start": "parallelshell \"npm run build:staticfiles\" \"npm run start:emojione\" \"npm run start:js\" \"npm run start:skins:css\" \"http-server -c 1 vector\"",
|
||||
"start:prod": "parallelshell \"npm run build:staticfiles\" \"npm run start:emojione\" \"npm run start:js:prod\" \"npm run start:skins:css\" \"http-server -c 1 vector\"",
|
||||
"start": "parallelshell \"npm run start:staticfiles\" \"npm run start:emojione\" \"npm run start:js\" \"npm run start:skins:css\" \"http-server -c 1 vector\"",
|
||||
"start:prod": "parallelshell \"npm run start:staticfiles\" \"npm run start:emojione\" \"npm run start:js:prod\" \"npm run start:skins:css\" \"http-server -c 1 vector\"",
|
||||
"clean": "rimraf lib vector/olm.js vector/bundle.css vector/bundle.js vector/bundle.js.map vector/webpack.css* vector/emojione",
|
||||
"prepublish": "npm run build:css && npm run build:compile",
|
||||
"test": "karma start --single-run=true --autoWatch=false --browsers PhantomJS --colors=false",
|
||||
@@ -38,16 +39,16 @@
|
||||
"babel-polyfill": "^6.5.0",
|
||||
"browser-request": "^0.3.3",
|
||||
"classnames": "^2.1.2",
|
||||
"draft-js": "^0.7.0",
|
||||
"draft-js": "^0.8.1",
|
||||
"extract-text-webpack-plugin": "^0.9.1",
|
||||
"filesize": "^3.1.2",
|
||||
"flux": "~2.0.3",
|
||||
"gemini-scrollbar": "matrix-org/gemini-scrollbar#b302279",
|
||||
"gfm.css": "^1.1.1",
|
||||
"highlight.js": "^9.0.0",
|
||||
"linkifyjs": "^2.0.0-beta.4",
|
||||
"matrix-js-sdk": "0.5.5",
|
||||
"matrix-react-sdk": "0.6.4",
|
||||
"linkifyjs": "^2.1.3",
|
||||
"matrix-js-sdk": "0.6.3",
|
||||
"matrix-react-sdk": "0.7.4",
|
||||
"modernizr": "^3.1.0",
|
||||
"q": "^1.4.1",
|
||||
"react": "^15.2.1",
|
||||
@@ -55,7 +56,9 @@
|
||||
"react-dnd-html5-backend": "^2.1.2",
|
||||
"react-dom": "^15.2.1",
|
||||
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef",
|
||||
"sanitize-html": "^1.11.1"
|
||||
"sanitize-html": "^1.11.1",
|
||||
"ua-parser-js": "^0.7.10",
|
||||
"url": "^0.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^5.8.23",
|
||||
@@ -87,6 +90,6 @@
|
||||
"webpack": "^1.12.14"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"olm": "https://matrix.org/packages/npm/olm/olm-1.0.0.tgz"
|
||||
"olm": "https://matrix.org/packages/npm/olm/olm-1.3.0.tgz"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// copy static files from node_modules to the vector directory
|
||||
//
|
||||
|
||||
var fs = require('fs-extra');
|
||||
|
||||
function exists(f) {
|
||||
try {
|
||||
fs.statSync(f);
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const olm = 'node_modules/olm/olm.js';
|
||||
if (exists(olm)) {
|
||||
console.log("copy", olm, "-> vector");
|
||||
fs.copySync(olm, 'vector/olm.js');
|
||||
}
|
||||
@@ -37,6 +37,8 @@ module.exports.components['structures.ViewSource'] = require('./components/struc
|
||||
module.exports.components['views.context_menus.MessageContextMenu'] = require('./components/views/context_menus/MessageContextMenu');
|
||||
module.exports.components['views.context_menus.NotificationStateContextMenu'] = require('./components/views/context_menus/NotificationStateContextMenu');
|
||||
module.exports.components['views.context_menus.RoomTagContextMenu'] = require('./components/views/context_menus/RoomTagContextMenu');
|
||||
module.exports.components['views.dialogs.ChangelogDialog'] = require('./components/views/dialogs/ChangelogDialog');
|
||||
module.exports.components['views.directory.NetworkDropdown'] = require('./components/views/directory/NetworkDropdown');
|
||||
module.exports.components['views.elements.ImageView'] = require('./components/views/elements/ImageView');
|
||||
module.exports.components['views.elements.Spinner'] = require('./components/views/elements/Spinner');
|
||||
module.exports.components['views.globals.GuestWarningBar'] = require('./components/views/globals/GuestWarningBar');
|
||||
@@ -47,8 +49,7 @@ module.exports.components['views.login.VectorLoginFooter'] = require('./componen
|
||||
module.exports.components['views.login.VectorLoginHeader'] = require('./components/views/login/VectorLoginHeader');
|
||||
module.exports.components['views.messages.DateSeparator'] = require('./components/views/messages/DateSeparator');
|
||||
module.exports.components['views.messages.MessageTimestamp'] = require('./components/views/messages/MessageTimestamp');
|
||||
module.exports.components['views.rooms.BottomLeftMenuTile'] = require('./components/views/rooms/BottomLeftMenuTile');
|
||||
module.exports.components['views.rooms.RoomDNDView'] = require('./components/views/rooms/RoomDNDView');
|
||||
module.exports.components['views.rooms.DNDRoomTile'] = require('./components/views/rooms/DNDRoomTile');
|
||||
module.exports.components['views.rooms.RoomDropTarget'] = require('./components/views/rooms/RoomDropTarget');
|
||||
module.exports.components['views.rooms.RoomTooltip'] = require('./components/views/rooms/RoomTooltip');
|
||||
module.exports.components['views.rooms.SearchBar'] = require('./components/views/rooms/SearchBar');
|
||||
|
||||
@@ -17,48 +17,105 @@ limitations under the License.
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'BottomLeftMenu',
|
||||
|
||||
propTypes: {
|
||||
collapsed: React.PropTypes.bool.isRequired,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return({
|
||||
directoryHover : false,
|
||||
roomsHover : false,
|
||||
peopleHover : false,
|
||||
settingsHover : false,
|
||||
});
|
||||
},
|
||||
|
||||
// Room events
|
||||
onDirectoryClick: function() {
|
||||
dis.dispatch({ action: 'view_room_directory' });
|
||||
},
|
||||
|
||||
onDirectoryMouseEnter: function() {
|
||||
this.setState({ directoryHover: true });
|
||||
},
|
||||
|
||||
onDirectoryMouseLeave: function() {
|
||||
this.setState({ directoryHover: false });
|
||||
},
|
||||
|
||||
onRoomsClick: function() {
|
||||
dis.dispatch({ action: 'view_create_room' });
|
||||
},
|
||||
|
||||
onRoomsMouseEnter: function() {
|
||||
this.setState({ roomsHover: true });
|
||||
},
|
||||
|
||||
onRoomsMouseLeave: function() {
|
||||
this.setState({ roomsHover: false });
|
||||
},
|
||||
|
||||
// People events
|
||||
onPeopleClick: function() {
|
||||
dis.dispatch({ action: 'view_create_chat' });
|
||||
},
|
||||
|
||||
onPeopleMouseEnter: function() {
|
||||
this.setState({ peopleHover: true });
|
||||
},
|
||||
|
||||
onPeopleMouseLeave: function() {
|
||||
this.setState({ peopleHover: false });
|
||||
},
|
||||
|
||||
// Settings events
|
||||
onSettingsClick: function() {
|
||||
dis.dispatch({action: 'view_user_settings'});
|
||||
dis.dispatch({ action: 'view_user_settings' });
|
||||
},
|
||||
|
||||
onRoomDirectoryClick: function() {
|
||||
dis.dispatch({action: 'view_room_directory'});
|
||||
onSettingsMouseEnter: function() {
|
||||
this.setState({ settingsHover: true });
|
||||
},
|
||||
|
||||
onCreateRoomClick: function() {
|
||||
dis.dispatch({action: 'view_create_room'});
|
||||
onSettingsMouseLeave: function() {
|
||||
this.setState({ settingsHover: false });
|
||||
},
|
||||
|
||||
getLabel: function(name) {
|
||||
if (!this.props.collapsed) {
|
||||
return <div className="mx_RoomTile_name">{name}</div>
|
||||
}
|
||||
else if (this.state.hover) {
|
||||
// Get the label/tooltip to show
|
||||
getLabel: function(label, show) {
|
||||
if (show) {
|
||||
var RoomTooltip = sdk.getComponent("rooms.RoomTooltip");
|
||||
return <RoomTooltip name={name}/>;
|
||||
return <RoomTooltip className="mx_BottomLeftMenu_tooltip" label={label} />;
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var BottomLeftMenuTile = sdk.getComponent('rooms.BottomLeftMenuTile');
|
||||
var TintableSvg = sdk.getComponent('elements.TintableSvg');
|
||||
return (
|
||||
<div className="mx_BottomLeftMenu">
|
||||
<div className="mx_BottomLeftMenu_options">
|
||||
<div className="mx_BottomLeftMenu_createRoom" title="Start chat" onClick={ this.onCreateRoomClick }>
|
||||
<TintableSvg src="img/icons-create-room.svg" width="25" height="25"/>
|
||||
<div className="mx_BottomLeftMenu_people" onClick={ this.onPeopleClick } onMouseEnter={ this.onPeopleMouseEnter } onMouseLeave={ this.onPeopleMouseLeave } >
|
||||
<TintableSvg src="img/icons-people.svg" width="25" height="25" />
|
||||
{ this.getLabel("Start chat", this.state.peopleHover) }
|
||||
</div>
|
||||
<div className="mx_BottomLeftMenu_directory" title="Room directory" onClick={ this.onRoomDirectoryClick }>
|
||||
<div className="mx_BottomLeftMenu_directory" onClick={ this.onDirectoryClick } onMouseEnter={ this.onDirectoryMouseEnter } onMouseLeave={ this.onDirectoryMouseLeave } >
|
||||
<TintableSvg src="img/icons-directory.svg" width="25" height="25"/>
|
||||
{ this.getLabel("Room directory", this.state.directoryHover) }
|
||||
</div>
|
||||
<div className="mx_BottomLeftMenu_settings" title="Settings" onClick={ this.onSettingsClick }>
|
||||
<TintableSvg src="img/icons-settings.svg" width="25" height="25"/>
|
||||
<div className="mx_BottomLeftMenu_createRoom" onClick={ this.onRoomsClick } onMouseEnter={ this.onRoomsMouseEnter } onMouseLeave={ this.onRoomsMouseLeave } >
|
||||
<TintableSvg src="img/icons-create-room.svg" width="25" height="25" />
|
||||
{ this.getLabel("Create new room", this.state.roomsHover) }
|
||||
</div>
|
||||
<div className="mx_BottomLeftMenu_settings" onClick={ this.onSettingsClick } onMouseEnter={ this.onSettingsMouseEnter } onMouseLeave={ this.onSettingsMouseLeave } >
|
||||
<TintableSvg src="img/icons-settings.svg" width="25" height="25" />
|
||||
{ this.getLabel("Settings", this.state.settingsHover) }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,9 +39,9 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div className="mx_CompatibilityPage">
|
||||
<div className="mx_CompatibilityPage_box">
|
||||
<p>Sorry, your browser is <b>not</b> able to run Vector.</p>
|
||||
<p>Sorry, your browser is <b>not</b> able to run Riot.</p>
|
||||
<p>
|
||||
Vector uses many advanced browser features, some of which are not
|
||||
Riot uses many advanced browser features, some of which are not
|
||||
available or experimental in your current browser.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
@@ -109,7 +109,7 @@ var LeftPanel = React.createClass({
|
||||
var CallView = sdk.getComponent('voip.CallView');
|
||||
callPreview = (
|
||||
<CallView
|
||||
className="mx_LeftPanel_callView" onClick={this.onCallViewClick}
|
||||
className="mx_LeftPanel_callView" showVoice={true} onClick={this.onCallViewClick}
|
||||
ConferenceHandler={VectorConferenceHandler} />
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,17 +17,26 @@ limitations under the License.
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var sdk = require('matrix-react-sdk');
|
||||
var Matrix = require("matrix-js-sdk");
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
var MatrixClientPeg = require("matrix-react-sdk/lib/MatrixClientPeg");
|
||||
var rate_limited_func = require('matrix-react-sdk/lib/ratelimitedfunc');
|
||||
var Modal = require('matrix-react-sdk/lib/Modal');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RightPanel',
|
||||
|
||||
propTypes: {
|
||||
userId: React.PropTypes.string, // if showing an orphaned MemberInfo page, this is set
|
||||
roomId: React.PropTypes.string, // if showing panels for a given room, this is set
|
||||
collapsed: React.PropTypes.bool, // currently unused property to request for a minimized view of the panel
|
||||
},
|
||||
|
||||
Phase : {
|
||||
MemberList: 'MemberList',
|
||||
FileList: 'FileList',
|
||||
FilePanel: 'FilePanel',
|
||||
NotificationPanel: 'NotificationPanel',
|
||||
MemberInfo: 'MemberInfo',
|
||||
},
|
||||
|
||||
@@ -45,13 +54,22 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
phase : this.Phase.MemberList
|
||||
if (this.props.userId) {
|
||||
var member = new Matrix.RoomMember(null, this.props.userId);
|
||||
return {
|
||||
phase: this.Phase.MemberInfo,
|
||||
member: member,
|
||||
}
|
||||
}
|
||||
else {
|
||||
return {
|
||||
phase: this.Phase.MemberList
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onMemberListButtonClick: function() {
|
||||
if (this.props.collapsed) {
|
||||
if (this.props.collapsed || this.state.phase !== this.Phase.MemberList) {
|
||||
this.setState({ phase: this.Phase.MemberList });
|
||||
dis.dispatch({
|
||||
action: 'show_right_panel',
|
||||
@@ -64,6 +82,51 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
onFileListButtonClick: function() {
|
||||
if (this.props.collapsed || this.state.phase !== this.Phase.FilePanel) {
|
||||
this.setState({ phase: this.Phase.FilePanel });
|
||||
dis.dispatch({
|
||||
action: 'show_right_panel',
|
||||
});
|
||||
}
|
||||
else {
|
||||
dis.dispatch({
|
||||
action: 'hide_right_panel',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onNotificationListButtonClick: function() {
|
||||
if (this.props.collapsed || this.state.phase !== this.Phase.NotificationPanel) {
|
||||
this.setState({ phase: this.Phase.NotificationPanel });
|
||||
dis.dispatch({
|
||||
action: 'show_right_panel',
|
||||
});
|
||||
}
|
||||
else {
|
||||
dis.dispatch({
|
||||
action: 'hide_right_panel',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onInviteButtonClick: function() {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
|
||||
Modal.createDialog(NeedToRegisterDialog, {
|
||||
title: "Please Register",
|
||||
description: "Guest users can't invite users. Please register to invite."
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// call ChatInviteDialog
|
||||
dis.dispatch({
|
||||
action: 'view_invite',
|
||||
roomId: this.props.roomId,
|
||||
});
|
||||
},
|
||||
|
||||
onRoomStateMember: function(ev, state, member) {
|
||||
// redraw the badge on the membership list
|
||||
if (this.state.phase == this.Phase.MemberList && member.roomId === this.props.roomId) {
|
||||
@@ -97,7 +160,7 @@ module.exports = React.createClass({
|
||||
});
|
||||
}
|
||||
}
|
||||
if (payload.action === "view_room") {
|
||||
else if (payload.action === "view_room") {
|
||||
if (this.state.phase === this.Phase.MemberInfo) {
|
||||
this.setState({
|
||||
phase: this.Phase.MemberList
|
||||
@@ -108,52 +171,86 @@ module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
var MemberList = sdk.getComponent('rooms.MemberList');
|
||||
var NotificationPanel = sdk.getComponent('structures.NotificationPanel');
|
||||
var FilePanel = sdk.getComponent('structures.FilePanel');
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
var buttonGroup;
|
||||
var inviteGroup;
|
||||
var panel;
|
||||
|
||||
var filesHighlight;
|
||||
var membersHighlight;
|
||||
var notificationsHighlight;
|
||||
if (!this.props.collapsed) {
|
||||
if (this.state.phase == this.Phase.MemberList || this.state.phase === this.Phase.MemberInfo) {
|
||||
membersHighlight = <div className="mx_RightPanel_headerButton_highlight"></div>;
|
||||
}
|
||||
else if (this.state.phase == this.Phase.FileList) {
|
||||
else if (this.state.phase == this.Phase.FilePanel) {
|
||||
filesHighlight = <div className="mx_RightPanel_headerButton_highlight"></div>;
|
||||
}
|
||||
else if (this.state.phase == this.Phase.NotificationPanel) {
|
||||
notificationsHighlight = <div className="mx_RightPanel_headerButton_highlight"></div>;
|
||||
}
|
||||
}
|
||||
|
||||
var membersBadge;
|
||||
if ((this.state.phase == this.Phase.MemberList || this.state.phase === this.Phase.MemberInfo) && this.props.roomId) {
|
||||
var cli = MatrixClientPeg.get();
|
||||
var room = cli.getRoom(this.props.roomId);
|
||||
var user_is_in_room;
|
||||
if (room) {
|
||||
membersBadge = <div className="mx_RightPanel_headerButton_badge">{ room.getJoinedMembers().length }</div>;
|
||||
membersBadge = room.getJoinedMembers().length;
|
||||
user_is_in_room = room.hasMembershipState(
|
||||
MatrixClientPeg.get().credentials.userId, 'join'
|
||||
);
|
||||
}
|
||||
|
||||
if (user_is_in_room) {
|
||||
inviteGroup =
|
||||
<div className="mx_RightPanel_invite" onClick={ this.onInviteButtonClick } >
|
||||
<div className="mx_RightPanel_icon" >
|
||||
<TintableSvg src="img/icon-invite-people.svg" width="35" height="35" />
|
||||
</div>
|
||||
<div className="mx_RightPanel_message">Invite to this room</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (this.props.roomId) {
|
||||
buttonGroup =
|
||||
<div className="mx_RightPanel_headerButtonGroup">
|
||||
<div className="mx_RightPanel_headerButton" title="Members" onClick={ this.onMemberListButtonClick }>
|
||||
{ membersBadge }
|
||||
<div className="mx_RightPanel_headerButton_badge">{ membersBadge ? membersBadge : <span> </span>}</div>
|
||||
<TintableSvg src="img/icons-people.svg" width="25" height="25"/>
|
||||
{ membersHighlight }
|
||||
</div>
|
||||
<div className="mx_RightPanel_headerButton mx_RightPanel_filebutton" title="Files">
|
||||
<TintableSvg src="img/files.svg" width="17" height="22"/>
|
||||
<div className="mx_RightPanel_headerButton mx_RightPanel_filebutton" title="Files" onClick={ this.onFileListButtonClick }>
|
||||
<div className="mx_RightPanel_headerButton_badge"> </div>
|
||||
<TintableSvg src="img/icons-files.svg" width="25" height="25"/>
|
||||
{ filesHighlight }
|
||||
</div>
|
||||
<div className="mx_RightPanel_headerButton mx_RightPanel_notificationbutton" title="Notifications" onClick={ this.onNotificationListButtonClick }>
|
||||
<div className="mx_RightPanel_headerButton_badge"> </div>
|
||||
<TintableSvg src="img/icons-notifications.svg" width="25" height="25"/>
|
||||
{ notificationsHighlight }
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
if (!this.props.collapsed) {
|
||||
if(this.state.phase == this.Phase.MemberList) {
|
||||
panel = <MemberList roomId={this.props.roomId} key={this.props.roomId} />
|
||||
}
|
||||
else if(this.state.phase == this.Phase.MemberInfo) {
|
||||
var MemberInfo = sdk.getComponent('rooms.MemberInfo');
|
||||
panel = <MemberInfo roomId={this.props.roomId} member={this.state.member} key={this.props.roomId} />
|
||||
}
|
||||
if (!this.props.collapsed) {
|
||||
if(this.props.roomId && this.state.phase == this.Phase.MemberList) {
|
||||
panel = <MemberList roomId={this.props.roomId} key={this.props.roomId} />
|
||||
}
|
||||
else if(this.state.phase == this.Phase.MemberInfo) {
|
||||
var MemberInfo = sdk.getComponent('rooms.MemberInfo');
|
||||
panel = <MemberInfo member={this.state.member} key={this.props.roomId || this.props.userId} />
|
||||
}
|
||||
else if (this.state.phase == this.Phase.NotificationPanel) {
|
||||
panel = <NotificationPanel />
|
||||
}
|
||||
else if (this.state.phase == this.Phase.FilePanel) {
|
||||
panel = <FilePanel roomId={this.props.roomId} />
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +270,7 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
{ panel }
|
||||
<div className="mx_RightPanel_footer">
|
||||
{ inviteGroup }
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
|
||||
@@ -29,21 +29,72 @@ var linkify = require('linkifyjs');
|
||||
var linkifyString = require('linkifyjs/string');
|
||||
var linkifyMatrix = require('matrix-react-sdk/lib/linkify-matrix');
|
||||
var sanitizeHtml = require('sanitize-html');
|
||||
var q = require('q');
|
||||
|
||||
linkifyMatrix(linkify);
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomDirectory',
|
||||
|
||||
propTypes: {
|
||||
config: React.PropTypes.object,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
config: {
|
||||
networks: [],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
publicRooms: [],
|
||||
roomAlias: '',
|
||||
loading: true,
|
||||
network: null,
|
||||
roomServer: null,
|
||||
filterString: null,
|
||||
}
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
// precompile Regexps
|
||||
this.portalRoomPatterns = {};
|
||||
this.nativePatterns = {};
|
||||
if (this.props.config.networks) {
|
||||
for (const network of Object.keys(this.props.config.networks)) {
|
||||
const network_info = this.props.config.networks[network];
|
||||
if (network_info.portalRoomPattern) {
|
||||
this.portalRoomPatterns[network] = new RegExp(network_info.portalRoomPattern);
|
||||
}
|
||||
if (network_info.nativePattern) {
|
||||
this.nativePatterns[network] = new RegExp(network_info.nativePattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.nextBatch = null;
|
||||
this.filterTimeout = null;
|
||||
this.scrollPanel = null;
|
||||
this.protocols = null;
|
||||
|
||||
MatrixClientPeg.get().getThirdpartyProtocols().done((response) => {
|
||||
this.protocols = response;
|
||||
}, (err) => {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
// Guests currently aren't allowed to use this API, so
|
||||
// ignore this as otherwise this error is literally the
|
||||
// thing you see when loading the client!
|
||||
return;
|
||||
}
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to get protocol list from Home Server",
|
||||
description: "The Home Server may be too old to support third party networks",
|
||||
});
|
||||
});
|
||||
|
||||
// dis.dispatch({
|
||||
// action: 'ui_opacity',
|
||||
// sideOpacity: 0.3,
|
||||
@@ -51,10 +102,6 @@ module.exports = React.createClass({
|
||||
// });
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.getPublicRooms();
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
// dis.dispatch({
|
||||
// action: 'ui_opacity',
|
||||
@@ -63,24 +110,65 @@ module.exports = React.createClass({
|
||||
// });
|
||||
},
|
||||
|
||||
getPublicRooms: function() {
|
||||
var self = this;
|
||||
MatrixClientPeg.get().publicRooms(function (err, data) {
|
||||
if (err) {
|
||||
self.setState({ loading: false });
|
||||
console.error("Failed to get publicRooms: %s", JSON.stringify(err));
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to get public room list",
|
||||
description: err.message
|
||||
});
|
||||
refreshRoomList: function() {
|
||||
this.nextBatch = null;
|
||||
this.setState({
|
||||
publicRooms: [],
|
||||
loading: true,
|
||||
});
|
||||
this.getMoreRooms().done();
|
||||
},
|
||||
|
||||
getMoreRooms: function() {
|
||||
if (!MatrixClientPeg.get()) return q();
|
||||
|
||||
const my_filter_string = this.state.filterString;
|
||||
const my_server = this.state.roomServer;
|
||||
// remember the next batch token when we sent the request
|
||||
// too. If it's changed, appending to the list will corrupt it.
|
||||
const my_next_batch = this.nextBatch;
|
||||
const opts = {limit: 20};
|
||||
if (my_server != MatrixClientPeg.getHomeServerName()) {
|
||||
opts.server = my_server;
|
||||
}
|
||||
if (this.nextBatch) opts.since = this.nextBatch;
|
||||
if (my_filter_string) opts.filter = { generic_search_term: my_filter_string } ;
|
||||
return MatrixClientPeg.get().publicRooms(opts).then((data) => {
|
||||
if (
|
||||
my_filter_string != this.state.filterString ||
|
||||
my_server != this.state.roomServer ||
|
||||
my_next_batch != this.nextBatch)
|
||||
{
|
||||
// if the filter or server has changed since this request was sent,
|
||||
// throw away the result (don't even clear the busy flag
|
||||
// since we must still have a request in flight)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
self.setState({
|
||||
publicRooms: data.chunk,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
this.nextBatch = data.next_batch;
|
||||
this.setState((s) => {
|
||||
s.publicRooms.push(...data.chunk);
|
||||
s.loading = false;
|
||||
return s;
|
||||
});
|
||||
return Boolean(data.next_batch);
|
||||
}, (err) => {
|
||||
if (
|
||||
my_filter_string != this.state.filterString ||
|
||||
my_server != this.state.roomServer ||
|
||||
my_next_batch != this.nextBatch)
|
||||
{
|
||||
// as above: we don't care about errors for old
|
||||
// requests either
|
||||
return;
|
||||
}
|
||||
this.setState({ loading: false });
|
||||
console.error("Failed to get publicRooms: %s", JSON.stringify(err));
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to get public room list",
|
||||
description: err.message
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -121,10 +209,10 @@ module.exports = React.createClass({
|
||||
return MatrixClientPeg.get().deleteAlias(alias);
|
||||
}).done(() => {
|
||||
modal.close();
|
||||
this.getPublicRooms();
|
||||
this.refreshRoomList();
|
||||
}, function(err) {
|
||||
modal.close();
|
||||
this.getPublicRooms();
|
||||
this.refreshRoomList();
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to "+step,
|
||||
description: err.toString()
|
||||
@@ -143,6 +231,98 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
onOptionChange: function(server, network) {
|
||||
// clear next batch so we don't try to load more rooms
|
||||
this.nextBatch = null;
|
||||
this.setState({
|
||||
// Clear the public rooms out here otherwise we needlessly
|
||||
// spend time filtering lots of rooms when we're about to
|
||||
// to clear the list anyway.
|
||||
publicRooms: [],
|
||||
roomServer: server,
|
||||
network: network,
|
||||
}, this.refreshRoomList);
|
||||
// We also refresh the room list each time even though this
|
||||
// filtering is client-side. It hopefully won't be client side
|
||||
// for very long, and we may have fetched a thousand rooms to
|
||||
// find the five gitter ones, at which point we do not want
|
||||
// to render all those rooms when switching back to 'all networks'.
|
||||
// Easiest to just blow away the state & re-fetch.
|
||||
},
|
||||
|
||||
onFillRequest: function(backwards) {
|
||||
if (backwards || !this.nextBatch) return q(false);
|
||||
|
||||
return this.getMoreRooms();
|
||||
},
|
||||
|
||||
onFilterChange: function(alias) {
|
||||
this.setState({
|
||||
filterString: alias || null,
|
||||
});
|
||||
|
||||
// don't send the request for a little bit,
|
||||
// no point hammering the server with a
|
||||
// request for every keystroke, let the
|
||||
// user finish typing.
|
||||
if (this.filterTimeout) {
|
||||
clearTimeout(this.filterTimeout);
|
||||
}
|
||||
this.filterTimeout = setTimeout(() => {
|
||||
this.filterTimeout = null;
|
||||
this.refreshRoomList();
|
||||
}, 300);
|
||||
},
|
||||
|
||||
onFilterClear: function() {
|
||||
// update immediately
|
||||
this.setState({
|
||||
filterString: null,
|
||||
}, this.refreshRoomList);
|
||||
|
||||
if (this.filterTimeout) {
|
||||
clearTimeout(this.filterTimeout);
|
||||
}
|
||||
},
|
||||
|
||||
onJoinClick: function(alias) {
|
||||
// If we're on the 'Matrix' network (or all networks),
|
||||
// just show that rooms alias
|
||||
if (this.state.network == null || this.state.network == '_matrix') {
|
||||
this.showRoomAlias(alias);
|
||||
} else {
|
||||
// This is a 3rd party protocol. Let's see if we
|
||||
// can join it
|
||||
const fields = this._getFieldsForThirdPartyLocation(alias, this.state.network);
|
||||
if (!fields) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Unable to join network",
|
||||
description: "Riot does not know how to join a room on this network",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const protocol = this._protocolForThirdPartyNetwork(this.state.network);
|
||||
MatrixClientPeg.get().getThirdpartyLocation(protocol, fields).done((resp) => {
|
||||
if (resp.length > 0 && resp[0].alias) {
|
||||
this.showRoomAlias(resp[0].alias);
|
||||
} else {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Room not found",
|
||||
description: "Couldn't find a matching Matrix room",
|
||||
});
|
||||
}
|
||||
}, (e) => {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Fetching third party location failed",
|
||||
description: "Unable to look up room ID from server",
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
showRoomAlias: function(alias) {
|
||||
this.showRoom(null, alias);
|
||||
},
|
||||
@@ -187,19 +367,17 @@ module.exports = React.createClass({
|
||||
dis.dispatch(payload);
|
||||
},
|
||||
|
||||
getRows: function(filter) {
|
||||
getRows: function() {
|
||||
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
|
||||
if (!this.state.publicRooms) return [];
|
||||
|
||||
var rooms = this.state.publicRooms.filter(function(a) {
|
||||
// FIXME: if incrementally typing, keep narrowing down the search set
|
||||
// incrementally rather than starting over each time.
|
||||
return (((a.name && a.name.toLowerCase().search(filter.toLowerCase()) >= 0) ||
|
||||
(a.aliases && a.aliases[0].toLowerCase().search(filter.toLowerCase()) >= 0)) &&
|
||||
a.num_joined_members > 0);
|
||||
}).sort(function(a,b) {
|
||||
return a.num_joined_members - b.num_joined_members;
|
||||
var rooms = this.state.publicRooms.filter((a) => {
|
||||
if (this.state.network) {
|
||||
if (!this._isRoomInNetwork(a, this.state.roomServer, this.state.network)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
var rows = [];
|
||||
var self = this;
|
||||
@@ -228,7 +406,7 @@ module.exports = React.createClass({
|
||||
var topic = rooms[i].topic || '';
|
||||
topic = linkifyString(sanitizeHtml(topic));
|
||||
|
||||
rows.unshift(
|
||||
rows.push(
|
||||
<tr key={ rooms[i].room_id }
|
||||
onClick={self.onRoomClicked.bind(self, rooms[i])}
|
||||
// cancel onMouseDown otherwise shift-clicking highlights text
|
||||
@@ -258,37 +436,188 @@ module.exports = React.createClass({
|
||||
return rows;
|
||||
},
|
||||
|
||||
onKeyUp: function(ev) {
|
||||
this.forceUpdate();
|
||||
this.setState({ roomAlias : this.refs.roomAlias.value })
|
||||
if (ev.key == "Enter") {
|
||||
this.showRoomAlias(this.refs.roomAlias.value);
|
||||
collectScrollPanel: function(element) {
|
||||
this.scrollPanel = element;
|
||||
},
|
||||
|
||||
/**
|
||||
* Terrible temporary function that guess what network a public room
|
||||
* entry is in, until synapse is able to tell us
|
||||
*/
|
||||
_isRoomInNetwork: function(room, server, network) {
|
||||
// We carve rooms into two categories here. 'portal' rooms are
|
||||
// rooms created by a user joining a bridge 'portal' alias to
|
||||
// participate in that room or a foreign network. A room is a
|
||||
// portal room if it has exactly one alias and that alias matches
|
||||
// a pattern defined in the config. Its network is the key
|
||||
// of the pattern that it matches.
|
||||
// All other rooms are considered 'native matrix' rooms, and
|
||||
// go into the special '_matrix' network.
|
||||
|
||||
let roomNetwork = '_matrix';
|
||||
if (room.aliases && room.aliases.length == 1) {
|
||||
if (this.props.config.serverConfig && this.props.config.serverConfig[server] && this.props.config.serverConfig[server].networks) {
|
||||
for (const n of this.props.config.serverConfig[server].networks) {
|
||||
const pat = this.portalRoomPatterns[n];
|
||||
if (pat && pat.test(room.aliases[0])) {
|
||||
roomNetwork = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return roomNetwork == network;
|
||||
},
|
||||
|
||||
_stringLooksLikeId: function(s, network) {
|
||||
let pat = /^#[^\s]+:[^\s]/;
|
||||
if (
|
||||
network && network != '_matrix' &&
|
||||
this.nativePatterns[network]
|
||||
) {
|
||||
pat = this.nativePatterns[network];
|
||||
}
|
||||
|
||||
return pat.test(s);
|
||||
},
|
||||
|
||||
_protocolForThirdPartyNetwork: function(network) {
|
||||
if (
|
||||
this.props.config.networks &&
|
||||
this.props.config.networks[network] &&
|
||||
this.props.config.networks[network].protocol
|
||||
) {
|
||||
return this.props.config.networks[network].protocol;
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (this.state.loading) {
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
return (
|
||||
<div className="mx_RoomDirectory">
|
||||
<Loader />
|
||||
</div>
|
||||
);
|
||||
_getFieldsForThirdPartyLocation: function(user_input, network) {
|
||||
if (!this.props.config.networks || !this.props.config.networks[network]) return null;
|
||||
|
||||
const network_info = this.props.config.networks[network];
|
||||
if (!network_info.protocol) return null;
|
||||
|
||||
if (!this.protocols) return null;
|
||||
|
||||
let matched_instance;
|
||||
// Try to find which instance in the 'protocols' response
|
||||
// matches this network. We look for a matching protocol
|
||||
// and the existence of a 'domain' field and if present,
|
||||
// its value.
|
||||
if (
|
||||
this.protocols[network_info.protocol] &&
|
||||
this.protocols[network_info.protocol].instances &&
|
||||
this.protocols[network_info.protocol].instances.length == 1
|
||||
) {
|
||||
const the_instance = this.protocols[network_info.protocol].instances[0];
|
||||
// If there's only one instance in this protocol, use it
|
||||
// as long as it has no domain (which we assume to mean it's
|
||||
// there is only one possible instance).
|
||||
if (
|
||||
(
|
||||
the_instance.fields.domain === undefined &&
|
||||
network_info.domain === undefined
|
||||
) ||
|
||||
(
|
||||
the_instance.fields.domain !== undefined &&
|
||||
the_instance.fields.domain == network_info.domain
|
||||
)
|
||||
) {
|
||||
matched_instance = the_instance;
|
||||
}
|
||||
} else if (network_info.domain) {
|
||||
// otherwise, we look for one with a matching domain.
|
||||
for (const this_instance of this.protocols[network_info.protocol].instances) {
|
||||
if (this_instance.fields.domain == network_info.domain) {
|
||||
matched_instance = this_instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
|
||||
if (matched_instance === undefined) return null;
|
||||
|
||||
// now make an object with the fields specified by that protocol. We
|
||||
// require that the values of all but the last field come from the
|
||||
// instance. The last is the user input.
|
||||
const required_fields = this.protocols[network_info.protocol].location_fields;
|
||||
const fields = {};
|
||||
for (let i = 0; i < required_fields.length - 1; ++i) {
|
||||
const this_field = required_fields[i];
|
||||
if (matched_instance.fields[this_field] === undefined) return null;
|
||||
fields[this_field] = matched_instance.fields[this_field];
|
||||
}
|
||||
fields[required_fields[required_fields.length - 1]] = user_input;
|
||||
return fields;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
let content;
|
||||
if (this.state.loading) {
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
content = <div className="mx_RoomDirectory">
|
||||
<Loader />
|
||||
</div>;
|
||||
} else {
|
||||
const rows = this.getRows();
|
||||
// we still show the scrollpanel, at least for now, because
|
||||
// otherwise we don't fetch more because we don't get a fill
|
||||
// request from the scrollpanel because there isn't one
|
||||
let scrollpanel_content;
|
||||
if (rows.length == 0) {
|
||||
scrollpanel_content = <i>No rooms to show</i>;
|
||||
} else {
|
||||
scrollpanel_content = <table ref="directory_table" className="mx_RoomDirectory_table">
|
||||
<tbody>
|
||||
{ this.getRows() }
|
||||
</tbody>
|
||||
</table>;
|
||||
}
|
||||
const ScrollPanel = sdk.getComponent("structures.ScrollPanel");
|
||||
content = <ScrollPanel ref={this.collectScrollPanel}
|
||||
className="mx_RoomDirectory_tableWrapper"
|
||||
onFillRequest={ this.onFillRequest }
|
||||
stickyBottom={false}
|
||||
startAtBottom={false}
|
||||
onResize={function(){}}
|
||||
>
|
||||
{ scrollpanel_content }
|
||||
</ScrollPanel>;
|
||||
}
|
||||
|
||||
let placeholder = 'Search for a room';
|
||||
if (this.state.network === null || this.state.network === '_matrix') {
|
||||
placeholder = '#example:' + this.state.roomServer;
|
||||
} else if (
|
||||
this.props.config.networks &&
|
||||
this.props.config.networks[this.state.network] &&
|
||||
this.props.config.networks[this.state.network].example &&
|
||||
this._getFieldsForThirdPartyLocation(this.state.filterString, this.state.network)
|
||||
) {
|
||||
placeholder = this.props.config.networks[this.state.network].example;
|
||||
}
|
||||
|
||||
let showJoinButton = this._stringLooksLikeId(this.state.filterString, this.state.network);
|
||||
if (this.state.network && this.state.network != '_matrix') {
|
||||
if (this._getFieldsForThirdPartyLocation(this.state.filterString, this.state.network) === null) {
|
||||
showJoinButton = false;
|
||||
}
|
||||
}
|
||||
|
||||
const SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
|
||||
const NetworkDropdown = sdk.getComponent('directory.NetworkDropdown');
|
||||
const DirectorySearchBox = sdk.getComponent('elements.DirectorySearchBox');
|
||||
return (
|
||||
<div className="mx_RoomDirectory">
|
||||
<SimpleRoomHeader title="Directory" />
|
||||
<div className="mx_RoomDirectory_list">
|
||||
<input ref="roomAlias" placeholder="Join a room (e.g. #foo:domain.com)" className="mx_RoomDirectory_input" size="64" onKeyUp={ this.onKeyUp }/>
|
||||
<GeminiScrollbar className="mx_RoomDirectory_tableWrapper">
|
||||
<table ref="directory_table" className="mx_RoomDirectory_table">
|
||||
<tbody>
|
||||
{ this.getRows(this.state.roomAlias) }
|
||||
</tbody>
|
||||
</table>
|
||||
</GeminiScrollbar>
|
||||
<div className="mx_RoomDirectory_listheader">
|
||||
<DirectorySearchBox
|
||||
className="mx_RoomDirectory_searchbox"
|
||||
onChange={this.onFilterChange} onClear={this.onFilterClear} onJoinClick={this.onJoinClick}
|
||||
placeholder={placeholder} showJoinButton={showJoinButton}
|
||||
/>
|
||||
<NetworkDropdown config={this.props.config} onOptionChange={this.onOptionChange} />
|
||||
</div>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,15 +17,21 @@ limitations under the License.
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var classNames = require('classnames');
|
||||
var DropTarget = require('react-dnd').DropTarget;
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
var Unread = require('matrix-react-sdk/lib/Unread');
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
var RoomNotifs = require('matrix-react-sdk/lib/RoomNotifs');
|
||||
var FormattingUtils = require('matrix-react-sdk/lib/utils/FormattingUtils');
|
||||
|
||||
// turn this on for drop & drag console debugging galore
|
||||
var debug = false;
|
||||
|
||||
const TRUNCATE_AT = 10;
|
||||
|
||||
var roomListTarget = {
|
||||
canDrop: function() {
|
||||
return true;
|
||||
@@ -80,7 +86,7 @@ var RoomSubList = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
hidden: this.props.startAsHidden || false,
|
||||
truncateAt: 20,
|
||||
truncateAt: TRUNCATE_AT,
|
||||
sortedList: [],
|
||||
};
|
||||
},
|
||||
@@ -109,17 +115,34 @@ var RoomSubList = React.createClass({
|
||||
});
|
||||
},
|
||||
|
||||
onClick: function(ev) {
|
||||
var isHidden = !this.state.hidden;
|
||||
this.setState({ hidden : isHidden });
|
||||
|
||||
if (isHidden) {
|
||||
// as good a way as any to reset the truncate state
|
||||
this.setState({ truncateAt : 20 });
|
||||
this.props.onShowMoreRooms();
|
||||
// The header is collapsable if it is hidden or not stuck
|
||||
// The dataset elements are added in the RoomList _initAndPositionStickyHeaders method
|
||||
isCollapsableOnClick: function() {
|
||||
var stuck = this.refs.header.dataset.stuck;
|
||||
if (this.state.hidden || stuck === undefined || stuck === "none") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
this.props.onHeaderClick(isHidden);
|
||||
onClick: function(ev) {
|
||||
if (this.isCollapsableOnClick()) {
|
||||
// The header isCollapsable, so the click is to be interpreted as collapse and truncation logic
|
||||
var isHidden = !this.state.hidden;
|
||||
this.setState({ hidden : isHidden });
|
||||
|
||||
if (isHidden) {
|
||||
// as good a way as any to reset the truncate state
|
||||
this.setState({ truncateAt : TRUNCATE_AT });
|
||||
}
|
||||
|
||||
this.props.onShowMoreRooms();
|
||||
this.props.onHeaderClick(isHidden);
|
||||
} else {
|
||||
// The header is stuck, so the click is to be interpreted as a scroll to the header
|
||||
this.props.onHeaderClick(this.state.hidden, this.refs.header.dataset.originalPosition);
|
||||
}
|
||||
},
|
||||
|
||||
tsOfNewestEvent: function(room) {
|
||||
@@ -186,6 +209,52 @@ var RoomSubList = React.createClass({
|
||||
this.setState({ sortedList: list.sort(comparator) });
|
||||
},
|
||||
|
||||
_shouldShowNotifBadge: function(roomNotifState) {
|
||||
const showBadgeInStates = [RoomNotifs.ALL_MESSAGES, RoomNotifs.ALL_MESSAGES_LOUD];
|
||||
return showBadgeInStates.indexOf(roomNotifState) > -1;
|
||||
},
|
||||
|
||||
_shouldShowMentionBadge: function(roomNotifState) {
|
||||
return roomNotifState != RoomNotifs.MUTE;
|
||||
},
|
||||
|
||||
/**
|
||||
* Total up all the notification counts from the rooms
|
||||
*
|
||||
* @param {Number} If supplied will only total notifications for rooms outside the truncation number
|
||||
* @returns {Array} The array takes the form [total, highlight] where highlight is a bool
|
||||
*/
|
||||
roomNotificationCount: function(truncateAt) {
|
||||
var self = this;
|
||||
|
||||
return this.props.list.reduce(function(result, room, index) {
|
||||
if (truncateAt === undefined || index >= truncateAt) {
|
||||
var roomNotifState = RoomNotifs.getRoomNotifsState(room.roomId);
|
||||
var highlight = room.getUnreadNotificationCount('highlight') > 0 || self.props.label === 'Invites';
|
||||
var notificationCount = room.getUnreadNotificationCount();
|
||||
|
||||
const notifBadges = notificationCount > 0 && self._shouldShowNotifBadge(roomNotifState);
|
||||
const mentionBadges = highlight && self._shouldShowMentionBadge(roomNotifState);
|
||||
const badges = notifBadges || mentionBadges;
|
||||
|
||||
if (badges) {
|
||||
result[0] += notificationCount;
|
||||
if (highlight) {
|
||||
result[1] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, [0, false]);
|
||||
},
|
||||
|
||||
_updateSubListCount: function() {
|
||||
// Force an update by setting the state to the current state
|
||||
// Doing it this way rather than using forceUpdate(), so that the shouldComponentUpdate()
|
||||
// method is honoured
|
||||
this.setState(this.state);
|
||||
},
|
||||
|
||||
moveRoomTile: function(room, atIndex) {
|
||||
if (debug) console.log("moveRoomTile: id " + room.roomId + ", atIndex " + atIndex);
|
||||
//console.log("moveRoomTile before: " + JSON.stringify(this.state.rooms));
|
||||
@@ -279,12 +348,12 @@ var RoomSubList = React.createClass({
|
||||
|
||||
makeRoomTiles: function() {
|
||||
var self = this;
|
||||
var RoomTile = sdk.getComponent("rooms.RoomTile");
|
||||
var DNDRoomTile = sdk.getComponent("rooms.DNDRoomTile");
|
||||
return this.state.sortedList.map(function(room) {
|
||||
var selected = room.roomId == self.props.selectedRoom;
|
||||
// XXX: is it evil to pass in self as a prop to RoomTile?
|
||||
return (
|
||||
<RoomTile
|
||||
<DNDRoomTile
|
||||
room={ room }
|
||||
roomSubList={ self }
|
||||
key={ room.roomId }
|
||||
@@ -293,32 +362,95 @@ var RoomSubList = React.createClass({
|
||||
unread={ Unread.doesRoomHaveUnreadMessages(room) }
|
||||
highlight={ room.getUnreadNotificationCount('highlight') > 0 || self.props.label === 'Invites' }
|
||||
isInvite={ self.props.label === 'Invites' }
|
||||
incomingCall={ self.props.incomingCall && (self.props.incomingCall.roomId === room.roomId) ? self.props.incomingCall : null } />
|
||||
refreshSubList={ self._updateSubListCount }
|
||||
incomingCall={ null } />
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
_getHeaderJsx: function() {
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
|
||||
var subListNotifications = this.roomNotificationCount();
|
||||
var subListNotifCount = subListNotifications[0];
|
||||
var subListNotifHighlight = subListNotifications[1];
|
||||
|
||||
var roomCount = this.props.list.length > 0 ? this.props.list.length : '';
|
||||
|
||||
var chevronClasses = classNames({
|
||||
'mx_RoomSubList_chevron': true,
|
||||
'mx_RoomSubList_chevronRight': this.state.hidden,
|
||||
'mx_RoomSubList_chevronDown': !this.state.hidden,
|
||||
});
|
||||
|
||||
var badgeClasses = classNames({
|
||||
'mx_RoomSubList_badge': true,
|
||||
'mx_RoomSubList_badgeHighlight': subListNotifHighlight,
|
||||
});
|
||||
|
||||
var badge;
|
||||
if (subListNotifCount > 0) {
|
||||
badge = <div className={badgeClasses}>{ FormattingUtils.formatCount(subListNotifCount) }</div>;
|
||||
}
|
||||
|
||||
// When collapsed, allow a long hover on the header to show user
|
||||
// the full tag name and room count
|
||||
var title;
|
||||
if (this.props.collapsed) {
|
||||
title = this.props.label;
|
||||
if (roomCount !== '') {
|
||||
title += " [" + roomCount + "]";
|
||||
}
|
||||
}
|
||||
|
||||
var incomingCall;
|
||||
if (this.props.incomingCall) {
|
||||
var self = this;
|
||||
// Check if the incoming call is for this section
|
||||
var incomingCallRoom = this.state.sortedList.filter(function(room) {
|
||||
return self.props.incomingCall.roomId === room.roomId;
|
||||
});
|
||||
|
||||
if (incomingCallRoom.length === 1) {
|
||||
var IncomingCallBox = sdk.getComponent("voip.IncomingCallBox");
|
||||
incomingCall = <IncomingCallBox className="mx_RoomSubList_incomingCall" incomingCall={ this.props.incomingCall }/>;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<h2 onClick={ this.onClick } className="mx_RoomSubList_label">
|
||||
{ this.props.collapsed ? '' : this.props.label }
|
||||
<img className="mx_RoomSubList_chevron"
|
||||
src={ this.state.hidden ? "img/list-close.svg" : "img/list-open.svg" }
|
||||
width="10" height="10" />
|
||||
</h2>
|
||||
<div className="mx_RoomSubList_labelContainer" title={ title } ref="header">
|
||||
<div onClick={ this.onClick } className="mx_RoomSubList_label">
|
||||
{ this.props.collapsed ? '' : this.props.label }
|
||||
<div className="mx_RoomSubList_roomCount">{ roomCount }</div>
|
||||
<div className={chevronClasses}></div>
|
||||
{ badge }
|
||||
{ incomingCall }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
_createOverflowTile: function(overflowCount, totalCount) {
|
||||
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
// XXX: this is duplicated from RoomTile - factor it out
|
||||
var content = <div className="mx_RoomSubList_chevronDown"></div>;
|
||||
|
||||
var overflowNotifications = this.roomNotificationCount(TRUNCATE_AT);
|
||||
var overflowNotifCount = overflowNotifications[0];
|
||||
var overflowNotifHighlight = overflowNotifications[1];
|
||||
if (overflowNotifCount && !this.props.collapsed) {
|
||||
content = FormattingUtils.formatCount(overflowNotifCount);
|
||||
}
|
||||
|
||||
var badgeClasses = classNames({
|
||||
'mx_RoomSubList_moreBadge': true,
|
||||
'mx_RoomSubList_moreBadgeNotify': overflowNotifCount && !this.props.collapsed,
|
||||
'mx_RoomSubList_moreBadgeHighlight': overflowNotifHighlight && !this.props.collapsed,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="mx_RoomTile mx_RoomTile_ellipsis" onClick={this._showFullMemberList}>
|
||||
<div className="mx_RoomTile_avatar">
|
||||
<BaseAvatar url="img/ellipsis.svg" name="..." width={24} height={24} />
|
||||
</div>
|
||||
<div className="mx_RoomTile_name">and { overflowCount } others...</div>
|
||||
<div className="mx_RoomSubList_ellipsis" onClick={this._showFullMemberList}>
|
||||
<div className="mx_RoomSubList_line"></div>
|
||||
<div className="mx_RoomSubList_more">more</div>
|
||||
<div className={ badgeClasses }>{ content }</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
@@ -327,7 +459,9 @@ var RoomSubList = React.createClass({
|
||||
this.setState({
|
||||
truncateAt: -1
|
||||
});
|
||||
|
||||
this.props.onShowMoreRooms();
|
||||
this.props.onHeaderClick(false);
|
||||
},
|
||||
|
||||
// Fix any undefined order elements of a room in a manual ordered list
|
||||
@@ -354,7 +488,7 @@ var RoomSubList = React.createClass({
|
||||
// is run with historical room tag data, after that there should only be undefined
|
||||
// in the list at a time anyway.
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (list[i].tags[self.props.tagName].order === undefined) {
|
||||
if (list[i].tags[self.props.tagName] && list[i].tags[self.props.tagName].order === undefined) {
|
||||
MatrixClientPeg.get().setRoomTag(list[i].roomId, self.props.tagName, {order: (order + 1.0) / 2.0}).finally(function() {
|
||||
// Do any final stuff here
|
||||
}).fail(function(err) {
|
||||
|
||||
@@ -20,9 +20,10 @@ var React = require('react');
|
||||
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var sdk = require('matrix-react-sdk');
|
||||
var Modal = require('matrix-react-sdk/lib/Modal');
|
||||
var Resend = require("matrix-react-sdk/lib/Resend");
|
||||
import * as UserSettingsStore from 'matrix-react-sdk/lib/UserSettingsStore';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MessageContextMenu',
|
||||
@@ -84,6 +85,14 @@ module.exports = React.createClass({
|
||||
if (this.props.onFinished) this.props.onFinished();
|
||||
},
|
||||
|
||||
onQuoteClick: function () {
|
||||
console.log(this.props.mxEvent);
|
||||
dis.dispatch({
|
||||
action: 'quote',
|
||||
event: this.props.mxEvent,
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var eventStatus = this.props.mxEvent.status;
|
||||
var resendButton;
|
||||
@@ -133,12 +142,17 @@ module.exports = React.createClass({
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: this should be https://matrix.to.
|
||||
// XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID)
|
||||
permalinkButton = (
|
||||
<div className="mx_MessageContextMenu_field">
|
||||
<a href={ "#/room/" + this.props.mxEvent.getRoomId() +"/"+ this.props.mxEvent.getId() }
|
||||
onClick={ this.onPermalinkClick }>Permalink</a>
|
||||
<a href={ "https://matrix.to/#/" + this.props.mxEvent.getRoomId() +"/"+ this.props.mxEvent.getId() }
|
||||
target="_blank" onClick={ this.onPermalinkClick }>Permalink</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
const quoteButton = (
|
||||
<div className="mx_MessageContextMenu_field" onClick={this.onQuoteClick}>
|
||||
Quote
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -150,6 +164,7 @@ module.exports = React.createClass({
|
||||
{viewSourceButton}
|
||||
{unhidePreviewButton}
|
||||
{permalinkButton}
|
||||
{UserSettingsStore.isFeatureEnabled('rich_text_editor') ? quoteButton : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ limitations under the License.
|
||||
var q = require("q");
|
||||
var React = require('react');
|
||||
var classNames = require('classnames');
|
||||
var RoomNotifs = require('matrix-react-sdk/lib/RoomNotifs');
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'NotificationStateContextMenu',
|
||||
@@ -31,95 +31,86 @@ module.exports = React.createClass({
|
||||
onFinished: React.PropTypes.func,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
var areNotifsMuted = false;
|
||||
var cli = MatrixClientPeg.get();
|
||||
if (!cli.isGuest()) {
|
||||
var roomPushRule = cli.getRoomPushRule("global", this.props.room.roomId);
|
||||
if (roomPushRule) {
|
||||
if (0 <= roomPushRule.actions.indexOf("dont_notify")) {
|
||||
areNotifsMuted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
areNotifsMuted: areNotifsMuted,
|
||||
};
|
||||
roomNotifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
|
||||
}
|
||||
},
|
||||
|
||||
_save: function( areNotifsMuted ) {
|
||||
var self = this;
|
||||
componentWillMount: function() {
|
||||
this._unmounted = false;
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this._unmounted = true;
|
||||
},
|
||||
|
||||
_save: function(newState) {
|
||||
const oldState = this.state.roomNotifState;
|
||||
const roomId = this.props.room.roomId;
|
||||
var cli = MatrixClientPeg.get();
|
||||
|
||||
if (!cli.isGuest()) {
|
||||
// Wrapping this in a q promise, as setRoomMutePushRule can return
|
||||
// a promise or a value
|
||||
q(cli.setRoomMutePushRule("global", roomId, areNotifsMuted))
|
||||
.then(function() {
|
||||
self.setState({areNotifsMuted: areNotifsMuted});
|
||||
if (cli.isGuest()) return;
|
||||
|
||||
// delay slightly so that the user can see their state change
|
||||
// before closing the menu
|
||||
return q.delay(500).then(function() {
|
||||
// tell everyone that wants to know of the change in
|
||||
// notification state
|
||||
dis.dispatch({
|
||||
action: 'notification_change',
|
||||
roomId: self.props.room.roomId,
|
||||
areNotifsMuted: areNotifsMuted,
|
||||
});
|
||||
|
||||
// Close the context menu
|
||||
if (self.props.onFinished) {
|
||||
self.props.onFinished();
|
||||
};
|
||||
});
|
||||
}).fail(function(error) {
|
||||
// TODO: some form of error notification to the user
|
||||
// to inform them that their state change failed.
|
||||
this.setState({
|
||||
roomNotifState: newState,
|
||||
});
|
||||
RoomNotifs.setRoomNotifsState(this.props.room.roomId, newState).done(() => {
|
||||
// delay slightly so that the user can see their state change
|
||||
// before closing the menu
|
||||
return q.delay(500).then(() => {
|
||||
if (this._unmounted) return;
|
||||
// Close the context menu
|
||||
if (this.props.onFinished) {
|
||||
this.props.onFinished();
|
||||
};
|
||||
});
|
||||
}
|
||||
}, (error) => {
|
||||
// TODO: some form of error notification to the user
|
||||
// to inform them that their state change failed.
|
||||
// For now we at least set the state back
|
||||
if (this._unmounted) return;
|
||||
this.setState({
|
||||
roomNotifState: oldState,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_onClickAlertMe: function() {
|
||||
// Placeholder
|
||||
this._save(RoomNotifs.ALL_MESSAGES_LOUD);
|
||||
},
|
||||
|
||||
_onClickAllNotifs: function() {
|
||||
this._save(false);
|
||||
this._save(RoomNotifs.ALL_MESSAGES);
|
||||
},
|
||||
|
||||
_onClickMentions: function() {
|
||||
this._save(true);
|
||||
this._save(RoomNotifs.MENTIONS_ONLY);
|
||||
},
|
||||
|
||||
_onClickMute: function() {
|
||||
// Placeholder
|
||||
this._save(RoomNotifs.MUTE);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
|
||||
var alertMeClasses = classNames({
|
||||
'mx_NotificationStateContextMenu_field': true,
|
||||
'mx_NotificationStateContextMenu_fieldDisabled': true,
|
||||
'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD,
|
||||
});
|
||||
|
||||
var allNotifsClasses = classNames({
|
||||
'mx_NotificationStateContextMenu_field': true,
|
||||
'mx_NotificationStateContextMenu_fieldSet': !this.state.areNotifsMuted,
|
||||
'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES,
|
||||
});
|
||||
|
||||
var mentionsClasses = classNames({
|
||||
'mx_NotificationStateContextMenu_field': true,
|
||||
'mx_NotificationStateContextMenu_fieldSet': this.state.areNotifsMuted,
|
||||
'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.MENTIONS_ONLY,
|
||||
});
|
||||
|
||||
var muteNotifsClasses = classNames({
|
||||
'mx_NotificationStateContextMenu_field': true,
|
||||
'mx_NotificationStateContextMenu_fieldDisabled': true,
|
||||
'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.MUTE,
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -21,6 +21,8 @@ var React = require('react');
|
||||
var classNames = require('classnames');
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
var DMRoomMap = require('matrix-react-sdk/lib/utils/DMRoomMap');
|
||||
var Rooms = require('matrix-react-sdk/lib/Rooms');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomTagContextMenu',
|
||||
@@ -32,9 +34,11 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
const dmRoomMap = new DMRoomMap(MatrixClientPeg.get());
|
||||
return {
|
||||
isFavourite: this.props.room.tags.hasOwnProperty("m.favourite"),
|
||||
isLowPriority: this.props.room.tags.hasOwnProperty("m.lowpriority"),
|
||||
isDirectMessage: Boolean(dmRoomMap.getUserIdForRoomId(this.props.room.roomId)),
|
||||
};
|
||||
},
|
||||
|
||||
@@ -113,6 +117,43 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
_onClickDM: function() {
|
||||
const newIsDirectMessage = !this.state.isDirectMessage;
|
||||
this.setState({
|
||||
isDirectMessage: newIsDirectMessage,
|
||||
});
|
||||
|
||||
if (MatrixClientPeg.get().isGuest()) return;
|
||||
|
||||
let newTarget;
|
||||
if (newIsDirectMessage) {
|
||||
const guessedTarget = Rooms.guessDMRoomTarget(
|
||||
this.props.room,
|
||||
this.props.room.getMember(MatrixClientPeg.get().credentials.userId),
|
||||
);
|
||||
newTarget = guessedTarget.userId;
|
||||
} else {
|
||||
newTarget = null;
|
||||
}
|
||||
|
||||
// give some time for the user to see the icon change first, since
|
||||
// this will hide the context menu once it completes
|
||||
q.delay(500).done(() => {
|
||||
return Rooms.setDMRoom(this.props.room.roomId, newTarget).finally(() => {
|
||||
// Close the context menu
|
||||
if (this.props.onFinished) {
|
||||
this.props.onFinished();
|
||||
};
|
||||
}, (err) => {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to set Direct Message status of room",
|
||||
description: err.toString()
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_onClickLeave: function() {
|
||||
// Leave room
|
||||
dis.dispatch({
|
||||
@@ -126,28 +167,64 @@ module.exports = React.createClass({
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
var myMember = this.props.room.getMember(myUserId);
|
||||
_onClickForget: function() {
|
||||
// FIXME: duplicated with RoomSettings (and dead code in RoomView)
|
||||
MatrixClientPeg.get().forget(this.props.room.roomId).done(function() {
|
||||
dis.dispatch({ action: 'view_next_room' });
|
||||
}, function(err) {
|
||||
var errCode = err.errcode || "unknown error code";
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error",
|
||||
description: `Failed to forget room (${errCode})`
|
||||
});
|
||||
});
|
||||
|
||||
var favouriteClasses = classNames({
|
||||
// Close the context menu
|
||||
if (this.props.onFinished) {
|
||||
this.props.onFinished();
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
const myMember = this.props.room.getMember(myUserId);
|
||||
|
||||
const favouriteClasses = classNames({
|
||||
'mx_RoomTagContextMenu_field': true,
|
||||
'mx_RoomTagContextMenu_fieldSet': this.state.isFavourite,
|
||||
'mx_RoomTagContextMenu_fieldDisabled': false,
|
||||
});
|
||||
|
||||
var lowPriorityClasses = classNames({
|
||||
const lowPriorityClasses = classNames({
|
||||
'mx_RoomTagContextMenu_field': true,
|
||||
'mx_RoomTagContextMenu_fieldSet': this.state.isLowPriority,
|
||||
'mx_RoomTagContextMenu_fieldDisabled': false,
|
||||
});
|
||||
|
||||
var leaveClasses = classNames({
|
||||
const leaveClasses = classNames({
|
||||
'mx_RoomTagContextMenu_field': true,
|
||||
'mx_RoomTagContextMenu_fieldSet': false,
|
||||
'mx_RoomTagContextMenu_fieldDisabled': false,
|
||||
});
|
||||
|
||||
const dmClasses = classNames({
|
||||
'mx_RoomTagContextMenu_field': true,
|
||||
'mx_RoomTagContextMenu_fieldSet': this.state.isDirectMessage,
|
||||
'mx_RoomTagContextMenu_fieldDisabled': false,
|
||||
});
|
||||
|
||||
if (myMember && myMember.membership === "leave") {
|
||||
return (
|
||||
<div>
|
||||
<div className={ leaveClasses } onClick={ this._onClickForget } >
|
||||
<img className="mx_RoomTagContextMenu_icon" src="img/icon_context_delete.svg" width="15" height="15" />
|
||||
Forget
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={ favouriteClasses } onClick={this._onClickFavourite} >
|
||||
@@ -160,6 +237,11 @@ module.exports = React.createClass({
|
||||
<img className="mx_RoomTagContextMenu_icon_set" src="img/icon_context_low_on.svg" width="15" height="15" />
|
||||
Low Priority
|
||||
</div>
|
||||
<div className={ dmClasses } onClick={this._onClickDM} >
|
||||
<img className="mx_RoomTagContextMenu_icon" src="img/icon_context_person.svg" width="15" height="15" />
|
||||
<img className="mx_RoomTagContextMenu_icon_set" src="img/icon_context_person_on.svg" width="15" height="15" />
|
||||
Direct Chat
|
||||
</div>
|
||||
<hr className="mx_RoomTagContextMenu_separator" />
|
||||
<div className={ leaveClasses } onClick={(myMember && myMember.membership === "join") ? this._onClickLeave : null} >
|
||||
<img className="mx_RoomTagContextMenu_icon" src="img/icon_context_delete.svg" width="15" height="15" />
|
||||
|
||||
92
src/components/views/dialogs/ChangelogDialog.js
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 2016 Aviral Dasgupta
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import request from 'browser-request';
|
||||
|
||||
const REPOS = ['vector-im/vector-web', 'matrix-org/matrix-react-sdk', 'matrix-org/matrix-js-sdk'];
|
||||
|
||||
export default class ChangelogDialog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const version = this.props.newVersion.split('-');
|
||||
const version2 = this.props.version.split('-');
|
||||
if(version == null || version2 == null) return;
|
||||
for(let i=0; i<REPOS.length; i++) {
|
||||
const oldVersion = version2[2*i+1];
|
||||
const newVersion = version[2*i+1];
|
||||
request(`https://api.github.com/repos/${REPOS[i]}/compare/${oldVersion}...${newVersion}`, (a, b, body) => {
|
||||
if(body == null) return;
|
||||
this.setState({[REPOS[i]]: JSON.parse(body).commits});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_elementsForCommit(commit) {
|
||||
return (
|
||||
<li key={commit.sha} className="mx_ChangelogDialog_li">
|
||||
<a href={commit.html_url} target="_blank" ref="noopener">
|
||||
{commit.commit.message}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const Spinner = sdk.getComponent('views.elements.Spinner');
|
||||
const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog');
|
||||
|
||||
const logs = REPOS.map(repo => {
|
||||
if (this.state[repo] == null) return <Spinner key={repo} />;
|
||||
return (
|
||||
<div key={repo}>
|
||||
<h2>{repo}</h2>
|
||||
<ul>
|
||||
{this.state[repo].map(this._elementsForCommit)}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
});
|
||||
|
||||
const content = (
|
||||
<div className="mx_ChangelogDialog_content">
|
||||
{this.props.version == null || this.props.newVersion == null ? <h2>Unavailable</h2> : logs}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
<QuestionDialog
|
||||
title="Changelog"
|
||||
description={content}
|
||||
button="Update"
|
||||
onFinished={this.props.onFinished}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ChangelogDialog.propTypes = {
|
||||
version: React.PropTypes.string.isRequired,
|
||||
newVersion: React.PropTypes.string.isRequired,
|
||||
onFinished: React.PropTypes.func.isRequired,
|
||||
};
|
||||
244
src/components/views/directory/NetworkDropdown.js
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
Copyright 2016 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.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
|
||||
export default class NetworkDropdown extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.dropdownRootElement = null;
|
||||
this.ignoreEvent = null;
|
||||
|
||||
this.onInputClick = this.onInputClick.bind(this);
|
||||
this.onRootClick = this.onRootClick.bind(this);
|
||||
this.onDocumentClick = this.onDocumentClick.bind(this);
|
||||
this.onMenuOptionClick = this.onMenuOptionClick.bind(this);
|
||||
this.onInputKeyUp = this.onInputKeyUp.bind(this);
|
||||
this.collectRoot = this.collectRoot.bind(this);
|
||||
this.collectInputTextBox = this.collectInputTextBox.bind(this);
|
||||
|
||||
this.inputTextBox = null;
|
||||
|
||||
const server = MatrixClientPeg.getHomeServerName();
|
||||
let defaultNetwork = null;
|
||||
if (
|
||||
this.props.config.serverConfig &&
|
||||
this.props.config.serverConfig[server] &&
|
||||
this.props.config.serverConfig[server].networks &&
|
||||
this.props.config.serverConfig[server].networks.indexOf('_matrix') > -1
|
||||
) {
|
||||
defaultNetwork = '_matrix';
|
||||
}
|
||||
|
||||
this.state = {
|
||||
expanded: false,
|
||||
selectedServer: server,
|
||||
selectedNetwork: defaultNetwork,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
// Listen for all clicks on the document so we can close the
|
||||
// menu when the user clicks somewhere else
|
||||
document.addEventListener('click', this.onDocumentClick, false);
|
||||
|
||||
// fire this now so the defaults can be set up
|
||||
this.props.onOptionChange(this.state.selectedServer, this.state.selectedNetwork);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('click', this.onDocumentClick, false);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.state.expanded && this.inputTextBox) {
|
||||
this.inputTextBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
onDocumentClick(ev) {
|
||||
// Close the dropdown if the user clicks anywhere that isn't
|
||||
// within our root element
|
||||
if (ev !== this.ignoreEvent) {
|
||||
this.setState({
|
||||
expanded: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onRootClick(ev) {
|
||||
// This captures any clicks that happen within our elements,
|
||||
// such that we can then ignore them when they're seen by the
|
||||
// click listener on the document handler, ie. not close the
|
||||
// dropdown immediately after opening it.
|
||||
// NB. We can't just stopPropagation() because then the event
|
||||
// doesn't reach the React onClick().
|
||||
this.ignoreEvent = ev;
|
||||
}
|
||||
|
||||
onInputClick(ev) {
|
||||
this.setState({
|
||||
expanded: !this.state.expanded,
|
||||
});
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
onMenuOptionClick(server, network, ev) {
|
||||
this.setState({
|
||||
expanded: false,
|
||||
selectedServer: server,
|
||||
selectedNetwork: network,
|
||||
});
|
||||
this.props.onOptionChange(server, network);
|
||||
}
|
||||
|
||||
onInputKeyUp(e) {
|
||||
if (e.key == 'Enter') {
|
||||
this.setState({
|
||||
expanded: false,
|
||||
selectedServer: e.target.value,
|
||||
selectedNetwork: null,
|
||||
});
|
||||
this.props.onOptionChange(e.target.value, null);
|
||||
}
|
||||
}
|
||||
|
||||
collectRoot(e) {
|
||||
if (this.dropdownRootElement) {
|
||||
this.dropdownRootElement.removeEventListener('click', this.onRootClick, false);
|
||||
}
|
||||
if (e) {
|
||||
e.addEventListener('click', this.onRootClick, false);
|
||||
}
|
||||
this.dropdownRootElement = e;
|
||||
}
|
||||
|
||||
collectInputTextBox(e) {
|
||||
this.inputTextBox = e;
|
||||
}
|
||||
|
||||
_getMenuOptions() {
|
||||
const options = [];
|
||||
|
||||
let servers = [];
|
||||
if (this.props.config.servers) {
|
||||
servers = servers.concat(this.props.config.servers);
|
||||
}
|
||||
|
||||
if (servers.indexOf(MatrixClientPeg.getHomeServerName()) == -1) {
|
||||
servers.unshift(MatrixClientPeg.getHomeServerName());
|
||||
}
|
||||
|
||||
for (const server of servers) {
|
||||
options.push(this._makeMenuOption(server, null));
|
||||
if (this.props.config.serverConfig && this.props.config.serverConfig[server] && this.props.config.serverConfig[server].networks) {
|
||||
for (const network of this.props.config.serverConfig[server].networks) {
|
||||
options.push(this._makeMenuOption(server, network));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
_makeMenuOption(server, network, wire_onclick) {
|
||||
if (wire_onclick === undefined) wire_onclick = true;
|
||||
let icon;
|
||||
let name;
|
||||
let span_class;
|
||||
|
||||
if (network === null) {
|
||||
name = server;
|
||||
span_class = 'mx_NetworkDropdown_menu_all';
|
||||
} else if (network == '_matrix') {
|
||||
name = 'Matrix';
|
||||
icon = <img src="img/network-matrix.svg" width="16" height="16" />;
|
||||
span_class = 'mx_NetworkDropdown_menu_network';
|
||||
} else {
|
||||
if (this.props.config.networks[network] === undefined) {
|
||||
throw new Error(network + ' network missing from config');
|
||||
}
|
||||
if (this.props.config.networks[network].name) {
|
||||
name = this.props.config.networks[network].name;
|
||||
} else {
|
||||
name = network;
|
||||
}
|
||||
if (this.props.config.networks[network].icon) {
|
||||
// omit height here so if people define a non-square logo in the config, it
|
||||
// will keep the aspect when it scales
|
||||
icon = <img src={this.props.config.networks[network].icon} width="16" />;
|
||||
} else {
|
||||
icon = <img src={iconPath} width="16" height="16" />;
|
||||
}
|
||||
|
||||
span_class = 'mx_NetworkDropdown_menu_network';
|
||||
}
|
||||
|
||||
const click_handler = wire_onclick ? this.onMenuOptionClick.bind(this, server, network) : null;
|
||||
|
||||
let key = server;
|
||||
if (network !== null) {
|
||||
key += '_' + network;
|
||||
}
|
||||
|
||||
return <div key={key} className="mx_NetworkDropdown_networkoption" onClick={click_handler}>
|
||||
{icon}
|
||||
<span className={span_class}>{name}</span>
|
||||
</div>;
|
||||
}
|
||||
|
||||
render() {
|
||||
let current_value;
|
||||
|
||||
let menu;
|
||||
if (this.state.expanded) {
|
||||
const menu_options = this._getMenuOptions();
|
||||
menu = <div className="mx_NetworkDropdown_menu">
|
||||
{menu_options}
|
||||
</div>;
|
||||
current_value = <input type="text" className="mx_NetworkDropdown_networkoption"
|
||||
ref={this.collectInputTextBox} onKeyUp={this.onInputKeyUp}
|
||||
placeholder="matrix.org" // 'matrix.org' as an example of an HS name
|
||||
/>
|
||||
} else {
|
||||
current_value = this._makeMenuOption(
|
||||
this.state.selectedServer, this.state.selectedNetwork, false
|
||||
);
|
||||
}
|
||||
|
||||
return <div className="mx_NetworkDropdown" ref={this.collectRoot}>
|
||||
<div className="mx_NetworkDropdown_input" onClick={this.onInputClick}>
|
||||
{current_value}
|
||||
<span className="mx_NetworkDropdown_arrow"></span>
|
||||
{menu}
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
NetworkDropdown.propTypes = {
|
||||
onOptionChange: React.PropTypes.func.isRequired,
|
||||
config: React.PropTypes.object,
|
||||
};
|
||||
|
||||
NetworkDropdown.defaultProps = {
|
||||
config: {
|
||||
networks: [],
|
||||
}
|
||||
};
|
||||
|
||||
@@ -80,7 +80,7 @@ module.exports = React.createClass({
|
||||
getName: function () {
|
||||
var name = this.props.name;
|
||||
if (name && this.props.link) {
|
||||
name = <a href={ this.props.link } target="_blank">{ name }</a>;
|
||||
name = <a href={ this.props.link } target="_blank" rel="noopener">{ name }</a>;
|
||||
}
|
||||
return name;
|
||||
},
|
||||
@@ -169,7 +169,7 @@ module.exports = React.createClass({
|
||||
{ this.getName() }
|
||||
</div>
|
||||
{ eventMeta }
|
||||
<a className="mx_ImageView_link" href={ this.props.src } target="_blank">
|
||||
<a className="mx_ImageView_link" href={ this.props.src } target="_blank" rel="noopener">
|
||||
<div className="mx_ImageView_download">
|
||||
Download this file<br/>
|
||||
<span className="mx_ImageView_size">{ size_res }</span>
|
||||
|
||||
@@ -34,7 +34,7 @@ module.exports = React.createClass({
|
||||
<div className="mx_GuestWarningBar">
|
||||
<img className="mx_GuestWarningBar_warning" src="img/warning.svg" width="24" height="23" alt="/!\"/>
|
||||
<div>
|
||||
You are using Vector as a guest. <a onClick={this.onRegisterClicked}>Register</a> or <a onClick={this.onLoginClicked}>log in</a> to access more rooms and features.
|
||||
You are Rioting as a guest. <a onClick={this.onRegisterClicked}>Register</a> or <a onClick={this.onLoginClicked}>sign in</a> to access more rooms and features.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,20 +17,49 @@ limitations under the License.
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var sdk = require('matrix-react-sdk');
|
||||
import Modal from 'matrix-react-sdk/lib/Modal';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'NewVersionBar',
|
||||
/**
|
||||
* Check a version string is compatible with the Changelog
|
||||
* dialog
|
||||
*/
|
||||
function checkVersion(ver) {
|
||||
const parts = ver.split('-');
|
||||
return parts[0] == 'vector' && parts[2] == 'react' && parts[4] == 'js';
|
||||
}
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_MatrixToolbar">
|
||||
<img className="mx_MatrixToolbar_warning" src="img/warning.svg" width="24" height="23" alt="/!\"/>
|
||||
<div>
|
||||
A new version of Vector is available. Refresh your browser.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
export default function NewVersionBar(props) {
|
||||
const onChangelogClicked = () => {
|
||||
const ChangelogDialog = sdk.getComponent('dialogs.ChangelogDialog');
|
||||
|
||||
Modal.createDialog(ChangelogDialog, {
|
||||
version: props.version,
|
||||
newVersion: props.newVersion,
|
||||
onFinished: (update) => {
|
||||
if(update) {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let changelog_button;
|
||||
if (checkVersion(props.version) && checkVersion(props.newVersion)) {
|
||||
changelog_button = <button className="mx_MatrixToolbar_action" onClick={onChangelogClicked}>Changelog</button>;
|
||||
}
|
||||
});
|
||||
return (
|
||||
<div className="mx_MatrixToolbar">
|
||||
<img className="mx_MatrixToolbar_warning" src="img/warning.svg" width="24" height="23" alt="/!\"/>
|
||||
<div className="mx_MatrixToolbar_content">
|
||||
A new version of Riot is available. Refresh your browser.
|
||||
</div>
|
||||
{changelog_button}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
NewVersionBar.propTypes = {
|
||||
version: React.PropTypes.string.isRequired,
|
||||
newVersion: React.PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
@@ -30,10 +30,10 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
<div className="mx_Dialog_content">
|
||||
<span>
|
||||
You can use the custom server options to log into other Matrix
|
||||
You can use the custom server options to sign into other Matrix
|
||||
servers by specifying a different Home server URL.
|
||||
<br/>
|
||||
This allows you to use Vector with an existing Matrix account on
|
||||
This allows you to use Riot with an existing Matrix account on
|
||||
a different home server.
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
@@ -27,8 +27,8 @@ module.exports = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_Login_links">
|
||||
<a href="https://medium.com/@Vector">blog</a> ·
|
||||
<a href="https://twitter.com/@VectorCo">twitter</a> ·
|
||||
<a href="https://medium.com/@RiotChat">blog</a> ·
|
||||
<a href="https://twitter.com/@RiotChat">twitter</a> ·
|
||||
<a href="https://github.com/vector-im/vector-web">github</a> ·
|
||||
<a href="https://matrix.org">powered by Matrix</a>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,7 @@ module.exports = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_Login_logo">
|
||||
<img src="img/logo.png" width="249" height="78" alt="vector"/>
|
||||
<img src="img/logo.png" width="195" height="195" alt="Riot"/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = React.createClass({
|
||||
var date = new Date(this.props.ts);
|
||||
return (
|
||||
<span className="mx_MessageTimestamp">
|
||||
{ DateUtils.formatDate(date) }
|
||||
{ DateUtils.formatTime(date) }
|
||||
</span>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var sdk = require('matrix-react-sdk')
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'BottomLeftMenuTile',
|
||||
|
||||
getInitialState: function() {
|
||||
return( { hover : false });
|
||||
},
|
||||
|
||||
onMouseEnter: function() {
|
||||
this.setState( { hover : true });
|
||||
},
|
||||
|
||||
onMouseLeave: function() {
|
||||
this.setState( { hover : false });
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var label;
|
||||
if (!this.props.collapsed) {
|
||||
label = <div className="mx_RoomTile_name">{ this.props.label }</div>;
|
||||
}
|
||||
else if (this.state.hover) {
|
||||
var RoomTooltip = sdk.getComponent("rooms.RoomTooltip");
|
||||
label = <RoomTooltip bottom={ true } label={ this.props.label }/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_RoomTile" onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} onClick={this.props.onClick}>
|
||||
<div className="mx_RoomTile_avatar">
|
||||
<img src={ this.props.img } width="26" height="26"/>
|
||||
</div>
|
||||
{ label }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -25,6 +25,13 @@ var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
var sdk = require('matrix-react-sdk');
|
||||
var RoomTile = require('matrix-react-sdk/lib/components/views/rooms/RoomTile');
|
||||
|
||||
/**
|
||||
* Defines a new Component, DNDRoomTile that wraps RoomTile, making it draggable.
|
||||
* Requires extra props:
|
||||
* roomSubList: React.PropTypes.object.isRequired,
|
||||
* refreshSubList: React.PropTypes.func.isRequired,
|
||||
*/
|
||||
|
||||
/**
|
||||
* Specifies the drag source contract.
|
||||
* Only `beginDrag` function is required.
|
||||
@@ -202,4 +209,3 @@ DragSource('RoomTile', roomTileSource, function(connect, monitor) {
|
||||
};
|
||||
})(RoomTile));
|
||||
|
||||
module.exports.replaces = 'RoomTile';
|
||||
@@ -18,42 +18,79 @@ limitations under the License.
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomTooltip',
|
||||
|
||||
componentDidMount: function() {
|
||||
var tooltip = ReactDOM.findDOMNode(this);
|
||||
if (!this.props.bottom) {
|
||||
// tell the roomlist about us so it can position us
|
||||
dis.dispatch({
|
||||
action: 'view_tooltip',
|
||||
tooltip: tooltip,
|
||||
});
|
||||
}
|
||||
else {
|
||||
tooltip.style.top = (70 + tooltip.parentElement.getBoundingClientRect().top) + "px";
|
||||
tooltip.style.display = "block";
|
||||
}
|
||||
propTypes: {
|
||||
// Alllow the tooltip to be styled by the parent element
|
||||
className: React.PropTypes.string.isRequired,
|
||||
// The tooltip is derived from either the room name or a label
|
||||
room: React.PropTypes.object,
|
||||
label: React.PropTypes.string,
|
||||
},
|
||||
|
||||
// Create a wrapper for the tooltip outside the parent and attach it to the body element
|
||||
componentDidMount: function() {
|
||||
this.tooltipContainer = document.createElement("div");
|
||||
this.tooltipContainer.className = "mx_RoomTileTooltip_wrapper";
|
||||
document.body.appendChild(this.tooltipContainer);
|
||||
|
||||
this._renderTooltip();
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
this._renderTooltip();
|
||||
},
|
||||
|
||||
// Remove the wrapper element, as the tooltip has finished using it
|
||||
componentWillUnmount: function() {
|
||||
if (!this.props.bottom) {
|
||||
dis.dispatch({
|
||||
action: 'view_tooltip',
|
||||
tooltip: null,
|
||||
});
|
||||
}
|
||||
dis.dispatch({
|
||||
action: 'view_tooltip',
|
||||
tooltip: null,
|
||||
parent: null,
|
||||
});
|
||||
|
||||
ReactDOM.unmountComponentAtNode(this.tooltipContainer);
|
||||
document.body.removeChild(this.tooltipContainer);
|
||||
},
|
||||
|
||||
_renderTooltip: function() {
|
||||
var label = this.props.room ? this.props.room.name : this.props.label;
|
||||
|
||||
// Add the parent's position to the tooltips, so it's correctly
|
||||
// positioned, also taking into account any window zoom
|
||||
// NOTE: The additional 6 pixels for the left position, is to take account of the
|
||||
// tooltips chevron
|
||||
var parent = ReactDOM.findDOMNode(this);
|
||||
var style = {};
|
||||
style.top = parent.getBoundingClientRect().top + window.pageYOffset;
|
||||
style.left = 6 + parent.getBoundingClientRect().right + window.pageXOffset;
|
||||
style.display = "block";
|
||||
|
||||
var tooltip = (
|
||||
<div className="mx_RoomTooltip" style={style} >
|
||||
<div className="mx_RoomTooltip_chevron"></div>
|
||||
{ label }
|
||||
</div>
|
||||
);
|
||||
|
||||
// Render the tooltip manually, as we wish it not to be rendered within the parent
|
||||
this.tooltip = ReactDOM.render(tooltip, this.tooltipContainer);
|
||||
|
||||
// Tell the roomlist about us so it can manipulate us if it wishes
|
||||
dis.dispatch({
|
||||
action: 'view_tooltip',
|
||||
tooltip: this.tooltip,
|
||||
parent: parent,
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var label = this.props.room ? this.props.room.name : this.props.label;
|
||||
// Render a placeholder
|
||||
return (
|
||||
<div className="mx_RoomTooltip">
|
||||
<img className="mx_RoomTooltip_chevron" src="img/chevron-left.png" width="9" height="16"/>
|
||||
{ label }
|
||||
<div className={ this.props.className } >
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ limitations under the License.
|
||||
var React = require('react');
|
||||
var sdk = require('matrix-react-sdk');
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'IntegrationsManager',
|
||||
@@ -31,10 +32,12 @@ module.exports = React.createClass({
|
||||
// XXX: keyboard shortcuts for managing dialogs should be done by the modal
|
||||
// dialog base class somehow, surely...
|
||||
componentDidMount: function() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
document.addEventListener("keydown", this.onKeyDown);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
dis.unregister(this.dispatcherRef);
|
||||
document.removeEventListener("keydown", this.onKeyDown);
|
||||
},
|
||||
|
||||
@@ -46,11 +49,15 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
onAction: function(payload) {
|
||||
if (payload.action === 'close_scalar') {
|
||||
this.props.onFinished();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_IntegrationsManager">
|
||||
<iframe src={ this.props.src }></iframe>
|
||||
</div>
|
||||
<iframe src={ this.props.src }></iframe>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -119,7 +119,7 @@ module.exports = React.createClass({
|
||||
var emailPusherPromise;
|
||||
if (event.target.checked) {
|
||||
var data = {}
|
||||
data['brand'] = this.props.brand || 'Vector';
|
||||
data['brand'] = this.props.brand || 'Riot';
|
||||
emailPusherPromise = UserSettingsStore.addEmailPusher(address, data);
|
||||
} else {
|
||||
var emailPusher = UserSettingsStore.getEmailPusher(this.state.pushers, address);
|
||||
@@ -132,7 +132,7 @@ module.exports = React.createClass({
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Error saving email notification preferences",
|
||||
description: "Vector was unable to save your email notification preferences.",
|
||||
description: "An error occurred whilst saving your email notification preferences.",
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -784,7 +784,7 @@ module.exports = React.createClass({
|
||||
<div>
|
||||
<h3>Advanced notifications settings</h3>
|
||||
There are advanced notifications which are not shown here.<br/>
|
||||
You might have configured them in another client than Vector. You cannot tune them in Vector but they still apply.
|
||||
You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply.
|
||||
<ul>
|
||||
{ externalRules }
|
||||
</ul>
|
||||
@@ -843,7 +843,7 @@ module.exports = React.createClass({
|
||||
<th width="55%"></th>
|
||||
<th width="15%">Off</th>
|
||||
<th width="15%">On</th>
|
||||
<th width="15%">Highlight<br/>& sound</th>
|
||||
<th width="15%">Noisy</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -65,7 +65,7 @@ module.exports = {
|
||||
// Messages containing user's display name
|
||||
// (skip contains_user_name which is too geeky)
|
||||
".m.rule.contains_display_name": new VectorPushRuleDefinition({
|
||||
kind: "underride",
|
||||
kind: "override",
|
||||
description: "Messages containing my name",
|
||||
vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
|
||||
on: StandardActions.ACTION_NOTIFY,
|
||||
|
||||
@@ -64,6 +64,11 @@ input[type=text]:focus, textarea:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Required by Firefox */
|
||||
textarea {
|
||||
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
|
||||
}
|
||||
|
||||
/* Prevent ugly dotted highlight around selected elements in Firefox */
|
||||
::-moz-focus-inner {
|
||||
border: 0;
|
||||
@@ -153,6 +158,8 @@ input[type=text]:focus, textarea:focus {
|
||||
width: 60%;
|
||||
max-width: 704px;
|
||||
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2);
|
||||
max-height: 80%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mx_Dialog_background {
|
||||
@@ -196,16 +203,20 @@ input[type=text]:focus, textarea:focus {
|
||||
height: 36px;
|
||||
border-radius: 40px;
|
||||
border: solid 1px #76cfa6;
|
||||
font-weight: 400;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
|
||||
margin-left: 0px;
|
||||
margin-right: 8px;
|
||||
padding-left: 1.5em;
|
||||
padding-right: 1.5em;
|
||||
outline: none;
|
||||
|
||||
cursor: pointer;
|
||||
color: #76cfa6;
|
||||
background-color: #fff;
|
||||
|
||||
/* align images in buttons (eg spinners) */
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_Dialog button.mx_Dialog_primary, .mx_Dialog input[type="submit"].mx_Dialog_primary {
|
||||
@@ -251,7 +262,7 @@ input[type=text]:focus, textarea:focus {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.emojione {
|
||||
.mx_emojione {
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -267,7 +278,7 @@ input[type=text]:focus, textarea:focus {
|
||||
}
|
||||
|
||||
/** green button with rounded corners */
|
||||
.textButton {
|
||||
.mx_textButton {
|
||||
color: #fff;
|
||||
background-color: #76cfa6;
|
||||
border-radius: 17px;
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
.mx_RoomSettings_encrypt,
|
||||
.mx_CreateRoom_encrypt,
|
||||
.mx_RightPanel_filebutton
|
||||
{
|
||||
display: none !important;
|
||||
}
|
||||
120
src/skins/vector/css/matrix-react-sdk/structures/FilePanel.css
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 2016 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_FilePanel {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-moz-box-ordinal-group: 2;
|
||||
-ms-flex-order: 2;
|
||||
-webkit-order: 2;
|
||||
order: 2;
|
||||
|
||||
-webkit-flex: 1 1 0;
|
||||
flex: 1 1 0;
|
||||
|
||||
width: 100%;
|
||||
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_RoomView_messageListWrapper {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_RoomView_MessageList h2 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* FIXME: rather than having EventTile's default CSS be for MessagePanel,
|
||||
we should make EventTile a base CSS class and customise it specifically
|
||||
for usage in {Message,File,Notification}Panel. */
|
||||
|
||||
.mx_FilePanel .mx_EventTile_avatar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Overrides for the attachment body tiles */
|
||||
|
||||
.mx_FilePanel .mx_EventTile {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_EventTile .mx_MImageBody {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_EventTile .mx_MImageBody_download {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #acacac;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_EventTile .mx_MImageBody_downloadLink {
|
||||
flex: 1 1 auto;
|
||||
color: #747474;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_EventTile .mx_MImageBody_size {
|
||||
flex: 1 0 0;
|
||||
font-size: 11px;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Overides for the sender details line */
|
||||
|
||||
.mx_FilePanel .mx_EventTile_senderDetails {
|
||||
display: flex;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_EventTile_senderDetailsLink {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_EventTile .mx_SenderProfile {
|
||||
flex: 1 1 auto;
|
||||
line-height: initial;
|
||||
padding: 0px;
|
||||
font-size: 11px;
|
||||
opacity: 1.0;
|
||||
color: #acacac;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_EventTile .mx_MessageTimestamp {
|
||||
flex: 1 0 0;
|
||||
text-align: right;
|
||||
visibility: visible;
|
||||
position: initial;
|
||||
font-size: 11px;
|
||||
opacity: 1.0;
|
||||
color: #acacac;
|
||||
}
|
||||
|
||||
/* Overrides for the wrappers around the body tile */
|
||||
|
||||
.mx_FilePanel .mx_EventTile_line {
|
||||
margin-right: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_EventTile:hover .mx_EventTile_line {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.mx_FilePanel .mx_EventTile_selected .mx_EventTile_line {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ limitations under the License.
|
||||
-webkit-order: 2;
|
||||
order: 2;
|
||||
|
||||
padding-left: 25px;
|
||||
padding-left: 20px;
|
||||
padding-right: 22px;
|
||||
background-color: #fff;
|
||||
|
||||
@@ -151,6 +151,6 @@ limitations under the License.
|
||||
}
|
||||
|
||||
.mx_MatrixChat .mx_RightPanel.collapsed {
|
||||
-webkit-flex: 0 0 72px;
|
||||
flex: 0 0 72px;
|
||||
-webkit-flex: 0 0 122px;
|
||||
flex: 0 0 122px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2015, 2016 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_NotificationPanel {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-moz-box-ordinal-group: 2;
|
||||
-ms-flex-order: 2;
|
||||
-webkit-order: 2;
|
||||
order: 2;
|
||||
|
||||
-webkit-flex: 1 1 0;
|
||||
flex: 1 1 0;
|
||||
|
||||
width: 100%;
|
||||
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_RoomView_messageListWrapper {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_RoomView_MessageList h2 {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
/* FIXME: rather than having EventTile's default CSS be for MessagePanel,
|
||||
we should make EventTile a base CSS class and customise it specifically
|
||||
for usage in {Message,File,Notification}Panel. */
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile_roomName {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile_roomName a {
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile_avatar {
|
||||
top: 8px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile .mx_SenderProfile,
|
||||
.mx_NotificationPanel .mx_EventTile .mx_MessageTimestamp {
|
||||
color: #000;
|
||||
opacity: 0.3;
|
||||
font-size: 12px;
|
||||
display: inline;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile_senderDetails {
|
||||
padding-left: 32px;
|
||||
padding-top: 8px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile_roomName a,
|
||||
.mx_NotificationPanel .mx_EventTile_senderDetails a {
|
||||
text-decoration: none ! important;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile .mx_MessageTimestamp {
|
||||
visibility: visible;
|
||||
position: initial;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile_line {
|
||||
margin-right: 0px;
|
||||
padding-left: 32px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile:hover .mx_EventTile_line {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile_selected .mx_EventTile_line {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.mx_NotificationPanel .mx_EventTile_content {
|
||||
margin-right: 0px;
|
||||
}
|
||||
@@ -15,7 +15,6 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_RoomStatusBar {
|
||||
margin-top: 15px;
|
||||
margin-left: 65px;
|
||||
min-height: 34px;
|
||||
}
|
||||
@@ -25,11 +24,17 @@ limitations under the License.
|
||||
padding-left: 18px;
|
||||
padding-right: 12px;
|
||||
margin-left: -73px;
|
||||
margin-top: 13px;
|
||||
float: left;
|
||||
width: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mx_RoomStatusBar_callBar {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
.mx_RoomStatusBar_placeholderIndicator span {
|
||||
color: #4a4a4a;
|
||||
opacity: 0.5;
|
||||
@@ -70,6 +75,7 @@ limitations under the License.
|
||||
}
|
||||
|
||||
.mx_RoomStatusBar_unreadMessagesBar {
|
||||
padding-top: 10px;
|
||||
color: #ff0064;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -103,10 +109,12 @@ limitations under the License.
|
||||
}
|
||||
|
||||
.mx_RoomStatusBar_tabCompleteBar {
|
||||
padding-top: 10px;
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
.mx_RoomStatusBar_typingBar {
|
||||
padding-top: 10px;
|
||||
color: #4a4a4a;
|
||||
opacity: 0.5;
|
||||
overflow-y: hidden;
|
||||
|
||||
@@ -207,7 +207,7 @@ hr.mx_RoomView_myReadMarker {
|
||||
.mx_RoomView_statusAreaBox {
|
||||
max-width: 960px;
|
||||
margin: auto;
|
||||
min-height: 60px;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.mx_RoomView_statusAreaBox_line {
|
||||
@@ -216,6 +216,15 @@ hr.mx_RoomView_myReadMarker {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.mx_RoomView_callStatusBar .mx_UploadBar_uploadProgressInner {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.mx_RoomView_callStatusBar .mx_UploadBar_uploadFilename {
|
||||
color: #fff;
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.mx_RoomView_inCall .mx_RoomView_statusAreaBox_line {
|
||||
border-top: 1px hidden;
|
||||
}
|
||||
@@ -239,6 +248,7 @@ hr.mx_RoomView_myReadMarker {
|
||||
.mx_RoomView_voipButton {
|
||||
float: right;
|
||||
margin-right: 13px;
|
||||
margin-top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -268,3 +278,7 @@ hr.mx_RoomView_myReadMarker {
|
||||
padding: 6px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomView_ongoingConfCallNotification a {
|
||||
color: #fff ! important;
|
||||
}
|
||||
@@ -20,7 +20,6 @@ limitations under the License.
|
||||
margin-right: 16px;
|
||||
padding-top: 24px;
|
||||
padding-bottom: 22px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
|
||||
@@ -104,6 +104,18 @@ limitations under the License.
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.mx_UserSettings_cryptoSection ul {
|
||||
display: table;
|
||||
}
|
||||
.mx_UserSettings_cryptoSection li {
|
||||
display: table-row;
|
||||
}
|
||||
.mx_UserSettings_cryptoSection label,
|
||||
.mx_UserSettings_cryptoSection span {
|
||||
display: table-cell;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.mx_UserSettings_toggle input {
|
||||
width: 16px;
|
||||
margin-right: 8px;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright 2016 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.
|
||||
*/
|
||||
|
||||
/* Using a textarea for this element, to circumvent autofill */
|
||||
.mx_ChatInviteDialog_input,
|
||||
.mx_ChatInviteDialog_input:focus
|
||||
{
|
||||
height: 26px;
|
||||
font-size: 14px;
|
||||
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
margin: 0 !important;
|
||||
border: 0 !important;
|
||||
outline: 0 !important;
|
||||
width: 1000%; /* Pretend that this is an "input type=text" */
|
||||
resize: none;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
box-sizing: border-box;
|
||||
word-wrap: nowrap;
|
||||
}
|
||||
|
||||
.mx_ChatInviteDialog_inputContainer {
|
||||
border-radius: 3px;
|
||||
border: solid 1px #f0f0f0;
|
||||
line-height: 36px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
max-height: 150px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mx_ChatInviteDialog_error {
|
||||
position: absolute;
|
||||
color: #ff0064;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.mx_ChatInviteDialog_cancel {
|
||||
position: absolute;
|
||||
right: 11px;
|
||||
top: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_ChatInviteDialog_cancel object {
|
||||
pointer-events: none;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2016 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_EncryptedEventDialog .mx_MemberDeviceInfo {
|
||||
float: right;
|
||||
padding: 0px;
|
||||
margin-right: 42px;
|
||||
}
|
||||
|
||||
.mx_EncryptedEventDialog .mx_MemberDeviceInfo_textButton {
|
||||
border: 0px;
|
||||
height: 36px;
|
||||
border-radius: 40px;
|
||||
border: solid 1px #76cfa6;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
|
||||
margin-left: 0px;
|
||||
margin-right: 8px;
|
||||
padding-left: 1.5em;
|
||||
padding-right: 1.5em;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
color: #76cfa6;
|
||||
background-color: #fff;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2016 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_AddressSelector {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
width: 485px;
|
||||
max-height: 116px;
|
||||
overflow-y: auto;
|
||||
border-radius: 3px;
|
||||
background-color: #fff;
|
||||
border: solid 1px #76cfa6;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_AddressSelector.mx_AddressSelector_empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_AddressSelector_addressListElement .mx_AddressTile {
|
||||
background-color: #fff;
|
||||
border: solid 1px #fff;
|
||||
}
|
||||
|
||||
.mx_AddressSelector_addressListElement.mx_AddressSelector_selected {
|
||||
background-color: #eaf5f0; /* selected colour */
|
||||
}
|
||||
|
||||
.mx_AddressSelector_addressListElement.mx_AddressSelector_selected .mx_AddressTile {
|
||||
background-color: #eaf5f0; /* selected colour */
|
||||
border: solid 1px #eaf5f0; /* selected colour */
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
Copyright 2015, 2016 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_AddressTile {
|
||||
display: inline-block;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(74, 73, 74, 0.1);
|
||||
border: solid 1px #f0f0f0;
|
||||
line-height: 26px;
|
||||
color: #454545;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.mx_AddressTile.mx_AddressTile_error {
|
||||
background-color: rgba(255, 0, 100, 0.1);
|
||||
color: #ff0064;
|
||||
border-color: #ff0064;
|
||||
}
|
||||
|
||||
.mx_AddressTile_network {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding-left: 2px;
|
||||
padding-right: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_AddressTile_avatar {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding-left: 2px;
|
||||
padding-right: 7px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_AddressTile_mx {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.mx_AddressTile_name {
|
||||
display: inline-block;
|
||||
padding-right: 4px;
|
||||
font-weight: 600;
|
||||
overflow: hidden;
|
||||
height: 26px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_AddressTile_name.mx_AddressTile_justified {
|
||||
width: 180px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_AddressTile_id {
|
||||
display: inline-block;
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
.mx_AddressTile_id.mx_AddressTile_justified {
|
||||
width: 200px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_AddressTile_unknownMx {
|
||||
display: inline-block;
|
||||
font-weight: 600;
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
.mx_AddressTile_unknownMxl.mx_AddressTile_justified {
|
||||
width: 380px; /* name + id width */
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_AddressTile_email {
|
||||
display: inline-block;
|
||||
font-weight: 600;
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
.mx_AddressTile_email.mx_AddressTile_justified {
|
||||
width: 380px; /* name + id width */
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_AddressTile_unknown {
|
||||
display: inline-block;
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
.mx_AddressTile_unknown.mx_AddressTile_justified {
|
||||
width: 380px; /* name + id width */
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_AddressTile_dismiss {
|
||||
display: inline-block;
|
||||
padding-right: 11px;
|
||||
padding-left: 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_AddressTile_dismiss object {
|
||||
pointer-events: none;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright 2016 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_DirectorySearchBox {
|
||||
position: relative;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #c7c7c7;
|
||||
}
|
||||
|
||||
.mx_DirectorySearchBox_container {
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
padding-left: 9px;
|
||||
padding-right: 9px;
|
||||
}
|
||||
|
||||
.mx_DirectorySearchBox_input {
|
||||
flex-grow: 1;
|
||||
-webkit-flex-grow: 1;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
font-weight: 300;
|
||||
font-size: 13px;
|
||||
}
|
||||
input[type=text].mx_DirectorySearchBox_input:focus {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.mx_DirectorySearchBox_joinButton {
|
||||
display: table-cell;
|
||||
padding: 3px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
background-color: #efefef;
|
||||
border-radius: 3px;
|
||||
background-image: url('img/icon-return.svg');
|
||||
background-position: 8px 70%;
|
||||
background-repeat: no-repeat;
|
||||
text-indent: 18px;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_DirectorySearchBox_clear_wrapper {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.mx_DirectorySearchBox_clear {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background: url('img/icon_context_delete.svg');
|
||||
background-position: 0 50%;
|
||||
background-repeat: no-repeat;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -20,3 +20,20 @@
|
||||
.mx_Markdown_ITALIC {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.mx_Markdown_CODE {
|
||||
padding: .2em 0;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
background-color: rgba(0,0,0,.04);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.mx_Markdown_HR {
|
||||
display: block;
|
||||
background: #e7e7e7;
|
||||
}
|
||||
|
||||
.mx_Markdown_STRIKETHROUGH {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ limitations under the License.
|
||||
|
||||
.mx_MImageBody {
|
||||
display: block;
|
||||
margin-right: 34px;
|
||||
}
|
||||
|
||||
.mx_MImageBody_thumbnail {
|
||||
@@ -29,7 +30,6 @@ limitations under the License.
|
||||
|
||||
.mx_MImageBody_download {
|
||||
color: #76cfa6;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_MImageBody_download a {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
z-index: 1000;
|
||||
width: 100%;
|
||||
border: 1px solid #e5e5e5;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
background: white;
|
||||
border-bottom: none;
|
||||
border-radius: 4px 4px 0 0;
|
||||
max-height: 50vh;
|
||||
@@ -12,56 +12,68 @@
|
||||
}
|
||||
|
||||
.mx_Autocomplete_ProviderSection {
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.mx_Autocomplete_ProviderSection * {
|
||||
padding: 2px;
|
||||
border-radius: 4px;
|
||||
.mx_Autocomplete_Completion_container_pill {
|
||||
margin: 12px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.mx_Autocomplete_Completion {
|
||||
/* a "block" completion takes up a whole line */
|
||||
.mx_Autocomplete_Completion_block {
|
||||
height: 34px;
|
||||
display: flex;
|
||||
padding: 0 12px;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
transition: 0.3s all ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
.mx_Autocomplete_Completion.selected * {
|
||||
transition: 0.3s all ease;
|
||||
.mx_Autocomplete_Completion_block * {
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
.mx_Autocomplete_Completion_pill {
|
||||
border-radius: 17px;
|
||||
height: 34px;
|
||||
display: flex;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
.mx_Autocomplete_Completion_pill * {
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
/* container for pill-style completions */
|
||||
.mx_Autocomplete_Completion_container_pill {
|
||||
margin: 12px;
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
}
|
||||
|
||||
.mx_Autocomplete_Completion.selected {
|
||||
background: #76cfa6;
|
||||
color: white;
|
||||
background: #f6f6f6;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.mx_Autocomplete_Completion.selected * {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.mx_Autocomplete_provider_name {
|
||||
color: #76cfa6;
|
||||
font-weight: 600;
|
||||
margin: 12px;
|
||||
color: #454545;
|
||||
font-weight: 400;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.autocomplete-enter {
|
||||
opacity: 0.01;
|
||||
/* styling for common completion elements */
|
||||
.mx_Autocomplete_Completion_subtitle {
|
||||
font-style: italic;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.autocomplete-enter.autocomplete-enter-active {
|
||||
opacity: 1;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
|
||||
.autocomplete-leave {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.autocomplete-leave.autocomplete-leave-active {
|
||||
opacity: 0.01;
|
||||
transition: opacity 300ms ease-in;
|
||||
.mx_Autocomplete_Completion_description {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
@@ -17,109 +17,72 @@ limitations under the License.
|
||||
.mx_EventTile {
|
||||
max-width: 100%;
|
||||
clear: both;
|
||||
padding-top: 24px;
|
||||
margin-left: 65px;
|
||||
padding-top: 18px;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_EventTile.mx_EventTile_info {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.mx_EventTile_avatar {
|
||||
padding-left: 18px;
|
||||
padding-right: 12px;
|
||||
margin-left: -73px;
|
||||
margin-top: -2px;
|
||||
float: left;
|
||||
position: relative;
|
||||
top: 0px;
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: 8px;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.mx_EventTile.mx_EventTile_info .mx_EventTile_avatar {
|
||||
top: 8px;
|
||||
left: 65px;
|
||||
}
|
||||
|
||||
.mx_EventTile_continuation {
|
||||
padding-top: 8px ! important;
|
||||
}
|
||||
|
||||
.mx_EventTile_verified {
|
||||
background-color: #eaf5f0;
|
||||
}
|
||||
|
||||
.mx_EventTile_unverified {
|
||||
background-color: #ffa0a0;
|
||||
padding-top: 0px ! important;
|
||||
}
|
||||
|
||||
.mx_EventTile .mx_SenderProfile {
|
||||
color: #454545;
|
||||
opacity: 0.5;
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
display: block; /* anti-zalgo, with overflow hidden */
|
||||
overflow-y: hidden;
|
||||
cursor: pointer;
|
||||
padding-left: 65px; /* left gutter */
|
||||
padding-bottom: 0px;
|
||||
padding-top: 0px;
|
||||
margin: 0px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.mx_EventTile .mx_MessageTimestamp {
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
white-space: nowrap;
|
||||
color: #acacac;
|
||||
font-size: 11px;
|
||||
left: 8px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.mx_EventTile_line {
|
||||
position: relative;
|
||||
/* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */
|
||||
margin-right: 95px;
|
||||
margin-right: 110px;
|
||||
padding-left: 65px; /* left gutter */
|
||||
padding-top: 4px;
|
||||
padding-bottom: 2px;
|
||||
border-radius: 4px;
|
||||
min-height: 24px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
/* all the overflow-y: hidden; are to trap Zalgos -
|
||||
but they introduce an implicit overflow-x: auto.
|
||||
so make that explicitly hidden too to avoid random
|
||||
horizontal scrollbars occasionally appearing, like in
|
||||
https://github.com/vector-im/vector-web/issues/1154
|
||||
*/
|
||||
.mx_EventTile_content {
|
||||
display: block;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
.mx_EventTile_info .mx_EventTile_line {
|
||||
padding-left: 83px;
|
||||
}
|
||||
|
||||
/* De-zalgoing */
|
||||
.mx_EventTile_body {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
/* Various markdown overrides */
|
||||
|
||||
.mx_EventTile_content .markdown-body {
|
||||
font-family: inherit ! important;
|
||||
white-space: normal ! important;
|
||||
line-height: inherit ! important;
|
||||
color: inherit;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
/* have to use overlay rather than auto otherwise Linux and Windows
|
||||
Chrome gets very confused about vertical spacing:
|
||||
https://github.com/vector-im/vector-web/issues/754
|
||||
*/
|
||||
.mx_EventTile_content .markdown-body pre {
|
||||
overflow-x: overlay;
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
.mx_EventTile_content .markdown-body h1,
|
||||
.mx_EventTile_content .markdown-body h2,
|
||||
.mx_EventTile_content .markdown-body h3,
|
||||
.mx_EventTile_content .markdown-body h4,
|
||||
.mx_EventTile_content .markdown-body h5,
|
||||
.mx_EventTile_content .markdown-body h6
|
||||
{
|
||||
font-family: inherit ! important;
|
||||
}
|
||||
|
||||
.mx_EventTile_content .markdown-body a {
|
||||
color: #76cfa6;
|
||||
}
|
||||
|
||||
.mx_EventTile_content .markdown-body .hljs {
|
||||
display: inline ! important;
|
||||
}
|
||||
|
||||
/* end of overrides */
|
||||
|
||||
/* HACK to override line-height which is already marked important elsewhere */
|
||||
.mx_EventTile_bigEmoji.mx_EventTile_bigEmoji {
|
||||
font-size: 48px ! important;
|
||||
@@ -129,10 +92,16 @@ limitations under the License.
|
||||
/* this is used for the tile for the event which is selected via the URL.
|
||||
* TODO: ultimately we probably want some transition on here.
|
||||
*/
|
||||
.mx_EventTile_selected {
|
||||
.mx_EventTile_selected .mx_EventTile_line {
|
||||
border-left: #76cfa6 5px solid;
|
||||
margin-left: 53px;
|
||||
padding-left: 7px;
|
||||
padding-left: 60px;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.mx_EventTile:hover .mx_EventTile_line,
|
||||
.mx_EventTile.menu .mx_EventTile_line
|
||||
{
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.mx_EventTile_searchHighlight {
|
||||
@@ -149,6 +118,10 @@ limitations under the License.
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.mx_EventTile_encrypting {
|
||||
color: #abddbc ! important;
|
||||
}
|
||||
|
||||
.mx_EventTile_sending {
|
||||
color: #ddd;
|
||||
}
|
||||
@@ -181,32 +154,29 @@ limitations under the License.
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mx_EventTile .mx_MessageTimestamp {
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mx_EventTile_last .mx_MessageTimestamp {
|
||||
.mx_EventTile_last .mx_MessageTimestamp,
|
||||
.mx_EventTile:hover .mx_MessageTimestamp,
|
||||
.mx_EventTile.menu .mx_MessageTimestamp
|
||||
{
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.mx_EventTile:hover .mx_MessageTimestamp {
|
||||
visibility: visible;
|
||||
.mx_EventTile_selected .mx_MessageTimestamp {
|
||||
left: 3px;
|
||||
}
|
||||
|
||||
.mx_EventTile_editButton {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
cursor: pointer;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
.mx_EventTile:hover .mx_EventTile_editButton {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.mx_EventTile.menu .mx_EventTile_editButton {
|
||||
.mx_EventTile:hover .mx_EventTile_editButton,
|
||||
.mx_EventTile.menu .mx_EventTile_editButton
|
||||
{
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@@ -219,6 +189,13 @@ limitations under the License.
|
||||
display: inline-block;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
top: 29px;
|
||||
}
|
||||
|
||||
.mx_EventTile_continuation .mx_EventTile_readAvatars,
|
||||
.mx_EventTile_info .mx_EventTile_readAvatars
|
||||
{
|
||||
top: 7px;
|
||||
}
|
||||
|
||||
.mx_EventTile_readAvatars .mx_BaseAvatar {
|
||||
@@ -231,3 +208,100 @@ limitations under the License.
|
||||
font-size: 11px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* all the overflow-y: hidden; are to trap Zalgos -
|
||||
but they introduce an implicit overflow-x: auto.
|
||||
so make that explicitly hidden too to avoid random
|
||||
horizontal scrollbars occasionally appearing, like in
|
||||
https://github.com/vector-im/vector-web/issues/1154
|
||||
*/
|
||||
.mx_EventTile_content {
|
||||
display: block;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
margin-right: 34px;
|
||||
}
|
||||
|
||||
/* De-zalgoing */
|
||||
.mx_EventTile_body {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
/* End to end encryption stuff */
|
||||
|
||||
.mx_EventTile_e2eIcon {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
left: 46px;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line,
|
||||
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line {
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line {
|
||||
border-left: #76cfa5 5px solid;
|
||||
}
|
||||
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line {
|
||||
border-left: #e8bf37 5px solid;
|
||||
}
|
||||
|
||||
.mx_EventTile:hover.mx_EventTile_verified .mx_MessageTimestamp,
|
||||
.mx_EventTile:hover.mx_EventTile_unverified .mx_MessageTimestamp {
|
||||
left: 3px;
|
||||
}
|
||||
|
||||
/*
|
||||
.mx_EventTile_verified .mx_EventTile_e2eIcon {
|
||||
display: none;
|
||||
}
|
||||
*/
|
||||
|
||||
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_e2eIcon,
|
||||
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_e2eIcon {
|
||||
display: block;
|
||||
left: 41px;
|
||||
}
|
||||
|
||||
/* Various markdown overrides */
|
||||
|
||||
.mx_EventTile_content .markdown-body {
|
||||
font-family: inherit ! important;
|
||||
white-space: normal ! important;
|
||||
line-height: inherit ! important;
|
||||
color: inherit;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* have to use overlay rather than auto otherwise Linux and Windows
|
||||
Chrome gets very confused about vertical spacing:
|
||||
https://github.com/vector-im/vector-web/issues/754
|
||||
*/
|
||||
.mx_EventTile_content .markdown-body pre {
|
||||
overflow-x: overlay;
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
.mx_EventTile_content .markdown-body h1,
|
||||
.mx_EventTile_content .markdown-body h2,
|
||||
.mx_EventTile_content .markdown-body h3,
|
||||
.mx_EventTile_content .markdown-body h4,
|
||||
.mx_EventTile_content .markdown-body h5,
|
||||
.mx_EventTile_content .markdown-body h6
|
||||
{
|
||||
font-family: inherit ! important;
|
||||
}
|
||||
|
||||
.mx_EventTile_content .markdown-body a {
|
||||
color: #76cfa6;
|
||||
}
|
||||
|
||||
.mx_EventTile_content .markdown-body .hljs {
|
||||
display: inline ! important;
|
||||
}
|
||||
|
||||
/* end of overrides */
|
||||
|
||||
@@ -50,7 +50,7 @@ limitations under the License.
|
||||
.mx_LinkPreviewWidget_description {
|
||||
margin-top: 8px;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.mx_LinkPreviewWidget_cancel {
|
||||
|
||||
@@ -15,14 +15,9 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MemberDeviceInfo {
|
||||
font-size: 12px;
|
||||
display: table-row;
|
||||
height: 17px;
|
||||
padding: 10px 0px;
|
||||
}
|
||||
|
||||
.mx_MemberDeviceInfo div {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.mx_MemberDeviceInfo_textButton {
|
||||
color: #fff;
|
||||
@@ -31,27 +26,44 @@ limitations under the License.
|
||||
text-align: center;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
width: 95px;
|
||||
border: 0px;
|
||||
font-size: 14px;
|
||||
|
||||
cursor: pointer;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.mx_MemberDeviceInfo_deviceId {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.mx_MemberDeviceInfo_deviceInfo {
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.mx_MemberDeviceInfo_block,
|
||||
.mx_MemberDeviceInfo_unblock {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_verified,
|
||||
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_unverified,
|
||||
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_blocked {
|
||||
color: #fff;
|
||||
width: 17px;
|
||||
border-radius: 17px;
|
||||
text-align: center;
|
||||
float: right;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_verified {
|
||||
background-color: #76cfa6;
|
||||
color: #76cfa5;
|
||||
}
|
||||
|
||||
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_unverified {
|
||||
background-color: #eca46f;
|
||||
color: #e8bf37;
|
||||
}
|
||||
|
||||
.mx_MemberDeviceInfo div.mx_MemberDeviceInfo_blocked {
|
||||
background-color: #e55e5e;
|
||||
color: #ba6363;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ limitations under the License.
|
||||
|
||||
.mx_MemberInfo {
|
||||
margin-top: 20px;
|
||||
padding-right: 20px;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@@ -24,9 +25,21 @@ limitations under the License.
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.mx_MemberInfo .mx_RoomTile_nameContainer {
|
||||
width: 154px;
|
||||
}
|
||||
|
||||
.mx_MemberInfo .mx_RoomTile_badge {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_MemberInfo .mx_RoomTile_name {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.mx_MemberInfo_cancel {
|
||||
float: right;
|
||||
margin-right: 18px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -74,7 +87,12 @@ limitations under the License.
|
||||
line-height: 23px;
|
||||
}
|
||||
|
||||
.mx_MemberInfo_devices {
|
||||
display: table;
|
||||
border-spacing: 5px;
|
||||
}
|
||||
.mx_MemberInfo_createRoom {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_MemberInfo_createRoom_label {
|
||||
width: initial ! important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,15 +52,29 @@ limitations under the License.
|
||||
flex: 1 1 0px;
|
||||
}
|
||||
|
||||
.mx_MemberList .mx_SearchableEntityList {
|
||||
order: 1;
|
||||
flex: 0 0 auto;
|
||||
-webkit-flex: 0 0 auto;
|
||||
.mx_MemberList_query {
|
||||
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #f0f0f0;
|
||||
padding: 9px;
|
||||
color: #454545;
|
||||
background-color: #fff;
|
||||
margin-left: 3px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
width: 189px;
|
||||
}
|
||||
|
||||
.mx_MemberList .mx_SearchableEntityList_expanded {
|
||||
flex: 1 0 0;
|
||||
-webkit-flex: 1 0 0;
|
||||
.mx_MemberList_query::-moz-placeholder {
|
||||
color: #454545;
|
||||
opacity: 0.5;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mx_MemberList_query::-webkit-input-placeholder {
|
||||
color: #454545;
|
||||
opacity: 0.5;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mx_MemberList_joined {
|
||||
|
||||
@@ -19,6 +19,7 @@ limitations under the License.
|
||||
vertical-align: middle;
|
||||
margin: auto;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_autocomplete_wrapper {
|
||||
@@ -46,6 +47,11 @@ limitations under the License.
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_e2eIcon {
|
||||
position: absolute;
|
||||
left: 44px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_noperm_error {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
@@ -54,26 +60,44 @@ limitations under the License.
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input_wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input {
|
||||
flex: 1;
|
||||
vertical-align: middle;
|
||||
min-height: 60px;
|
||||
max-height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
flex-direction: column;
|
||||
min-height: 60px;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
font-size: 14px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
.mx_MessageComposer_input_rte {
|
||||
border-top: 2px solid #76cfa6; /* placeholder RTE indicator */
|
||||
|
||||
.mx_MessageComposer_input_empty .public-DraftEditorPlaceholder-root {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input .DraftEditor-root {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
max-height: 120px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input blockquote {
|
||||
color: rgb(119, 119, 119);
|
||||
margin: 0 0 16px;
|
||||
padding: 0 15px;
|
||||
border-left: 4px solid rgb(221, 221, 221);
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input textarea {
|
||||
display: block;
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
margin-top: 6px;
|
||||
@@ -86,7 +110,9 @@ limitations under the License.
|
||||
box-shadow: none;
|
||||
color: #454545;
|
||||
background-color: #fff;
|
||||
|
||||
font-size: 14px;
|
||||
max-height: 120px;
|
||||
overflow: auto;
|
||||
/* needed for FF */
|
||||
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
|
||||
}
|
||||
@@ -120,3 +146,59 @@ limitations under the License.
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_formatting {
|
||||
cursor: pointer;
|
||||
margin: 0 11px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_formatbar_wrapper {
|
||||
width: 100%;
|
||||
background-color: #f7f7f7;
|
||||
box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.mx_MessageComposer_formatbar {
|
||||
margin: auto;
|
||||
max-width: 960px;
|
||||
display: flex;
|
||||
|
||||
height: 30px;
|
||||
|
||||
box-sizing: border-box;
|
||||
padding-left: 62px;
|
||||
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_formatbar * {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_format_button,
|
||||
.mx_MessageComposer_formatbar_cancel,
|
||||
.mx_MessageComposer_formatbar_markdown {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_format_button_disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_formatbar_cancel {
|
||||
margin-right: 22px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_formatbar_markdown {
|
||||
margin-right: 64px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input_markdownIndicator {
|
||||
cursor: pointer;
|
||||
height: 10px;
|
||||
padding: 4px 4px 4px 0;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_RoomList {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 12px;
|
||||
min-height: 400px;
|
||||
}
|
||||
@@ -33,3 +32,8 @@ limitations under the License.
|
||||
overflow-x: hidden ! important;
|
||||
overflow-y: scroll ! important;
|
||||
}
|
||||
|
||||
/* Make sure the scrollbar is above the sticky headers from RoomList */
|
||||
.mx_RoomList_scrollbar .gm-scrollbar.-vertical {
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,30 @@ limitations under the License.
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_leaveButton,
|
||||
.mx_RoomSettings_integrationsButton {
|
||||
height: 36px;
|
||||
background-color: #76cfa6;
|
||||
border-radius: 36px;
|
||||
margin-right: 8px;
|
||||
color: #fff;
|
||||
line-height: 34px;
|
||||
text-align: center;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_e2eIcon {
|
||||
padding-left: 4px;
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_leaveButton {
|
||||
margin-right: 32px;
|
||||
}
|
||||
|
||||
.mx_RoomSettings_powerLevels {
|
||||
display: table;
|
||||
}
|
||||
@@ -73,12 +97,14 @@ limitations under the License.
|
||||
height: 37px;
|
||||
border: 1px solid #979797;
|
||||
margin-right: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomSettings .mx_RoomSettings_roomColor_selected {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 4px;
|
||||
cursor: default ! important;
|
||||
}
|
||||
|
||||
.mx_RoomSettings .mx_RoomSettings_roomColorPrimary {
|
||||
|
||||
@@ -22,12 +22,24 @@ limitations under the License.
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.mx_RoomTile_tooltip {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: -54px;
|
||||
left: -12px;
|
||||
}
|
||||
|
||||
|
||||
.mx_RoomTile_nameContainer {
|
||||
display: inline-block;
|
||||
width: 180px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.mx_RoomTile_avatar_container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_RoomTile_avatar {
|
||||
display: inline-block;
|
||||
padding-top: 5px;
|
||||
@@ -39,7 +51,15 @@ limitations under the License.
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_RoomTile_avatar_container:hover:before,
|
||||
.mx_RoomTile_dm {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: -5px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.mx_RoomTile:hover .mx_RoomTile_avatar_container:before,
|
||||
.mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:before {
|
||||
display: block;
|
||||
position: absolute;
|
||||
@@ -47,31 +67,30 @@ limitations under the License.
|
||||
border-radius: 40px;
|
||||
background-image: url("img/icons_ellipsis.svg");
|
||||
background-size: 25px;
|
||||
left: 15px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.mx_RoomTile_avatar_container:hover:after,
|
||||
.mx_RoomTile:hover .mx_RoomTile_avatar_container:after,
|
||||
.mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
content: "";
|
||||
border-radius: 40px;
|
||||
background: #4A4A4A;
|
||||
top: 5px;
|
||||
bottom: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
opacity: 0.6;
|
||||
z-index: 2;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomTile_avatar_container:hover:before {
|
||||
.collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomTile_avatar_container:hover:after {
|
||||
.collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -90,18 +109,12 @@ limitations under the License.
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_RoomTile_ellipsis .mx_RoomTile_name {
|
||||
font-style: italic;
|
||||
color: #454545;
|
||||
}
|
||||
|
||||
.mx_RoomTile_invite {
|
||||
/* color: rgba(69, 69, 69, 0.5);
|
||||
*/
|
||||
/* color: rgba(69, 69, 69, 0.5); */
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomTile_nameContainer {
|
||||
height: 0;
|
||||
width: 60px; /* colapsed panel width */
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomTile_name {
|
||||
@@ -109,12 +122,11 @@ limitations under the License.
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomTile_badge {
|
||||
top: -2px;
|
||||
top: 0px;
|
||||
min-width: 12px;
|
||||
height: 16px;
|
||||
border-radius: 16px;
|
||||
padding: 0px 4px 0px 4px;
|
||||
z-index: 200;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
/* Hide the bottom of speech bubble */
|
||||
@@ -129,22 +141,22 @@ limitations under the License.
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 6px;
|
||||
border-top: 8px solid #ff0064;
|
||||
border-right: 10px solid transparent;
|
||||
margin-left: 5px;
|
||||
border-top: 5px solid #ff0064;
|
||||
border-right: 7px solid transparent;
|
||||
}
|
||||
|
||||
.mx_RoomTile_badge {
|
||||
display: inline-block;
|
||||
min-width: 19px;
|
||||
height: 17px;
|
||||
min-width: 15px;
|
||||
height: 15px;
|
||||
position: absolute;
|
||||
right: 8px; /*gutter */
|
||||
top: 9px;
|
||||
border-radius: 14px;
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 11px;
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
padding-top: 1px;
|
||||
padding-left: 4px;
|
||||
@@ -175,7 +187,7 @@ limitations under the License.
|
||||
}
|
||||
|
||||
.mx_RoomTile_selected {
|
||||
background-color: rgba(118,207,166,0.2);
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.mx_RoomTile .mx_RoomTile_name.mx_RoomTile_badgeShown {
|
||||
@@ -187,5 +199,3 @@ limitations under the License.
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.mx_RoomTile:hover {
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ limitations under the License.
|
||||
padding-bottom: 2px;
|
||||
margin-bottom: 6px;
|
||||
border-radius: 30px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.mx_TabCompleteBar_command .mx_TabCompleteBar_text {
|
||||
|
||||
@@ -45,3 +45,7 @@ limitations under the License.
|
||||
.mx_DevicesPanel_device > div {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.mx_DevicesPanel_myDevice {
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -14,20 +14,18 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_IntegrationsManager {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
-webkit-justify-content: center;
|
||||
.mx_IntegrationsManager .mx_Dialog {
|
||||
width: 60%;
|
||||
height: 70%;
|
||||
overflow: hidden;
|
||||
padding: 0px;
|
||||
max-width: initial;
|
||||
max-height: initial;
|
||||
}
|
||||
|
||||
.mx_IntegrationsManager iframe {
|
||||
background-color: #fff;
|
||||
border: 0px;
|
||||
width: 720px;
|
||||
height: 512px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -12,4 +12,14 @@ 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_CallView_voice {
|
||||
background-color: #76cfa6;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
padding: 6px;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
}
|
||||
65
src/skins/vector/css/vector-web/fonts.css
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Open Sans
|
||||
* Includes extended Latin, Greek, Cyrillic and Vietnamese character sets
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src: url('fonts/Open_Sans/OpenSans-Regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src: url('fonts/Open_Sans/OpenSans-Italic.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src: url('fonts/Open_Sans/OpenSans-Semibold.ttf') format('truetype');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src: url('fonts/Open_Sans/OpenSans-SemiboldItalic.ttf') format('truetype');
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src: url('fonts/Open_Sans/OpenSans-Bold.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src: url('fonts/Open_Sans/OpenSans-BoldItalic.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fira Mono
|
||||
* Used for monospace copy, i.e. code
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira Mono';
|
||||
src: url('fonts/Fira_Mono/FiraMono-Regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fira Mono';
|
||||
src: url('fonts/Fira_Mono/FiraMono-Bold.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -49,10 +49,11 @@ limitations under the License.
|
||||
flex: 1 1 0;
|
||||
|
||||
overflow-y: auto;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
.mx_LeftPanel.collapsed .mx_BottomLeftMenu {
|
||||
flex: 0 0 120px;
|
||||
flex: 0 0 160px;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_BottomLeftMenu {
|
||||
@@ -62,7 +63,7 @@ limitations under the License.
|
||||
-webkit-order: 3;
|
||||
order: 3;
|
||||
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border-top: 1px solid rgba(118, 207, 166, 0.2);
|
||||
margin-left: 16px; /* gutter */
|
||||
margin-right: 16px; /* gutter */
|
||||
-webkit-flex: 0 0 60px;
|
||||
@@ -78,23 +79,27 @@ limitations under the License.
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_directory,
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_people,
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_settings {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.collapsed .mx_BottomLeftMenu_createRoom,
|
||||
.collapsed .mx_BottomLeftMenu_directory,
|
||||
.collapsed .mx_BottomLeftMenu_createRoom,
|
||||
.collapsed .mx_BottomLeftMenu_people,
|
||||
.collapsed .mx_BottomLeftMenu_settings {
|
||||
margin-left: 0px ! important;
|
||||
margin-right: 0px ! important;
|
||||
padding-top: 3px ! important;
|
||||
padding-bottom: 3px ! important;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_directory {
|
||||
margin-left: 10px;
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_directory,
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_people {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_settings {
|
||||
@@ -104,3 +109,10 @@ limitations under the License.
|
||||
.mx_LeftPanel.collapsed .mx_BottomLeftMenu_settings {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_BottomLeftMenu_tooltip {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: -25px;
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
@@ -46,15 +46,15 @@ limitations under the License.
|
||||
margin-top: 6px;
|
||||
float: left;
|
||||
background-color: #fff;
|
||||
margin-left: -4px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.mx_RightPanel_headerButton {
|
||||
cursor: pointer;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
vertical-align: top;
|
||||
padding-left: 4px;
|
||||
padding-right: 5px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
@@ -86,8 +86,8 @@ limitations under the License.
|
||||
-ms-flex-order: 2;
|
||||
-webkit-order: 2;
|
||||
order: 2;
|
||||
flex: 1;
|
||||
-webkit-flex: 1;
|
||||
flex: 1 1 0;
|
||||
-webkit-flex: 1 1 0;
|
||||
}
|
||||
|
||||
.mx_RightPanel_footer {
|
||||
@@ -103,3 +103,30 @@ limitations under the License.
|
||||
-webkit-flex: 0 0 60px;
|
||||
flex: 0 0 60px;
|
||||
}
|
||||
|
||||
.mx_RightPanel_footer .mx_RightPanel_invite {
|
||||
line-height: 35px;
|
||||
font-size: 14px;
|
||||
color: #4A4A4A;
|
||||
padding-top: 13px;
|
||||
padding-left: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.collapsed .mx_RightPanel_footer .mx_RightPanel_invite {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_RightPanel_invite .mx_RightPanel_icon {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.mx_RightPanel_invite .mx_RightPanel_icon object {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.mx_RightPanel_invite .mx_RightPanel_message {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
padding-left: 10px
|
||||
}
|
||||
|
||||
@@ -46,15 +46,27 @@ limitations under the License.
|
||||
-webkit-flex-direction: column;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_input {
|
||||
margin: auto;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #c7c7c7;
|
||||
font-weight: 300;
|
||||
font-size: 13px;
|
||||
padding: 9px;
|
||||
.mx_RoomDirectory_list .mx_RoomView_messageListWrapper {
|
||||
justify-content: flex-start;
|
||||
-webkit-justify-content: flex-start;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_listheader {
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
border-spacing: 5px;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_searchbox {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_listheader .mx_NetworkDropdown {
|
||||
display: table-cell;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_tableWrapper {
|
||||
|
||||
@@ -20,23 +20,222 @@ limitations under the License.
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_labelContainer {
|
||||
height: 31px; /* mx_RoomSubList_label height including border */
|
||||
width: 235px; /* LHS Panel width */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_label {
|
||||
position: relative;
|
||||
text-transform: uppercase;
|
||||
color: #3d3b39;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
font-size: 12px;
|
||||
width: 203px; /* padding + width = LHS Panel width */
|
||||
height: 17px; /* padding + height = 29px, same as mx_RoomSubList_stickyContainer */
|
||||
padding-left: 16px; /* gutter */
|
||||
padding-right: 16px; /* gutter */
|
||||
margin-top: 8px;
|
||||
margin-bottom: 4px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
cursor: pointer;
|
||||
background-color: #d3efe1;
|
||||
border-top: solid 2px #eaf5f0;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_label.mx_RoomSubList_fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
/* pointer-events: none; */
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomSubList_label {
|
||||
height: 17px;
|
||||
width: 28px; /* collapsed LHS Panel width */
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomSubList_labelContainer {
|
||||
width: 28px; /* collapsed LHS Panel width */
|
||||
}
|
||||
|
||||
.mx_RoomSubList_roomCount {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: #76cfa6;
|
||||
padding-left: 5px;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomSubList_roomCount {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_badge {
|
||||
display: inline-block;
|
||||
min-width: 15px;
|
||||
height: 15px;
|
||||
position: absolute;
|
||||
right: 8px; /*gutter */
|
||||
top: 7px;
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
padding-top: 1px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
background-color: #76cfa6;
|
||||
}
|
||||
|
||||
/*
|
||||
.collapsed .mx_RoomSubList_badge {
|
||||
display: none;
|
||||
}
|
||||
*/
|
||||
|
||||
.mx_RoomSubList_badgeHighlight {
|
||||
background-color: #ff0064;
|
||||
}
|
||||
|
||||
/* This is the bottom of the speech bubble */
|
||||
.mx_RoomSubList_badgeHighlight:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 5px;
|
||||
border-top: 5px solid #ff0064;
|
||||
border-right: 7px solid transparent;
|
||||
}
|
||||
|
||||
/* Hide the bottom of speech bubble */
|
||||
.collapsed .mx_RoomSubList_badgeHighlight:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_chevron {
|
||||
padding-left: 4px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
right: 41px;
|
||||
top: 11px;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomSubList_chevron {
|
||||
padding-left: 12px;
|
||||
.mx_RoomSubList_chevronDown {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-top: 6px solid #76cfa6;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_chevronUp {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-bottom: 6px solid #76cfa6;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_chevronRight {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 5px solid transparent;
|
||||
border-left: 6px solid #76cfa6;
|
||||
border-bottom: 5px solid transparent;
|
||||
}
|
||||
|
||||
/* The overflow section */
|
||||
.mx_RoomSubList_ellipsis {
|
||||
display: block;
|
||||
line-height: 11px;
|
||||
height: 18px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomSubList_ellipsis {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_line {
|
||||
display: inline-block;
|
||||
width: 159px;
|
||||
border-top: dotted 2px #76cfa6;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomSubList_line {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_more {
|
||||
display: inline-block;
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
color: #76cfa6;
|
||||
padding-left: 7px;
|
||||
padding-right: 7px;
|
||||
padding-left: 7px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomSubList_more {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_moreBadge {
|
||||
display: inline-block;
|
||||
min-width: 15px;
|
||||
height: 13px;
|
||||
position: absolute;
|
||||
right: 8px; /*gutter */
|
||||
top: -2px;
|
||||
border-radius: 8px;
|
||||
border: solid 1px #76cfa6;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
padding-top: 1px;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
background-color: #fff;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_moreBadge.mx_RoomSubList_moreBadgeNotify {
|
||||
background-color: #76cfa6;
|
||||
border: 0;
|
||||
padding-top: 3px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_moreBadge.mx_RoomSubList_moreBadgeHighlight {
|
||||
background-color: #ff0064;
|
||||
border: 0;
|
||||
padding-top: 3px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.collapsed .mx_RoomSubList_moreBadge {
|
||||
position: static;
|
||||
margin-left: 16px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.mx_RoomSubList_ellipsis .mx_RoomSubList_chevronDown {
|
||||
position: relative;
|
||||
top: 4px;
|
||||
left: 2px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
Copyright 2016 Aviral Dasgupta
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -14,23 +14,11 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MultiInviteDialog ul {
|
||||
height: 300px;
|
||||
overflow-y: auto;
|
||||
.mx_ChangelogDialog_content {
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.mx_MultiInviteDialog li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.mx_MultiInviteDialog_statusText {
|
||||
text-indent: 20px;
|
||||
}
|
||||
|
||||
.mx_MultiInviteDialog p.error {
|
||||
color: #ff0064;
|
||||
}
|
||||
|
||||
.mx_MultiInviteDialog p.invited {
|
||||
color: #76cfa6;
|
||||
.mx_ChangelogDialog_li {
|
||||
padding: 0.2em;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright 2015, 2016 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_NetworkDropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_input {
|
||||
position: relative;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #c7c7c7;
|
||||
font-weight: 300;
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_arrow {
|
||||
border-color: #4a4a4a transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 5px 0;
|
||||
display: block;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 14px;
|
||||
width: 0
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_networkoption {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_networkoption img {
|
||||
margin: 5px;
|
||||
width: 25px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
input.mx_NetworkDropdown_networkoption, input.mx_NetworkDropdown_networkoption:focus {
|
||||
border: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_menu {
|
||||
position: absolute;
|
||||
left: -1px;
|
||||
right: -1px;
|
||||
top: 100%;
|
||||
z-index: 2;
|
||||
margin: 0;
|
||||
padding: 0px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #76cfa6;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_menu .mx_NetworkDropdown_networkoption:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.mx_NetworkDropdown_menu_network {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -54,3 +54,7 @@ limitations under the License.
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.mx_MatrixToolbar_action {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ limitations under the License.
|
||||
font-size: 13px;
|
||||
margin-left: 18px;
|
||||
margin-right: 18px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 7px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
border: 1px dashed #76cfa6;
|
||||
|
||||
@@ -16,17 +16,38 @@ limitations under the License.
|
||||
|
||||
.mx_RoomTooltip_chevron {
|
||||
position: absolute;
|
||||
left: -9px;
|
||||
top: 7px;
|
||||
left: -8px;
|
||||
top: 4px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 8px solid transparent;
|
||||
border-right: 8px solid rgba(187, 187, 187, 0.5);
|
||||
border-bottom: 8px solid transparent;
|
||||
}
|
||||
|
||||
.mx_RoomTooltip_chevron:after{
|
||||
content:'';
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 7px solid transparent;
|
||||
border-right: 7px solid #fff;
|
||||
border-bottom: 7px solid transparent;
|
||||
position:absolute;
|
||||
top: -7px;
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
.mx_RoomTooltip {
|
||||
display: none;
|
||||
position: fixed;
|
||||
border: 1px solid #a4a4a4;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(187, 187, 187, 0.5);
|
||||
border-radius: 5px;
|
||||
background-color: #fff;
|
||||
z-index: 2000;
|
||||
left: 52px;
|
||||
padding: 6px;
|
||||
padding: 5px;
|
||||
pointer-events: none;
|
||||
line-height: 14px;
|
||||
font-size: 13px;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
|
||||
BIN
src/skins/vector/fonts/Fira_Mono/FiraMono-Bold.ttf
Executable file
BIN
src/skins/vector/fonts/Fira_Mono/FiraMono-Regular.ttf
Executable file
92
src/skins/vector/fonts/Fira_Mono/OFL.txt
Executable file
@@ -0,0 +1,92 @@
|
||||
Copyright (c) 2012-2013, The Mozilla Corporation and Telefonica S.A.
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
@@ -1,48 +0,0 @@
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Lato Light'), local('Lato-Light'), url(IY9HZVvI1cMoAHxvl0w9LVKPGs1ZzpMvnHX-7fPOuAc.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Lato Light'), local('Lato-Light'), url(22JRxvfANxSmnAhzbFH8PgLUuEpTyoUstqEm5AMlJo4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Lato Regular'), local('Lato-Regular'), url(8qcEw_nrk_5HEcCpYdJu8BTbgVql8nDJpwnrE27mub0.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Lato Regular'), local('Lato-Regular'), url(MDadn8DQ_3oT6kvnUq_2r_esZW2xOQ-xsNqO47m55DA.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Lato Bold'), local('Lato-Bold'), url(rZPI2gHXi8zxUjnybc2ZQFKPGs1ZzpMvnHX-7fPOuAc.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Lato Bold'), local('Lato-Bold'), url(MgNNr5y1C_tIEuLEmicLmwLUuEpTyoUstqEm5AMlJo4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans'), local('OpenSans'), url(opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format('woff2'), url(Open_Sans/OpenSans-Regular.ttf) format('truetype');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(opensans/v13/MTP_ySUJH_bn48VBG8sNShampu5_7CjHW5spxoeN3Vs.woff2) format('woff2'), url(Open_Sans/OpenSans-Semibold.ttf) format('truetype');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Open Sans Bold'), local('OpenSans-Bold'), url(opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2) format('woff2'), url(Open_Sans/OpenSans-Bold.ttf) format('truetype');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
BIN
src/skins/vector/fonts/Open_Sans/OpenSans-BoldItalic.ttf
Executable file
BIN
src/skins/vector/fonts/Open_Sans/OpenSans-Italic.ttf
Executable file
BIN
src/skins/vector/fonts/Open_Sans/OpenSans-SemiboldItalic.ttf
Executable file
15
src/skins/vector/img/avatar-error.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: sketchtool 39.1 (31720) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>5EF602F6-A36C-41EE-BAEC-50801DFD5492</title>
|
||||
<desc>Created with sketchtool.</desc>
|
||||
<defs></defs>
|
||||
<g id="1:1-chat" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Chat-People-2c-Invite-modal-ERROR" transform="translate(-611.000000, -358.000000)">
|
||||
<g id="avatar_error" transform="translate(611.000000, 358.000000)">
|
||||
<circle id="Oval-2" fill="#FF0064" cx="12.5" cy="12.5" r="12.5"></circle>
|
||||
<path d="M11.2470703,15.0292969 C11.2470703,14.5901671 11.2733559,14.2082536 11.3259277,13.8835449 C11.3784996,13.5588363 11.4650873,13.2619642 11.5856934,12.9929199 C11.7062994,12.7238756 11.8624665,12.4687512 12.0541992,12.2275391 C12.2459319,11.9863269 12.4809556,11.7296563 12.7592773,11.4575195 C12.9695649,11.2534169 13.1659333,11.0601409 13.3483887,10.8776855 C13.530844,10.6952302 13.6916497,10.508139 13.8308105,10.3164062 C13.9699714,10.1246735 14.0797522,9.920574 14.1601562,9.70410156 C14.2405603,9.48762913 14.2807617,9.2464206 14.2807617,8.98046875 C14.2807617,8.39908563 14.1369643,7.9553238 13.8493652,7.64916992 C13.5617661,7.34301605 13.1396512,7.18994141 12.5830078,7.18994141 C12.3603504,7.18994141 12.1438813,7.22086558 11.9335938,7.28271484 C11.7233062,7.34456411 11.5346688,7.44352146 11.3676758,7.57958984 C11.2006828,7.71565823 11.0661626,7.88883358 10.9641113,8.09912109 C10.86206,8.3094086 10.8110352,8.5629868 10.8110352,8.85986328 L8.55664062,8.85986328 C8.56282555,8.27848017 8.66951394,7.76668515 8.87670898,7.32446289 C9.08390403,6.88224063 9.36840639,6.51115059 9.73022461,6.21118164 C10.0920428,5.91121269 10.515704,5.68546625 11.0012207,5.53393555 C11.4867375,5.38240484 12.0139946,5.30664062 12.5830078,5.30664062 C13.2076854,5.30664062 13.7643205,5.38704347 14.2529297,5.54785156 C14.7415389,5.70865966 15.1559228,5.94368335 15.4960938,6.25292969 C15.8362647,6.56217603 16.0944815,6.9394509 16.270752,7.38476562 C16.4470224,7.83008035 16.5351562,8.33414432 16.5351562,8.89697266 C16.5351562,9.30517782 16.4702155,9.68554511 16.340332,10.0380859 C16.2104486,10.3906268 16.0372732,10.7215154 15.8208008,11.0307617 C15.6043283,11.3400081 15.356935,11.6368801 15.0786133,11.9213867 C14.8002916,12.2058933 14.5126968,12.4873033 14.2158203,12.765625 C13.8756493,13.0748713 13.6483567,13.413491 13.5339355,13.7814941 C13.4195144,14.1494973 13.3592123,14.5654274 13.3530273,15.0292969 L11.2470703,15.0292969 Z M11.0893555,17.9145508 C11.0893555,17.7413728 11.1171872,17.5805671 11.1728516,17.4321289 C11.2285159,17.2836907 11.310465,17.1538092 11.4187012,17.0424805 C11.5269374,16.9311518 11.6599113,16.8445641 11.817627,16.7827148 C11.9753426,16.7208656 12.156249,16.6899414 12.3603516,16.6899414 C12.5644541,16.6899414 12.7453605,16.7208656 12.9030762,16.7827148 C13.0607918,16.8445641 13.1937657,16.9311518 13.302002,17.0424805 C13.4102382,17.1538092 13.4937334,17.2836907 13.5524902,17.4321289 C13.611247,17.5805671 13.640625,17.7413728 13.640625,17.9145508 C13.640625,18.2547218 13.529298,18.5392241 13.3066406,18.7680664 C13.0839833,18.9969087 12.7685567,19.1113281 12.3603516,19.1113281 C11.9521464,19.1113281 11.6382661,18.9969087 11.4187012,18.7680664 C11.1991363,18.5392241 11.0893555,18.2547218 11.0893555,17.9145508 L11.0893555,17.9145508 Z" id="?" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
BIN
src/skins/vector/img/button-md-false.png
Normal file
|
After Width: | Height: | Size: 569 B |
29
src/skins/vector/img/button-md-false.svg
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="23px" height="15px" viewBox="0 0 23 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: sketchtool 39 (31667) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>D335F9E8-C813-47D7-B1BE-C8DEF2C8214F</title>
|
||||
<desc>Created with sketchtool.</desc>
|
||||
<defs>
|
||||
<text id="text-1" font-family="markdown" font-size="14" font-weight="normal" fill="#DDDDDD">
|
||||
<tspan x="829.125" y="759"></tspan>
|
||||
</text>
|
||||
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-2">
|
||||
<feOffset dx="1" dy="1" in="SourceAlpha" result="shadowOffsetInner1"></feOffset>
|
||||
<feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"></feComposite>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0526494565 0" type="matrix" in="shadowInnerInner1"></feColorMatrix>
|
||||
</filter>
|
||||
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-3">
|
||||
<feOffset dx="1" dy="1" in="SourceAlpha" result="shadowOffsetInner1"></feOffset>
|
||||
<feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"></feComposite>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0526494565 0" type="matrix" in="shadowInnerInner1"></feColorMatrix>
|
||||
</filter>
|
||||
</defs>
|
||||
<g id="Screens-revised" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" fill-opacity="1">
|
||||
<g id="02_x-Chat-text-input-markdown-panel-MD_off-BUTTONS-ON" transform="translate(-829.000000, -745.000000)" fill="#DDDDDD">
|
||||
<g id="button_md_off">
|
||||
<use filter="url(#filter-2)" xlink:href="#text-1"></use>
|
||||
<use filter="url(#filter-3)" xlink:href="#text-1"></use>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/skins/vector/img/button-md-false@2x.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/skins/vector/img/button-md-false@3x.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/skins/vector/img/button-md-true.png
Normal file
|
After Width: | Height: | Size: 483 B |
14
src/skins/vector/img/button-md-true.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="23px" height="15px" viewBox="0 0 23 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: sketchtool 39 (31667) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>2A63B135-4281-4FBB-A88C-012AE22E9594</title>
|
||||
<desc>Created with sketchtool.</desc>
|
||||
<defs></defs>
|
||||
<g id="Screens-revised" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" font-size="14" font-family="markdown" font-weight="normal">
|
||||
<g id="02_x-Chat-text-input-markdown-panel-MD_on" transform="translate(-829.000000, -745.000000)" fill="#4A4A4A">
|
||||
<text id="button_markdown_on">
|
||||
<tspan x="829.125" y="759"></tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 820 B |
BIN
src/skins/vector/img/button-md-true@2x.png
Normal file
|
After Width: | Height: | Size: 906 B |
BIN
src/skins/vector/img/button-md-true@3x.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |