Compare commits

...

197 Commits

Author SHA1 Message Date
Luke Barnard
533ca9f3c6 Merge branch 'develop' into luke/new-guest-access-set-mxid-2 2017-05-11 09:48:05 +01:00
Luke Barnard
ab24994e37 Move general CSS to more specific so as not to affect other dialogs 2017-05-11 09:42:21 +01:00
Luke Barnard
98f62d0300 NL at EOF 2017-05-11 09:40:06 +01:00
Luke Barnard
2e49014ffe CSS for mxIdDialog redesign 2017-05-11 09:33:52 +01:00
David Baker
e67e891040 Merge pull request #3877 from vector-im/t3chguy/electron_install_fix
move electron -> electron_app because npm smart
2017-05-10 13:48:18 +01:00
Michael Telatynski
c607b1bc89 npm is "smart" enough to try and install our electron wrapper as a module
instead of the actual electron package. With no way to ignore directories.
I'd like to think of this as temporary, until I get to rip apart riot-web
and riot-electron

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-05-10 13:36:27 +01:00
Richard van der Hoff
41738ec025 Merge pull request #3863 from vector-im/rav/bug_report_endpoint
Fix bug report endpoint in config.sample.json.
2017-05-09 12:34:40 +01:00
Richard van der Hoff
f9ae456a64 Fix bug report endpoint in config.sample.json.
Not sure why this was like this - has vector.im/bugs *ever* worked?
2017-05-09 12:27:41 +01:00
David Baker
1b78737f12 Merge pull request #3817 from vector-im/luke/password-nag-bar
Implement PasswordNagBar
2017-05-08 15:00:37 +01:00
David Baker
2983b36d4c Merge pull request #3851 from vector-im/dbkr/missed_icons
Update 2 missed icons to the new icon
2017-05-08 13:12:00 +01:00
David Baker
640aa98cf4 Update 2 missed icons to the new icon
Electron icons for windows & Linux. Also add them to the script
that makes all the icon versions.
2017-05-08 13:05:17 +01:00
David Baker
e6133820a2 Merge pull request #3804 from vector-im/dbkr/left_panel_for_newbies_2
Make left panel better for new users (mk II)
2017-05-08 10:37:59 +01:00
Luke Barnard
5766a6e93d Give warning icon better alt 2017-05-08 10:02:05 +01:00
Luke Barnard
c783f701dd reskindex 2017-05-08 10:01:18 +01:00
Matthew Hodgson
d1db602b3a Merge pull request #3839 from vector-im/t3chguy/patch-1
match primary package.json
2017-05-07 20:34:18 +01:00
Michael Telatynski
ea72e9c7a0 match primary package.json
got mismatched after a release -> develop merge
2017-05-07 20:33:13 +01:00
Matthew Hodgson
8e94d5240f merge master into develop post 0.9.9 2017-05-07 19:58:42 +01:00
Matthew Hodgson
1e5908a31e speed up burndown generation by ~250x 2017-05-07 19:34:16 +01:00
David Baker
40c98fc84f Merge pull request #3829 from vector-im/t3chguy/productName-missing
Re-add productName
2017-05-06 12:20:30 +01:00
Michael Telatynski
9c6b3819a5 Re-add productName
so that electron-builder packages is as Riot rather than riot-web
2017-05-06 10:24:13 +01:00
David Baker
6013a3e71d Merge pull request #3683 from t3chguy/t3chguy/electron_version_inconsistency
Remove leading v in /version file, for SemVer and to match Electron ver
2017-05-05 18:28:16 +01:00
David Baker
0deed1b511 Merge pull request #3790 from t3chguy/patch-2
Fix scope of callback
2017-05-05 18:25:29 +01:00
David Baker
2c36506342 Merge pull request #3622 from t3chguy/t3chguy/electron-persist-window-layout
Remember and Recall window layout/position state
2017-05-05 18:23:15 +01:00
Michael Telatynski
309afdb813 no point installing deps here, builder will do it for us
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-05-05 17:08:50 +01:00
Michael Telatynski
1ed1080bf3 Update README with npm run electron
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-05-05 17:05:03 +01:00
Michael Telatynski
a09f890619 Merge package.json, match version in electron/package.json
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-05-05 17:03:28 +01:00
Michael Telatynski
499b04c254 Only install electron deps when we're bundling/running electron
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-05-05 17:01:32 +01:00
Michael Telatynski
8a50207189 Change shebang to bash for string manipulations
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-05-05 16:57:18 +01:00
Michael Telatynski
f54708227e Proper two package.json format, release.sh bumps 2nd json ver too
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-05-05 16:54:55 +01:00
Luke Barnard
f14c2a0a71 Implement PasswordNagBar
This will tell the user that they need to set a password to return to their account.
2017-05-05 16:30:18 +01:00
David Baker
c27f39714a Dedicated classes for the buttons 2017-05-05 14:26:13 +01:00
Luke Barnard
e1cd046c1a Prevent zalgo-like text overflowing MELS summary 2017-05-05 09:54:00 +01:00
Luke Barnard
ae76c76558 Fix #3450 - RM hidden by things 2017-05-04 21:27:33 +01:00
David Baker
1001c98a3c Align buttons better with the text 2017-05-04 18:23:04 +01:00
David Baker
23a141c5ad Remove slightly misleading commented code 2017-05-04 17:46:44 +01:00
Luke Barnard
8731e46900 Merge pull request #3808 from vector-im/dbkr/remove_babelcheck
Remove babelcheck
2017-05-04 17:45:59 +01:00
David Baker
da960e776d Remove commented code 2017-05-04 17:45:11 +01:00
David Baker
d419024da9 Merge pull request #3809 from vector-im/rav/include_mx_id_in_rageshake
Include MXID and device id in rageshakes
2017-05-04 17:30:51 +01:00
Richard van der Hoff
45efdbdd43 Include MXID and device id in rageshakes
- to make for easier triage
2017-05-04 17:21:16 +01:00
David Baker
7b320f8fbb Remove babelcheck
Nobody is likley to be upgrading from babel 5 any more, so this
can go away now.
2017-05-04 16:51:36 +01:00
David Baker
e6e2e6989a Merge pull request #3791 from t3chguy/patch-3
import Modal
2017-05-04 16:35:15 +01:00
David Baker
2bf0074953 Make bottom left menu buttons use RoleButton too 2017-05-04 15:38:53 +01:00
David Baker
ff709ed8b1 Fix import 2017-05-04 14:53:13 +01:00
David Baker
cbb32968f1 Merge remote-tracking branch 'origin/develop' into dbkr/left_panel_for_newbies_2 2017-05-04 14:04:33 +01:00
David Baker
095da68aac Add buttons to room sub list headers 2017-05-04 13:58:17 +01:00
Michael Telatynski
9997cc9891 import Modal
class seems to be referring to Modal but does not import it
2017-05-02 22:27:30 +01:00
Michael Telatynski
d5009962cd Fix scope of callback
This may have led to the room list not refreshing on error of deleting alias
2017-05-02 22:19:32 +01:00
Michael Telatynski
6367344181 tidy and fix flow notation
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-05-02 21:32:34 +01:00
Michael Telatynski
61c338a233 remove leading v in /version file so its semver
and also then consistent with electron versioning

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-05-02 21:32:27 +01:00
Luke Barnard
425719c72e Merge pull request #3762 from vector-im/luke/new-guest-access-set-mxid
CSS for new SetMxIdDialog
2017-05-02 14:15:28 +01:00
Matthew Hodgson
9f3c1deae6 Merge pull request #3775 from t3chguy/patch-1
Pin filesize ver to fix break upstream
2017-04-30 13:11:33 +01:00
Michael Telatynski
4a8ad53bd9 Pin filesize ver to fix break upstream
https://travis-ci.org/vector-im/riot-web/builds/227340622
avoidwork/filesize.js#87
3.5.7 and 3.5.8 ver released <24h ago and broke stuff for us
2017-04-30 13:11:01 +01:00
Matthew Hodgson
67efb8bde2 Add date tooltip to timestamps 2017-04-29 00:00:37 +01:00
Luke Barnard
d7b2f0d3be CSS for new SetMxIdDialog 2017-04-28 14:32:08 +01:00
David Baker
96c867b34b Make left panel more friendly to new users
https://github.com/vector-im/riot-web/issues/3609
2017-04-28 11:23:13 +01:00
David Baker
4eb0ca63a9 Revert commits acciderntally put on develop 2017-04-28 11:22:05 +01:00
David Baker
73fb2c859e Remove now-redundant grey CSS 2017-04-28 11:20:55 +01:00
David Baker
431b8aaefa Make left panel more friendly to new users
https://github.com/vector-im/riot-web/issues/3609
2017-04-28 11:10:41 +01:00
David Baker
b637ab33cc Merge pull request #3751 from vector-im/luke/room-directory-improve
Improve Room Directory Look & Feel
2017-04-27 18:28:25 +01:00
Luke Barnard
afb4b79d81 Improve Room Directory Look & Feel
By adding an icon next to the title.
Requires https://github.com/matrix-org/matrix-react-sdk/pull/848
2017-04-27 18:04:41 +01:00
Luke Barnard
5defd0bb74 Merge branch 'develop' of github.com:vector-im/vector-web into develop 2017-04-27 16:46:21 +01:00
Luke Barnard
e6f694307d add word-break to RoomDirectory 2017-04-27 16:46:14 +01:00
David Baker
beefcfcb8c Merge pull request #3742 from vector-im/luke/fix-emotes-rrs
Fix emote RRs alignment
2017-04-26 18:25:27 +01:00
Luke Barnard
44d0e7dcba Fix emote RRs alignment 2017-04-26 18:00:51 +01:00
Luke Barnard
71685b5eab Merge pull request #3741 from vector-im/dbkr/remove_unused_droptarget_placeholder
Remove unused `placeholder` prop on RoomDropTarget
2017-04-26 16:46:47 +01:00
David Baker
7b3719bc3c Remove unused placeholder prop on RoomDropTarget 2017-04-26 16:27:25 +01:00
David Baker
c070e86c1f Merge pull request #3732 from vector-im/luke/css-improve-country-dd
Modify CSS for matrix-org/matrix-react-sdk#833
2017-04-26 10:28:07 +01:00
Luke Barnard
78cabed0bf Modify CSS for matrix-org/matrix-react-sdk#833 2017-04-25 16:24:00 +01:00
David Baker
bf88620581 Merge pull request #3727 from vector-im/dbkr/warn_when_single_instance_quit
Warn when exiting due to single-instance
2017-04-25 11:18:19 +01:00
David Baker
777087504a Merge branch 'release-v0.9.9' 2017-04-25 11:12:14 +01:00
David Baker
aa482bae28 v0.9.9 2017-04-25 11:08:08 +01:00
David Baker
6fd64d19f0 Prepare changelog for v0.9.9 2017-04-25 11:08:07 +01:00
David Baker
2d311ddbf4 Released js-sdk & react-sdk 2017-04-25 11:04:03 +01:00
David Baker
e24ef2bb5c Warn when exiting due to single-instance
This lost me a fair bit of time trying to figure out why Riot was
starting and then immediately quitting.
2017-04-25 10:18:17 +01:00
Matthew Hodgson
4dd6ee681d fix /config.json in .gitignore 2017-04-25 00:14:24 +01:00
Matthew Hodgson
ef057e4693 Merge pull request #3709 from t3chguy/electron_notification_causes_weirdness_onclick
Electron forgets it was maximized when you click on a notification
2017-04-25 00:10:20 +01:00
Matthew Hodgson
f53b238c24 Merge pull request #3719 from turt2live/travis/h1-h2-to-h3
CSS to make h1 and h2 the same size as h1.
2017-04-25 00:08:07 +01:00
Matthew Hodgson
7957eeba10 Merge pull request #3721 from vector-im/luke/css-fix-long-room-names
Prevent long room names/topics from pushing UI of the screen
2017-04-25 00:07:41 +01:00
Matthew Hodgson
95931918dc Merge pull request #3717 from vector-im/luke/css-disable-dd-highlight
Disable dropdown highlight on focus
2017-04-25 00:07:13 +01:00
David Baker
5326faa0b8 v0.9.9-rc.2 2017-04-24 18:26:20 +01:00
David Baker
7f2fa09d4c Prepare changelog for v0.9.9-rc.2 2017-04-24 18:26:19 +01:00
David Baker
b6435502fc New version of react-sdk 2017-04-24 18:25:13 +01:00
David Baker
1701ea43a4 Remove spurious changelog entries 2017-04-24 18:22:23 +01:00
Luke Barnard
69f5833c9f Prevent long room names/topics from pushing UI of the screen
This was causing the "save" button in RoomSettings to be obscured when room names were set to long strings without spaces

Fixes https://github.com/vector-im/riot-web/issues/1729
2017-04-24 16:05:49 +01:00
turt2live
61bba6c31f CSS to make h1 and h2 the same size as h1.
Addresses #1772

Signed-off-by: Travis Ralston <travpc@gmail.com>
2017-04-24 08:44:53 -06:00
Luke Barnard
c067800a4f Disable dropdown highlight on focus 2017-04-24 10:00:39 +01:00
Matthew Hodgson
af105b1920 moar padding for _TopUnreadMessagesBar.scss 2017-04-24 01:17:17 +01:00
Matthew Hodgson
a414352661 re-add img to _TopUnreadMessagesBar.scss 2017-04-24 01:13:24 +01:00
Matthew Hodgson
57f91086e6 add bullseye icon for 'Jump to first unread message' 2017-04-24 01:08:09 +01:00
Michael Telatynski
9e2324fb69 don't hook on postinstall, current dev cycle uses (abuses) npm i to build
so no point making it take longer than it has to for the devs only testing
webapp

build:electron - hook npm run install:electron
install:electron - run npm i for the electron deps
electron - start the app locally for testing

add to README

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-23 22:50:58 +01:00
Michael Telatynski
b3c9229aee DRY code and change double quotes to single
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-23 09:59:00 +01:00
Michael Telatynski
2139fb74bb change show logic to same as that of the tray icon
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-23 09:56:43 +01:00
Matthew Hodgson
8b4ab4bcdd update room directory icon to something that looks like a room list 2017-04-23 03:14:41 +01:00
Matthew Hodgson
40eceaf9bc show err.message in errors if present 2017-04-23 02:22:31 +01:00
Matthew Hodgson
ab5ec04507 oops 2017-04-23 01:01:38 +01:00
Matthew Hodgson
b1ff0b9e65 hook up keyb shortcuts for roomdir 2017-04-23 01:00:25 +01:00
Matthew Hodgson
be52787473 better solution to incomingcallbox weirdness 2017-04-22 17:37:16 +01:00
Matthew Hodgson
b3431bb750 fix incoming call box 2017-04-22 17:28:09 +01:00
Matthew Hodgson
4864716abb Merge pull request #3564 from t3chguy/t3chguy/malformed-notifications-gnome-kde
Escape HTML Tags from Linux Notifications (electron)
2017-04-22 16:45:04 +01:00
Matthew Hodgson
8a6283fedf Merge pull request #3651 from t3chguy/t3chguy/show_access_token
styling for spoilerized access token view in Settings
2017-04-22 16:22:48 +01:00
Matthew Hodgson
634cf528b4 Merge pull request #3690 from t3chguy/fix_webpack_config
Fix Webpack conf
2017-04-22 16:14:19 +01:00
Michael Telatynski
0da6ca8aea add more comment to explain this weirdness
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-22 16:05:08 +01:00
Michael Telatynski
08fb20a0df use a character class for brevity
add a comment so this madness has meaning

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-22 14:02:18 +01:00
Michael Telatynski
a8e4a2158a move styling to correct place
NOTE TO SELF
1:1 mapping between react component to scss file.
Makes sense...

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-22 04:33:47 +01:00
Matthew Hodgson
2f3e389a68 Merge pull request #3599 from coletivoEITA/develop
Add config.json to .gitignore
2017-04-22 03:11:17 +01:00
Matthew Hodgson
fb3ef89b50 Merge pull request #3641 from t3chguy/t3chguy/electron_launch_hidden
add command line arg (--hidden) for electron app
2017-04-22 03:02:48 +01:00
Matthew Hodgson
523b315985 Merge pull request #3640 from t3chguy/t3chguy/lightbox_download_button
fix ImageView Download functionality
2017-04-22 02:59:17 +01:00
Matthew Hodgson
36f08cf73c Merge pull request #3693 from t3chguy/cross-env
Add cross-env into the mix
2017-04-22 02:40:23 +01:00
Matthew Hodgson
5c00af7123 Merge pull request #3694 from turt2live/travis/remember-unsupported-browser
Remember acceptance for unsupported browsers.
2017-04-22 02:17:37 +01:00
Matthew Hodgson
38fa9f78f1 prefix localstorage key as per the convention 2017-04-22 02:17:22 +01:00
Matthew Hodgson
8a9b750b31 apply focus filter to normal buttons too 2017-04-22 01:55:57 +01:00
Matthew Hodgson
26ebd20956 improve logo cosmetics 2017-04-22 01:19:11 +01:00
turt2live
e877ad2e63 Remember acceptance for unsupported browsers.
Addresses #3624.

This stores the flag in localStorage, after checking if localStorage is available. If localStorage is not available, the user will be prompted just like before this commit.

Signed-off-by: Travis Ralston <travpc@gmail.com>
2017-04-21 16:08:49 -06:00
Michael Telatynski
dd7f9e2d5f argh, fix eslint false positives
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-21 19:00:24 +01:00
David Baker
141aafd18e v0.9.9-rc.1 2017-04-21 18:40:25 +01:00
David Baker
8aed52ece9 Prepare changelog for v0.9.9-rc.1 2017-04-21 18:40:24 +01:00
David Baker
ce5a7ba48a Rewind version to try again, again 2017-04-21 18:39:11 +01:00
David Baker
95647fb7a1 v0.9.9-rc.1 2017-04-21 18:35:15 +01:00
David Baker
d0c0eeac0a Prepare changelog for v0.9.9-rc.1 2017-04-21 18:35:14 +01:00
David Baker
f25612198e 0.9.8, not 0.9.9 2017-04-21 18:33:53 +01:00
David Baker
ca6d9063fd Back up release version to try again 2017-04-21 18:32:55 +01:00
David Baker
eec0c274d2 v0.9.9-rc.1 2017-04-21 18:26:29 +01:00
David Baker
b5a5b472c4 Prepare changelog for v0.9.9-rc.1 2017-04-21 18:26:29 +01:00
David Baker
9747836a4d Update react-sdk and js-sdk dependencies 2017-04-21 18:24:29 +01:00
Luke Barnard
2afe9e6928 Merge pull request #3692 from vector-im/luke/login-ui
Cosmetics to go with matrix-org/matrix-react-sdk#811
2017-04-21 17:40:53 +01:00
Luke Barnard
f010afe63f Add emojione PNGs to the COPY_LIST 2017-04-21 17:36:48 +01:00
Michael Telatynski
60b280f166 Add cross-env into the mix
this way `npm run build` will work on Windows too :D

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-21 17:16:53 +01:00
Luke Barnard
a2b465e352 Remove old logo 2017-04-21 17:14:59 +01:00
Luke Barnard
1e139ef183 Cosmetics to go with matrix-org/matrix-react-sdk#811 2017-04-21 17:04:11 +01:00
Michael Telatynski
9b38a97110 Fix Webpack conf
+ conform to a bit more eslint (IDE makes my eyes hurt)
+ specify windows-specific copies of noParse regexes to stop the olm error

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-21 15:09:45 +01:00
Matthew Hodgson
9c27075175 Merge pull request #3680 from t3chguy/t3chguy/escape_cancel_search_focus_composer
Cancel quicksearch on ESC
2017-04-21 01:27:04 +01:00
Michael Telatynski
52a119244b Cancel quick-search on Escape, clearing it and returning focus to composer.
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-21 01:21:25 +01:00
Matthew Hodgson
ddd12edc06 clear the searchbox after quick-search 2017-04-20 14:21:36 +01:00
Matthew Hodgson
8f20fcfa6b Merge pull request #3654 from vector-im/matthew/quick-search
Optimise RoomList and implement quick-search functionality on it.
2017-04-20 11:26:08 +01:00
Matthew Hodgson
c1d30664de pass through selectedRoom 2017-04-20 01:13:13 +01:00
Matthew Hodgson
1803a0df9e select any existing filter text on ctrl-k 2017-04-20 00:04:08 +01:00
Matthew Hodgson
a5bd8bd034 bump react-gemini-scrollbar 2017-04-19 23:35:06 +01:00
Matthew Hodgson
751f715e77 fix focus highlight on bright theme 2017-04-19 02:29:10 +01:00
Matthew Hodgson
a5bd8b36b8 fix focus highlight on bright theme 2017-04-19 02:28:16 +01:00
Matthew Hodgson
e780fe4067 we don't need RoomTile specific focus in the end 2017-04-18 22:54:20 +01:00
Michael Telatynski
0480a880f3 styling for spoilerized access token view in Settings
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-18 19:53:56 +01:00
Matthew Hodgson
acbc3e9f9b move RoomSubList.refreshHeader to apply to the whole RoomSubList again 2017-04-18 19:27:57 +01:00
Matthew Hodgson
a8daa53a5b always let tab/shift-tab select sublist headers 2017-04-18 17:49:50 +01:00
Matthew Hodgson
053beae035 move focus-via-up/down cursors to LeftPanel 2017-04-18 17:36:23 +01:00
Richard van der Hoff
ccc33db9dd Compress uploaded rageshakes. (#3647) 2017-04-18 17:23:34 +01:00
Richard van der Hoff
66a473863a Merge pull request #3648 from vector-im/rav/rageshake_progress
Progress updates for rageshake uploads
2017-04-18 17:23:03 +01:00
Richard van der Hoff
25907301a3 More unmounted guards in BugReportDialog 2017-04-18 16:51:35 +01:00
Richard van der Hoff
d8bf57edc5 Add progress reporting to rageshake submission 2017-04-18 16:51:35 +01:00
Richard van der Hoff
269f9a5ccc Load submit-rageshake asynchronously
... because it's 250K :/
2017-04-18 16:51:35 +01:00
Richard van der Hoff
a34b5abc82 Use multipart-form encoding for rageshake uploads (#3646)
This is a more sensible encoding for uploading logfiles, and will allow us to
compress the logfiles in future.

browser-request doesn't give us enough flexibility to do this properly, so we
use XMLHttpRequest directly.
2017-04-18 16:47:50 +01:00
Richard van der Hoff
062cf47290 Merge pull request #3645 from vector-im/rav/refactor_rageshake
Factor out rageshake upload to a separate file
2017-04-18 15:54:07 +01:00
Richard van der Hoff
fa132d3945 Merge pull request #3644 from vector-im/rav/fix_rageshake_race
rageshake: fix race when collecting logs
2017-04-18 15:53:41 +01:00
Richard van der Hoff
9fd379c97c Merge pull request #3649 from vector-im/rav/fix_test_fail
Fix a flaky test
2017-04-18 14:53:28 +01:00
Richard van der Hoff
593e101521 Fix a flaky test
Depending on timing, the first `httpBackend.flush()` could end up just flushing
a '/presence' call rather than the initial sync. The fix to that is simply to
not set the expectation on /presence.

While we're there, split out the flushes of /publicRooms and
/thirdparty/protocols, so that we can be sure that they happen.

There is probably still a bunch of flakiness there, but this should fix one
particular instance.
2017-04-18 13:45:31 +01:00
Richard van der Hoff
6fd6ea9b8e rageshake: fix race when collecting logs
*apparently* it's possible for your indexeddb transaction to complete in the
background, so that the `oncomplete` handler is never called. Make sure that
the oncomplete handler is set *before* doing the work.
2017-04-18 12:37:26 +01:00
Matthew Hodgson
f8aa2c3487 fix bugs in RoomSubListHeader splitout 2017-04-18 02:43:06 +01:00
Michael Telatynski
44479f24dd add command line arg (--hidden) for electron app
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-17 22:10:56 +01:00
Matthew Hodgson
5ff49f4000 split out header from RoomSubList and let it update separately
By moving the header into its own RoomSubListHeader, we can refresh it explicitly
by poking it by the new constantTimeDispatcher without re-rendering the whole stack
of room tiles

*UNTESTED*
2017-04-17 20:53:52 +01:00
Michael Telatynski
cc7a585126 make ImageView Download work, based on props.name
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-17 15:07:21 +01:00
daniel tygel
d3331f293b Merge branch 'develop' of github.com:vector-im/riot-web into develop 2017-04-16 23:27:38 -03:00
Matthew Hodgson
c6ee221ae4 typos 2017-04-16 15:58:00 +01:00
Matthew Hodgson
8351ec9738 thread RoomTile focus events through RoomSubList up to RoomList 2017-04-15 13:23:11 +01:00
Matthew Hodgson
27de972bfb oops 2017-04-15 12:02:50 +01:00
Matthew Hodgson
e5e259e1f8 put a ! on invite sublists 2017-04-15 12:02:16 +01:00
Matthew Hodgson
a74bbb424c cmd-k shortcut to the searchbox 2017-04-15 11:37:09 +01:00
Matthew Hodgson
15accf33f5 get rid of the evil blue outlines 2017-04-15 00:30:31 +01:00
Michael Telatynski
3fb54029d7 Fix packaged functionality
Improve dependency management for Electron main process deps

Dependencies in /electron/package.json will be installed through a script in /package.json and will be bundled via electron-builder

Does not affect standard webapp whatsoever

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-13 13:39:15 +01:00
Michael Telatynski
76008e8abd Remember and Recall window layout so that position+size persist
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-12 18:13:25 +01:00
Richard van der Hoff
3f291aae5b Use an opts arg for submit-rageshake 2017-04-12 11:26:53 +01:00
David Baker
76f140c62c Back to develop js & react sdks 2017-04-12 10:14:58 +01:00
David Baker
a12d7a2b66 Merge branch 'release-v0.9.8' 2017-04-12 10:14:00 +01:00
David Baker
ba8745cb42 v0.9.8 2017-04-12 10:10:53 +01:00
David Baker
967ebb5f9f Prepare changelog for v0.9.8 2017-04-12 10:10:52 +01:00
David Baker
6a5d0dda2f Use release versions of js-sdk & react-sdk 2017-04-12 10:03:43 +01:00
Richard van der Hoff
6423f7ce03 rageshake: factor out submission to a separate file
This will mean we can load it asyncronously in future, if we want.
2017-04-11 18:59:22 +01:00
David Baker
4ead2f338d v0.9.8-rc.3 2017-04-11 18:50:21 +01:00
David Baker
55ec7dcebc Prepare changelog for v0.9.8-rc.3 2017-04-11 18:50:20 +01:00
David Baker
8587df1dd9 React SDK rc.4 2017-04-11 18:49:27 +01:00
David Baker
d5b1db064f Merge remote-tracking branch 'origin/develop' into release-v0.9.8 2017-04-11 18:48:55 +01:00
Richard van der Hoff
4efb2b6750 Rageshake: Factor out getLogsForReport
... in preparation for factoring out sending the report
2017-04-11 18:47:55 +01:00
Richard van der Hoff
cbfa4dd1ab Get rageshake endpoint from SdkConfig instead of storing in rageshake
- in preparation for factoring out the sending of the rageshake
2017-04-11 18:46:48 +01:00
Matthew Hodgson
b26c460f13 shrink the redacted tear 2017-04-10 23:22:25 +01:00
daniel tygel
dd9150cef1 Merge branch 'add_config_json_to_gitignore' into develop 2017-04-10 14:12:38 -03:00
daniel tygel
ab1b377a1d add config.json to .gitignore 2017-04-10 14:11:26 -03:00
David Baker
3fa8460ed7 Merge pull request #3598 from vector-im/dbkr/clear_cache_button_electron
Make the clear cache button work on desktop
2017-04-10 17:56:49 +01:00
David Baker
7f6d9a625d Make the clear cache button work on desktop
Implement reload in Platforms to support
https://github.com/matrix-org/matrix-react-sdk/pull/798

Fixes https://github.com/vector-im/riot-web/issues/3597
2017-04-10 17:40:09 +01:00
David Baker
0b266d2e83 v0.9.8-rc.2 2017-04-10 16:56:41 +01:00
David Baker
7907d41ea8 Prepare changelog for v0.9.8-rc.2 2017-04-10 16:56:40 +01:00
David Baker
32c6482dcf Bump js-sdk & react-sdk versions 2017-04-10 16:55:27 +01:00
David Baker
ea0c41a9f8 Merge remote-tracking branch 'origin/develop' into release-v0.9.8 2017-04-10 16:55:02 +01:00
David Baker
a1cb566761 Bump electron version 2017-04-10 16:01:21 +01:00
Luke Barnard
01a96d92f4 Merge pull request #3596 from vector-im/luke/fix-redacted-bg
Redacted events bg: black lozenge -> torn paper
2017-04-10 15:59:41 +01:00
Luke Barnard
0b1745bceb Redacted events bg: black lozenge -> torn paper 2017-04-10 15:49:40 +01:00
David Baker
7d203f40cd Merge pull request #3594 from vector-im/rav/send_app_to_rageshake
Add 'app' parameter to rageshake report
2017-04-10 15:25:55 +01:00
Richard van der Hoff
b8b74402c1 Add 'app' parameter to rageshake report 2017-04-10 15:07:43 +01:00
Michael Telatynski
99923b7b8f Escape HTML tags in Notifications (Linux)
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2017-04-03 20:30:05 +01:00
Tom Lant
c4bc38f0d7 Fixing triage markdown as per #3382 2017-03-09 12:00:54 +00:00
84 changed files with 1233 additions and 576 deletions

2
.gitignore vendored
View File

@@ -5,6 +5,7 @@
/key.pem
/lib
/node_modules
/electron/node_modules
/packages/
/webapp
/.npmrc
@@ -12,3 +13,4 @@
npm-debug.log
electron/dist
electron/pub
/config.json

View File

@@ -1,3 +1,46 @@
Changes in [0.9.9](https://github.com/vector-im/riot-web/releases/tag/v0.9.9) (2017-04-25)
==========================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.9-rc.2...v0.9.9)
* No changes
Changes in [0.9.9-rc.2](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.2) (2017-04-24)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.9-rc.1...v0.9.9-rc.2)
* Fix bug where links to Riot would fail to open.
Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
* Update js-sdk and matrix-react-sdk to fix registration without a captcha (https://github.com/vector-im/riot-web/issues/3621)
Changes in [0.9.8](https://github.com/vector-im/riot-web/releases/tag/v0.9.8) (2017-04-12)
==========================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8-rc.3...v0.9.8)
* No changes
Changes in [0.9.8-rc.3](https://github.com/vector-im/riot-web/releases/tag/v0.9.8-rc.3) (2017-04-11)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8-rc.2...v0.9.8-rc.3)
* Make the clear cache button work on desktop
[\#3598](https://github.com/vector-im/riot-web/pull/3598)
Changes in [0.9.8-rc.2](https://github.com/vector-im/riot-web/releases/tag/v0.9.8-rc.2) (2017-04-10)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8-rc.1...v0.9.8-rc.2)
* Redacted events bg: black lozenge -> torn paper
[\#3596](https://github.com/vector-im/riot-web/pull/3596)
* Add 'app' parameter to rageshake report
[\#3594](https://github.com/vector-im/riot-web/pull/3594)
Changes in [0.9.8-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.8-rc.1) (2017-04-07)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.7...v0.9.8-rc.1)

View File

@@ -135,7 +135,7 @@ To run as a desktop app:
```
npm install electron
node_modules/.bin/electron .
npm run electron
```
To build packages, use electron-builder. This is configured to output:

View File

@@ -4,7 +4,7 @@
"brand": "Riot",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"bug_report_endpoint_url": "https://vector.im/bugs",
"bug_report_endpoint_url": "https://riot.im/bugreports/submit",
"enableLabs": true,
"roomDirectory": {
"servers": [

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 673 B

After

Width:  |  Height:  |  Size: 673 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
electron_app/img/riot.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
electron_app/img/riot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

11
electron_app/package.json Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "riot-web",
"productName": "Riot",
"main": "src/electron-main.js",
"version": "0.9.9",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"dependencies": {
"electron-window-state": "^4.1.0"
}
}

View File

@@ -30,6 +30,8 @@ const tray = require('./tray');
const VectorMenu = require('./vectormenu');
const windowStateKeeper = require('electron-window-state');
let vectorConfig = {};
try {
vectorConfig = require('../../webapp/config.json');
@@ -171,6 +173,7 @@ const shouldQuit = electron.app.makeSingleInstance((commandLine, workingDirector
});
if (shouldQuit) {
console.log("Other instance detected: exiting");
electron.app.quit()
}
@@ -186,11 +189,21 @@ electron.app.on('ready', () => {
process.platform == 'win32' ? 'ico' : 'png'
);
// Load the previous window state with fallback to defaults
let mainWindowState = windowStateKeeper({
defaultWidth: 1024,
defaultHeight: 768,
});
mainWindow = new electron.BrowserWindow({
icon: icon_path,
width: 1024, height: 768,
show: false,
autoHideMenuBar: true,
x: mainWindowState.x,
y: mainWindowState.y,
width: mainWindowState.width,
height: mainWindowState.height,
});
mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`);
electron.Menu.setApplicationMenu(VectorMenu);
@@ -201,9 +214,12 @@ electron.app.on('ready', () => {
brand: vectorConfig.brand || 'Riot'
});
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
if (!process.argv.includes('--hidden')) {
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
}
mainWindow.on('closed', () => {
mainWindow = null;
});
@@ -226,6 +242,8 @@ electron.app.on('ready', () => {
onLinkContextMenu(ev, params);
}
});
mainWindowState.manage(mainWindow);
});
electron.app.on('window-all-closed', () => {

View File

@@ -1,8 +1,8 @@
{
"name": "riot-web",
"productName": "Riot",
"main": "electron/src/electron-main.js",
"version": "0.9.8-rc.1",
"main": "electron_app/src/electron-main.js",
"version": "0.9.9",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
@@ -30,16 +30,18 @@
"build:res": "node scripts/copy-res.js",
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
"build:compile": "babel --source-maps -d lib src",
"build:bundle": "NODE_ENV=production webpack -p --progress",
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress",
"build:bundle:dev": "webpack --optimize-occurence-order --progress",
"build:electron": "npm run clean && npm run build && build -wml --ia32 --x64",
"build": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle",
"build:dev": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle:dev",
"build": "npm run build:res && npm run build:bundle",
"build:dev": "npm run build:res && npm run build:bundle:dev",
"dist": "scripts/package.sh",
"install:electron": "install-app-deps",
"electron": "npm run install:electron && electron .",
"start:res": "node scripts/copy-res.js -w",
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-file=bundles/_dev_/[name].js -w --progress",
"start:js:prod": "NODE_ENV=production webpack-dev-server -w --progress",
"start": "node scripts/babelcheck.js && parallelshell \"npm run start:res\" \"npm run start:js\"",
"start:js:prod": "cross-env NODE_ENV=production webpack-dev-server -w --progress",
"start": "parallelshell \"npm run start:res\" \"npm run start:js\"",
"start:prod": "parallelshell \"npm run start:res\" \"npm run start:js:prod\"",
"lint": "eslint src/",
"lintall": "eslint src/ test/",
@@ -56,21 +58,21 @@
"draft-js": "^0.8.1",
"extract-text-webpack-plugin": "^0.9.1",
"favico.js": "^0.3.10",
"filesize": "^3.1.2",
"filesize": "3.5.6",
"flux": "~2.0.3",
"gemini-scrollbar": "matrix-org/gemini-scrollbar#b302279",
"gfm.css": "^1.1.1",
"highlight.js": "^9.0.0",
"linkifyjs": "^2.1.3",
"matrix-js-sdk": "0.7.6-rc.1",
"matrix-react-sdk": "0.8.7-rc.1",
"matrix-js-sdk": "matrix-org/matrix-js-sdk#develop",
"matrix-react-sdk": "matrix-org/matrix-react-sdk#develop",
"modernizr": "^3.1.0",
"pako": "^1.0.5",
"q": "^1.4.1",
"react": "^15.4.0",
"react-dnd": "^2.1.4",
"react-dnd-html5-backend": "^2.1.2",
"react-dom": "^15.4.0",
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef",
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#39d858c",
"sanitize-html": "^1.11.1",
"ua-parser-js": "^0.7.10",
"url": "^0.11.0"
@@ -93,6 +95,7 @@
"babel-preset-stage-2": "^6.17.0",
"chokidar": "^1.6.1",
"cpx": "^1.3.2",
"cross-env": "^4.0.0",
"css-raw-loader": "^0.1.1",
"electron-builder": "^11.2.4",
"electron-builder-squirrel-windows": "^11.2.1",
@@ -138,16 +141,18 @@
"build": {
"appId": "im.riot.app",
"category": "Network",
"electronVersion": "1.4.14",
"electronVersion": "1.6.2",
"//asar=false": "https://github.com/electron-userland/electron-builder/issues/675",
"asar": false,
"dereference": true,
"//files": "We bundle everything, so we only need to include webapp/",
"files": [
"electron/src/**",
"electron/img/**",
"webapp/**",
"package.json"
"node_modules/**",
"src/**",
"img/**"
],
"extraResources": [
"webapp/**/*"
],
"linux": {
"target": "deb",
@@ -158,10 +163,11 @@
},
"win": {
"target": "squirrel"
},
"directories": {
"buildResources": "electron_app/build",
"output": "electron_app/dist",
"app": "electron_app"
}
},
"directories": {
"buildResources": "electron/build",
"output": "electron/dist"
}
}

View File

@@ -1,12 +1,25 @@
#!/bin/sh
#!/bin/bash
#
# Script to perform a release of vector-web.
#
# Requires github-changelog-generator; to install, do
# Requires github-changelog-generator; to install, do
# pip install git+https://github.com/matrix-org/github-changelog-generator.git
set -e
cd `dirname $0`
# bump Electron's package.json first
release="${1#v}"
tag="v${release}"
echo "electron npm version"
cd electron_app
npm version --no-git-tag-version "$release"
git commit package.json -m "$tag"
cd ..
exec ./node_modules/matrix-js-sdk/release.sh -z "$@"

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env node
var exec = require('child_process').exec;
// Makes sure the babel executable in the path is babel 6 (or greater), not
// babel 5, which it is if you upgrade from an older version of react-sdk and
// run 'npm install' since the package has changed to babel-cli, so 'babel'
// remains installed and the executable in node_modules/.bin remains as babel
// 5.
// This script is duplicated from matrix-react-sdk because it can't reliably
// be pulled in from react-sdk while npm install is failing, as it will do
// if the environment is in the erroneous state this script checks for.
exec("babel -V", function (error, stdout, stderr) {
if ((error && error.code) || parseInt(stdout.substr(0,1), 10) < 6) {
console.log("\033[31m\033[1m"+
'*****************************************\n'+
'* vector-web has moved to babel 6 *\n'+
'* Please "rm -rf node_modules && npm i" *\n'+
'* then restore links as appropriate *\n'+
'*****************************************\n'+
"\033[91m");
process.exit(1);
}
});

View File

@@ -10,6 +10,7 @@ const COPY_LIST = [
["res/{media,vector-icons}/**", "webapp"],
["src/skins/vector/{fonts,img}/**", "webapp"],
["node_modules/emojione/assets/svg/*", "webapp/emojione/svg/"],
["node_modules/emojione/assets/png/*", "webapp/emojione/png/"],
["./config.json", "webapp", {directwatch: 1}],
];

View File

@@ -90,8 +90,8 @@ npm run build:electron
popd
distdir="$builddir/electron/dist"
pubdir="$projdir/electron/pub"
distdir="$builddir/electron_app/dist"
pubdir="$projdir/electron_app/pub"
rm -r "$pubdir" || true
mkdir -p "$pubdir"
@@ -120,11 +120,11 @@ cp $distdir/win/*.nupkg "$pubdir/update/win32/x64/"
cp $distdir/win/RELEASES "$pubdir/update/win32/x64/"
# Move the debs to the main project dir's dist folder
rm -r "$projdir/electron/dist" || true
mkdir -p "$projdir/electron/dist"
cp $distdir/*.deb "$projdir/electron/dist/"
rm -r "$projdir/electron_app/dist" || true
mkdir -p "$projdir/electron_app/dist"
cp $distdir/*.deb "$projdir/electron_app/dist/"
rm -rf "$builddir"
echo "Riot Desktop is ready to go in $pubdir: this directory can be hosted on your web server."
echo "deb archives are in electron/dist/ - these should be added into your debian repository"
echo "deb archives are in electron_app/dist/ - these should be added into your debian repository"

40
scripts/issues-burndown.pl Normal file → Executable file
View File

@@ -4,16 +4,24 @@ use warnings;
use strict;
use Net::GitHub;
use DateTime;
use DateTime::Format::ISO8601;
use Time::Moment;
use Term::ReadPassword;
# This version of the script emits the cumulative number of bugs, split into open & closed
# suitable for drawing the 'top' and 'bottom' of a burndown graph.
#
# N.B. this doesn't take into account issues changing priority over time, but only their most recent priority.
#
# If you want instead the number of open issues on a given day, then look at issues-no-state.pl
my $gh = Net::GitHub->new(
login => 'ara4n', pass => 'secret'
login => 'ara4n', pass => read_password("github password: "),
);
$gh->set_default_user_repo('vector-im', 'vector-web');
my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 });
#my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 });
my @issues = $gh->issue->repos_issues({ state => 'all' });
while ($gh->issue->has_next_page) {
push @issues, $gh->issue->next_page;
}
@@ -30,11 +38,11 @@ while ($gh->issue->has_next_page) {
my $days = {};
my $schema = {};
my $now = DateTime->now();
my $now = Time::Moment->now;
foreach my $issue (@issues) {
next if ($issue->{pull_request});
# use Data::Dumper;
# print STDERR Dumper($issue);
@@ -56,10 +64,10 @@ foreach my $issue (@issues) {
my $priority = &$extract_labels(qw(p1 p2 p3 p4 p5)) || "unprioritised";
my $severity = &$extract_labels(qw(minor major critical cosmetic network)) || "no-severity";
my $start = DateTime::Format::ISO8601->parse_datetime($issue->{created_at});
my $start = Time::Moment->from_string($issue->{created_at});
do {
my $ymd = $start->ymd();
my $ymd = $start->strftime('%F');
$days->{ $ymd }->{ 'created' }->{ $type }->{ $priority }->{ $severity }->{ total }++;
$schema->{ 'created' }->{ $type }->{ $priority }->{ $severity }->{ total }++;
@@ -68,13 +76,14 @@ foreach my $issue (@issues) {
$schema->{ 'created' }->{ $type }->{ $priority }->{ $severity }->{ $_ }++;
}
$start = $start->add(days => 1);
} while (DateTime->compare($start, $now) < 0);
$start = $start->plus_days(1);
# print STDERR "^";
} while ($start->compare($now) < 0);
if ($state eq 'closed') {
my $end = DateTime::Format::ISO8601->parse_datetime($issue->{closed_at});
my $end = Time::Moment->from_string($issue->{closed_at});
do {
my $ymd = $end->ymd();
my $ymd = $end->strftime('%F');
$days->{ $ymd }->{ 'resolved' }->{ $type }->{ $priority }->{ $severity }->{ total }++;
$schema->{ 'resolved' }->{ $type }->{ $priority }->{ $severity }->{ total }++;
@@ -83,9 +92,12 @@ foreach my $issue (@issues) {
$schema->{ 'resolved' }->{ $type }->{ $priority }->{ $severity }->{ $_ }++;
}
$end = $end->add(days => 1);
} while (DateTime->compare($end, $now) < 0);
$end = $end->plus_days(1);
} while ($end->compare($now) < 0);
# print STDERR "v";
}
# print STDERR "\n";
}
print "day,";

View File

@@ -6,14 +6,22 @@ use strict;
use Net::GitHub;
use DateTime;
use DateTime::Format::ISO8601;
use Term::ReadPassword;
# This version of the script emits the total number of bugs open on a given day,
# split by various tags.
#
# If you want instead the cumulative number of open & closed issues on a given day,
# then look at issues-burndown.pl
my $gh = Net::GitHub->new(
login => 'ara4n', pass => 'secret'
login => 'ara4n', pass => read_password("github password: "),
);
$gh->set_default_user_repo('vector-im', 'vector-web');
my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 });
#my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 });
my @issues = $gh->issue->repos_issues({ state => 'all' });
while ($gh->issue->has_next_page) {
push @issues, $gh->issue->next_page;
}

View File

@@ -52,7 +52,7 @@ cp "$tmpdir/256.png" "$tmpdir/Riot.iconset/icon_256x256.png"
cp "$tmpdir/512.png" "$tmpdir/Riot.iconset/icon_256x256@2x.png"
cp "$tmpdir/512.png" "$tmpdir/Riot.iconset/icon_512x512.png"
cp "$tmpdir/1024.png" "$tmpdir/Riot.iconset/icon_512x512@2x.png"
iconutil -c icns -o electron/build/icon.icns "$tmpdir/Riot.iconset"
iconutil -c icns -o electron_app/build/icon.icns "$tmpdir/Riot.iconset"
cp "$tmpdir/36.png" "res/vector-icons/android-chrome-36x36.png"
cp "$tmpdir/48.png" "res/vector-icons/android-chrome-48x48.png"
@@ -79,15 +79,17 @@ cp "$tmpdir/144.png" "res/vector-icons/mstile-144x144.png"
cp "$tmpdir/150.png" "res/vector-icons/mstile-150x150.png"
cp "$tmpdir/310.png" "res/vector-icons/mstile-310x310.png"
cp "$tmpdir/310x150.png" "res/vector-icons/mstile-310x150.png"
cp "$tmpdir/180.png" "electron_app/img/riot.png"
convert "$tmpdir/16.png" "$tmpdir/32.png" "$tmpdir/64.png" "$tmpdir/128.png" "$tmpdir/256.png" "res/vector-icons/favicon.ico"
cp "res/vector-icons/favicon.ico" "electron/build/icon.ico"
cp "res/vector-icons/favicon.ico" "electron_app/build/icon.ico"
cp "res/vector-icons/favicon.ico" "electron_app/img/riot.ico"
# https://github.com/electron-userland/electron-builder/blob/3f97b86993d4ea5172e562b182230a194de0f621/src/targets/LinuxTargetHelper.ts#L127
for i in 24 96 16 48 64 128 256 512
do
cp "$tmpdir/$i.png" "electron/build/icons/${i}x${i}.png"
cp "$tmpdir/$i.png" "electron_app/build/icons/${i}x${i}.png"
done
rm -r "$tmpdir"

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
set -e
@@ -22,7 +22,14 @@ cp config.sample.json webapp/
mkdir -p dist
cp -r webapp vector-$version
echo $version > vector-$version/version
# if $version looks like semver with leading v, strip it before writing to file
if [[ ${version} =~ ^v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+(-.+)?$ ]]; then
echo ${version:1} > vector-$version/version
else
echo ${version} > vector-$version/version
fi
tar chvzf dist/vector-$version.tar.gz vector-$version
rm -r vector-$version

View File

@@ -19,9 +19,6 @@ limitations under the License.
* You can edit it you like, but your changes will be overwritten,
* so you'd just be trying to swim upstream like a salmon.
* You are not a salmon.
*
* To update it, run:
* ./reskindex.js -h header
*/
module.exports.components = require('matrix-react-sdk/lib/component-index').components;
@@ -40,6 +37,8 @@ import structures$RoomDirectory from './components/structures/RoomDirectory';
structures$RoomDirectory && (module.exports.components['structures.RoomDirectory'] = structures$RoomDirectory);
import structures$RoomSubList from './components/structures/RoomSubList';
structures$RoomSubList && (module.exports.components['structures.RoomSubList'] = structures$RoomSubList);
import structures$RoomSubListHeader from './components/structures/RoomSubListHeader';
structures$RoomSubListHeader && (module.exports.components['structures.RoomSubListHeader'] = structures$RoomSubListHeader);
import structures$SearchBox from './components/structures/SearchBox';
structures$SearchBox && (module.exports.components['structures.SearchBox'] = structures$SearchBox);
import structures$ViewSource from './components/structures/ViewSource';
@@ -64,6 +63,8 @@ import views$globals$MatrixToolbar from './components/views/globals/MatrixToolba
views$globals$MatrixToolbar && (module.exports.components['views.globals.MatrixToolbar'] = views$globals$MatrixToolbar);
import views$globals$NewVersionBar from './components/views/globals/NewVersionBar';
views$globals$NewVersionBar && (module.exports.components['views.globals.NewVersionBar'] = views$globals$NewVersionBar);
import views$globals$PasswordNagBar from './components/views/globals/PasswordNagBar';
views$globals$PasswordNagBar && (module.exports.components['views.globals.PasswordNagBar'] = views$globals$PasswordNagBar);
import views$login$VectorCustomServerDialog from './components/views/login/VectorCustomServerDialog';
views$login$VectorCustomServerDialog && (module.exports.components['views.login.VectorCustomServerDialog'] = views$login$VectorCustomServerDialog);
import views$login$VectorLoginFooter from './components/views/login/VectorLoginFooter';

View File

@@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,13 +15,8 @@ See the License for the specific language governing permissions and
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');
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
import React from 'react';
import sdk from 'matrix-react-sdk';
module.exports = React.createClass({
displayName: 'BottomLeftMenu',
@@ -30,121 +26,28 @@ module.exports = React.createClass({
teamToken: React.PropTypes.string,
},
getInitialState: function() {
return({
directoryHover : false,
roomsHover : false,
homeHover: 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 });
},
// Home button events
onHomeClick: function() {
dis.dispatch({ action: 'view_home_page' });
},
onHomeMouseEnter: function() {
this.setState({ homeHover: true });
},
onHomeMouseLeave: function() {
this.setState({ homeHover: 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' });
},
onSettingsMouseEnter: function() {
this.setState({ settingsHover: true });
},
onSettingsMouseLeave: function() {
this.setState({ settingsHover: false });
},
// Get the label/tooltip to show
getLabel: function(label, show) {
if (show) {
var RoomTooltip = sdk.getComponent("rooms.RoomTooltip");
return <RoomTooltip className="mx_BottomLeftMenu_tooltip" label={label} />;
}
},
render: function() {
var TintableSvg = sdk.getComponent('elements.TintableSvg');
const HomeButton = sdk.getComponent('elements.HomeButton');
const StartChatButton = sdk.getComponent('elements.StartChatButton');
const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton');
const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton');
const SettingsButton = sdk.getComponent('elements.SettingsButton');
var homeButton;
if (this.props.teamToken) {
homeButton = (
<AccessibleButton className="mx_BottomLeftMenu_homePage" onClick={ this.onHomeClick } onMouseEnter={ this.onHomeMouseEnter } onMouseLeave={ this.onHomeMouseLeave } >
<TintableSvg src="img/icons-home.svg" width="25" height="25" />
{ this.getLabel("Welcome page", this.state.homeHover) }
</AccessibleButton>
);
homeButton = <HomeButton tooltip={true} />;
}
return (
<div className="mx_BottomLeftMenu">
<div className="mx_BottomLeftMenu_options">
{ homeButton }
<AccessibleButton 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) }
</AccessibleButton>
<AccessibleButton 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) }
</AccessibleButton>
<AccessibleButton 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) }
</AccessibleButton>
<AccessibleButton 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) }
</AccessibleButton>
<StartChatButton tooltip={true} />
<RoomDirectoryButton tooltip={true} />
<CreateRoomButton tooltip={true} />
<span className="mx_BottomLeftMenu_settings">
<SettingsButton tooltip={true} />
</span>
</div>
</div>
);

View File

@@ -19,9 +19,11 @@ limitations under the License.
var React = require('react');
var DragDropContext = require('react-dnd').DragDropContext;
var HTML5Backend = require('react-dnd-html5-backend');
var KeyCode = require('matrix-react-sdk/lib/KeyCode');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var VectorConferenceHandler = require('../../VectorConferenceHandler');
var CallHandler = require("matrix-react-sdk/lib/CallHandler");
@@ -40,6 +42,10 @@ var LeftPanel = React.createClass({
};
},
componentWillMount: function() {
this.focusedElement = null;
},
componentDidMount: function() {
this.dispatcherRef = dis.register(this.onAction);
},
@@ -62,6 +68,91 @@ var LeftPanel = React.createClass({
}
},
_onFocus: function(ev) {
this.focusedElement = ev.target;
},
_onBlur: function(ev) {
this.focusedElement = null;
},
_onKeyDown: function(ev) {
if (!this.focusedElement) return;
let handled = false;
switch (ev.keyCode) {
case KeyCode.UP:
this._onMoveFocus(true);
handled = true;
break;
case KeyCode.DOWN:
this._onMoveFocus(false);
handled = true;
break;
}
if (handled) {
ev.stopPropagation();
ev.preventDefault();
}
},
_onMoveFocus: function(up) {
var element = this.focusedElement;
// unclear why this isn't needed
// var descending = (up == this.focusDirection) ? this.focusDescending : !this.focusDescending;
// this.focusDirection = up;
var descending = false; // are we currently descending or ascending through the DOM tree?
var classes;
do {
var child = up ? element.lastElementChild : element.firstElementChild;
var sibling = up ? element.previousElementSibling : element.nextElementSibling;
if (descending) {
if (child) {
element = child;
}
else if (sibling) {
element = sibling;
}
else {
descending = false;
element = element.parentElement;
}
}
else {
if (sibling) {
element = sibling;
descending = true;
}
else {
element = element.parentElement;
}
}
if (element) {
classes = element.classList;
if (classes.contains("mx_LeftPanel")) { // we hit the top
element = up ? element.lastElementChild : element.firstElementChild;
descending = true;
}
}
} while(element && !(
classes.contains("mx_RoomTile") ||
classes.contains("mx_SearchBox_search") ||
classes.contains("mx_RoomSubList_ellipsis")));
if (element) {
element.focus();
this.focusedElement = element;
this.focusedDescending = descending;
}
},
_recheckCallElement: function(selectedRoomId) {
// if we aren't viewing a room with an ongoing call, but there is an
// active call, show the call element - we need to do this to make
@@ -120,7 +211,8 @@ var LeftPanel = React.createClass({
}
return (
<aside className={classes} style={{ opacity: this.props.opacity }}>
<aside className={classes} style={{ opacity: this.props.opacity }}
onKeyDown={ this._onKeyDown } onFocus={ this._onFocus } onBlur={ this._onBlur }>
<SearchBox collapsed={ this.props.collapsed } onSearch={ this.onSearch } />
{ collapseButton }
{ callPreview }

View File

@@ -23,7 +23,6 @@ var ContentRepo = require("matrix-js-sdk").ContentRepo;
var Modal = require('matrix-react-sdk/lib/Modal');
var sdk = require('matrix-react-sdk');
var dis = require('matrix-react-sdk/lib/dispatcher');
var GeminiScrollbar = require('react-gemini-scrollbar');
var linkify = require('linkifyjs');
var linkifyString = require('linkifyjs/string');
@@ -162,7 +161,7 @@ module.exports = React.createClass({
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Failed to get public room list",
description: "The server may be unavailable or overloaded",
description: ((err && err.message) ? err.message : "The server may be unavailable or overloaded"),
});
});
},
@@ -205,13 +204,13 @@ module.exports = React.createClass({
}).done(() => {
modal.close();
this.refreshRoomList();
}, function(err) {
}, (err) => {
modal.close();
this.refreshRoomList();
console.error("Failed to " + step + ": " + err);
Modal.createDialog(ErrorDialog, {
title: "Error",
description: "Failed to " + step,
title: "Failed to " + step,
description: ((err && err.message) ? err.message : "The server may be unavailable or overloaded"),
});
});
}
@@ -460,6 +459,17 @@ module.exports = React.createClass({
return fields;
},
/**
* called by the parent component when PageUp/Down/etc is pressed.
*
* We pass it down to the scroll panel.
*/
handleScrollKey: function(ev) {
if (this.scrollPanel) {
this.scrollPanel.handleScrollKey(ev);
}
},
render: function() {
const SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
const Loader = sdk.getComponent("elements.Spinner");
@@ -538,7 +548,7 @@ module.exports = React.createClass({
const DirectorySearchBox = sdk.getComponent('elements.DirectorySearchBox');
return (
<div className="mx_RoomDirectory">
<SimpleRoomHeader title="Directory" />
<SimpleRoomHeader title="Directory" icon="img/icons-directory.svg"/>
<div className="mx_RoomDirectory_list">
<div className="mx_RoomDirectory_listheader">
<DirectorySearchBox

View File

@@ -1,4 +1,5 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2015, 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,8 +28,11 @@ 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');
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
var ConstantTimeDispatcher = require('matrix-react-sdk/lib/ConstantTimeDispatcher');
var RoomSubListHeader = require('./RoomSubListHeader.js');
import Modal from 'matrix-react-sdk/lib/Modal';
// turn this on for drop & drag console debugging galore
// turn this on for drag & drop console debugging galore
var debug = false;
const TRUNCATE_AT = 10;
@@ -71,17 +75,17 @@ var RoomSubList = React.createClass({
order: React.PropTypes.string.isRequired,
// undefined if no room is selected (eg we are showing settings)
selectedRoom: React.PropTypes.string,
startAsHidden: React.PropTypes.bool,
showSpinner: React.PropTypes.bool, // true to show a spinner if 0 elements when expanded
collapsed: React.PropTypes.bool.isRequired, // is LeftPanel collapsed?
onHeaderClick: React.PropTypes.func,
alwaysShowHeader: React.PropTypes.bool,
selectedRoom: React.PropTypes.string,
incomingCall: React.PropTypes.object,
onShowMoreRooms: React.PropTypes.func,
searchFilter: React.PropTypes.string,
emptyContent: React.PropTypes.node, // content shown if the list is empty
headerItems: React.PropTypes.node, // content shown in the sublist header
},
getInitialState: function() {
@@ -100,13 +104,31 @@ var RoomSubList = React.createClass({
},
componentWillMount: function() {
constantTimeDispatcher.register("RoomSubList.sort", this.props.tagName, this.onSort);
constantTimeDispatcher.register("RoomSubList.refreshHeader", this.props.tagName, this.onRefresh);
this.sortList(this.applySearchFilter(this.props.list, this.props.searchFilter), this.props.order);
this._fixUndefinedOrder(this.props.list);
},
componentWillUnmount: function() {
constantTimeDispatcher.unregister("RoomSubList.sort", this.props.tagName, this.onSort);
constantTimeDispatcher.unregister("RoomSubList.refreshHeader", this.props.tagName, this.onRefresh);
},
componentWillReceiveProps: function(newProps) {
// order the room list appropriately before we re-render
//if (debug) console.log("received new props, list = " + newProps.list);
this.sortList(this.applySearchFilter(newProps.list, newProps.searchFilter), newProps.order);
this._fixUndefinedOrder(newProps.list);
},
onSort: function() {
this.sortList(this.applySearchFilter(this.props.list, this.props.searchFilter), this.props.order);
// we deliberately don't waste time trying to fix undefined ordering here
},
onRefresh: function() {
this.forceUpdate();
},
applySearchFilter: function(list, filter) {
@@ -119,7 +141,7 @@ var RoomSubList = React.createClass({
// 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;
var stuck = this.refs.header.refs.header.dataset.stuck;
if (this.state.hidden || stuck === undefined || stuck === "none") {
return true;
} else {
@@ -142,14 +164,15 @@ var RoomSubList = React.createClass({
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);
this.props.onHeaderClick(this.state.hidden, this.refs.header.refs.header.dataset.originalPosition);
}
},
onRoomTileClick(roomId) {
onRoomTileClick(roomId, ev) {
dis.dispatch({
action: 'view_room',
room_id: roomId,
clear_search: (ev && (ev.keyCode == 13 || ev.keyCode == 32)),
});
},
@@ -211,9 +234,6 @@ var RoomSubList = React.createClass({
if (order === "manual") comparator = this.manualComparator;
if (order === "recent") comparator = this.recentsComparator;
// Fix undefined orders here, and make sure the backend gets updated as well
this._fixUndefinedOrder(list);
//if (debug) console.log("sorting list for sublist " + this.props.label + " with length " + list.length + ", this.props.list = " + this.props.list);
this.setState({ sortedList: list.sort(comparator) });
},
@@ -248,10 +268,9 @@ var RoomSubList = React.createClass({
if (badges) {
result[0] += notificationCount;
if (highlight) {
result[1] = true;
}
}
result[1] |= highlight;
}
return result;
}, [0, false]);
@@ -359,7 +378,6 @@ var RoomSubList = React.createClass({
var self = this;
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 (
<DNDRoomTile
@@ -367,9 +385,7 @@ var RoomSubList = React.createClass({
roomSubList={ self }
key={ room.roomId }
collapsed={ self.props.collapsed || false}
selected={ selected }
unread={ Unread.doesRoomHaveUnreadMessages(room) }
highlight={ room.getUnreadNotificationCount('highlight') > 0 || self.props.label === 'Invites' }
selectedRoom={ self.props.selectedRoom }
isInvite={ self.props.label === 'Invites' }
refreshSubList={ self._updateSubListCount }
incomingCall={ null }
@@ -379,70 +395,6 @@ var RoomSubList = React.createClass({
});
},
_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.props.list.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 }/>;
}
}
var tabindex = this.props.searchFilter === "" ? "0" : "-1";
return (
<div className="mx_RoomSubList_labelContainer" title={ title } ref="header">
<AccessibleButton onClick={ this.onClick } className="mx_RoomSubList_label" tabIndex={tabindex}>
{ this.props.collapsed ? '' : this.props.label }
<div className="mx_RoomSubList_roomCount">{ roomCount }</div>
<div className={chevronClasses}></div>
{ badge }
{ incomingCall }
</AccessibleButton>
</div>
);
},
_createOverflowTile: function(overflowCount, totalCount) {
var content = <div className="mx_RoomSubList_chevronDown"></div>;
@@ -498,7 +450,7 @@ var RoomSubList = React.createClass({
// gets triggered and another list is passed in. Doing it one at a time means that
// we always correctly calculate the highest order for the list - stops multiple
// rooms getting the same order. This is only really relevant for the first time this
// is run with historical room tag data, after that there should only be undefined
// is run with historical room tag data, after that there should only be one undefined
// in the list at a time anyway.
for (let i = 0; i < list.length; i++) {
if (list[i].tags[self.props.tagName] && list[i].tags[self.props.tagName].order === undefined) {
@@ -508,8 +460,8 @@ var RoomSubList = React.createClass({
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to add tag " + self.props.tagName + " to room" + err);
Modal.createDialog(ErrorDialog, {
title: "Error",
description: "Failed to add tag " + self.props.tagName + " to room",
title: "Failed to add tag " + self.props.tagName + " to room",
description: ((err && err.message) ? err.message : "Operation failed"),
});
});
break;
@@ -520,16 +472,25 @@ var RoomSubList = React.createClass({
render: function() {
var connectDropTarget = this.props.connectDropTarget;
var RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget');
var TruncatedList = sdk.getComponent('elements.TruncatedList');
var label = this.props.collapsed ? null : this.props.label;
//console.log("render: " + JSON.stringify(this.state.sortedList));
let content;
if (this.state.sortedList.length == 0) {
content = this.props.emptyContent;
} else {
content = this.makeRoomTiles();
}
var target;
if (this.state.sortedList.length == 0 && this.props.editable) {
target = <RoomDropTarget label={ 'Drop here to ' + this.props.verb }/>;
var roomCount = this.props.list.length > 0 ? this.props.list.length : '';
var isIncomingCallRoom;
if (this.props.incomingCall) {
// Check if the incoming call is for this section
isIncomingCallRoom = this.props.list.find(room=>{
return this.props.incomingCall.roomId === room.roomId;
}) ? true : false;
}
if (this.state.sortedList.length > 0 || this.props.editable) {
@@ -539,8 +500,7 @@ var RoomSubList = React.createClass({
if (!this.state.hidden) {
subList = <TruncatedList className={ classes } truncateAt={this.state.truncateAt}
createOverflowElement={this._createOverflowTile} >
{ target }
{ this.makeRoomTiles() }
{ content }
</TruncatedList>;
}
else {
@@ -550,7 +510,20 @@ var RoomSubList = React.createClass({
return connectDropTarget(
<div>
{ this._getHeaderJsx() }
<RoomSubListHeader
ref='header'
label={ this.props.label }
tagName={ this.props.tagName }
roomCount={ roomCount }
collapsed={ this.props.collapsed }
hidden={ this.state.hidden }
incomingCall={ this.props.incomingCall }
isIncomingCallRoom={ isIncomingCallRoom }
roomNotificationCount={ this.roomNotificationCount() }
onClick={ this.onClick }
onHeaderClick={ this.props.onHeaderClick }
headerItems={this.props.headerItems}
/>
{ subList }
</div>
);
@@ -559,7 +532,21 @@ var RoomSubList = React.createClass({
var Loader = sdk.getComponent("elements.Spinner");
return (
<div className="mx_RoomSubList">
{ this.props.alwaysShowHeader ? this._getHeaderJsx() : undefined }
{ this.props.alwaysShowHeader ?
<RoomSubListHeader
ref='header'
label={ this.props.label }
tagName={ this.props.tagName }
roomCount={ roomCount }
collapsed={ this.props.collapsed }
hidden={ this.state.hidden }
isIncomingCallRoom={ isIncomingCallRoom }
roomNotificationCount={ this.roomNotificationCount() }
onClick={ this.onClick }
onHeaderClick={ this.props.onHeaderClick }
headerItems={this.props.headerItems}
/>
: undefined }
{ (this.props.showSpinner && !this.state.hidden) ? <Loader /> : undefined }
</div>
);

View File

@@ -0,0 +1,117 @@
/*
Copyright 2017 Vector Creations 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 classNames from 'classnames';
import sdk from 'matrix-react-sdk';
import { formatCount } from 'matrix-react-sdk/lib/utils/FormattingUtils';
import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton';
module.exports = React.createClass({
displayName: 'RoomSubListHeader',
propTypes: {
label: React.PropTypes.string.isRequired,
tagName: React.PropTypes.string,
roomCount: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number
]),
collapsed: React.PropTypes.bool.isRequired, // is LeftPanel collapsed?
incomingCall: React.PropTypes.object,
isIncomingCallRoom: React.PropTypes.bool,
roomNotificationCount: React.PropTypes.array,
hidden: React.PropTypes.bool,
onClick: React.PropTypes.func,
onHeaderClick: React.PropTypes.func,
headerItems: React.PropTypes.node, // content shown in the sublist header
},
getDefaultProps: function() {
return {
onHeaderClick: function() {}, // NOP
};
},
componentWillMount: function() {
// constantTimeDispatcher.register("RoomSubList.refreshHeader", this.props.tagName, this.onRefresh);
},
componentWillUnmount: function() {
// constantTimeDispatcher.unregister("RoomSubList.refreshHeader", this.props.tagName, this.onRefresh);
},
// onRefresh: function() {
// this.forceUpdate();
// },
render: function() {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
const subListNotifications = this.props.roomNotificationCount;
const subListNotifCount = subListNotifications[0];
const subListNotifHighlight = subListNotifications[1];
const chevronClasses = classNames({
'mx_RoomSubList_chevron': true,
'mx_RoomSubList_chevronRight': this.props.hidden,
'mx_RoomSubList_chevronDown': !this.props.hidden,
});
const badgeClasses = classNames({
'mx_RoomSubList_badge': true,
'mx_RoomSubList_badgeHighlight': subListNotifHighlight,
});
let badge;
if (subListNotifCount > 0) {
badge = <div className={badgeClasses}>{ formatCount(subListNotifCount) }</div>;
} else if (subListNotifHighlight) {
badge = <div className={badgeClasses}>!</div>;
}
// When collapsed, allow a long hover on the header to show user
// the full tag name and room count
let title;
const roomCount = this.props.roomCount;
if (this.props.collapsed) {
title = this.props.label;
if (roomCount !== '') {
title += " [" + roomCount + "]";
}
}
let incomingCall;
if (this.props.isIncomingCallRoom) {
const IncomingCallBox = sdk.getComponent("voip.IncomingCallBox");
incomingCall = <IncomingCallBox className="mx_RoomSubList_incomingCall" incomingCall={ this.props.incomingCall }/>;
}
return (
<div className="mx_RoomSubList_labelContainer" title={ title } ref="header">
<AccessibleButton onClick={ this.props.onClick } className="mx_RoomSubList_label" tabIndex="0">
{ this.props.collapsed ? '' : this.props.label }
{this.props.headerItems}
<div className="mx_RoomSubList_roomCount">{ roomCount }</div>
<div className={chevronClasses}></div>
{ badge }
</AccessibleButton>
{ incomingCall }
</div>
);
},
});

View File

@@ -21,6 +21,7 @@ var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var rate_limited_func = require('matrix-react-sdk/lib/ratelimitedfunc');
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
var KeyCode = require('matrix-react-sdk/lib/KeyCode');
module.exports = React.createClass({
displayName: 'SearchBox',
@@ -38,25 +39,23 @@ module.exports = React.createClass({
componentDidMount: function() {
this.dispatcherRef = dis.register(this.onAction);
document.addEventListener('keydown', this._onKeyDown);
},
componentWillUnmount: function() {
dis.unregister(this.dispatcherRef);
document.removeEventListener('keydown', this._onKeyDown);
},
onAction: function(payload) {
// Disabling this as I find it really really annoying, and was used to the
// previous behaviour - see https://github.com/vector-im/riot-web/issues/3348
/*
switch (payload.action) {
// Clear up the text field when a room is selected.
case 'view_room':
if (this.refs.search) {
if (payload.clear_search && this.refs.search) {
this._clearSearch();
}
break;
}
*/
},
onChange: function() {
@@ -90,6 +89,38 @@ module.exports = React.createClass({
this.onChange();
},
_onKeyDown: function(ev) {
let handled = false;
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
let ctrlCmdOnly;
if (isMac) {
ctrlCmdOnly = ev.metaKey && !ev.altKey && !ev.ctrlKey && !ev.shiftKey;
} else {
ctrlCmdOnly = ev.ctrlKey && !ev.altKey && !ev.metaKey && !ev.shiftKey;
}
switch (ev.keyCode) {
case KeyCode.ESCAPE:
this._clearSearch();
dis.dispatch({action: 'focus_composer'});
break;
case KeyCode.KEY_K:
if (ctrlCmdOnly) {
if (this.refs.search) {
this.refs.search.focus();
this.refs.search.select();
}
handled = true;
}
break;
}
if (handled) {
ev.stopPropagation();
ev.preventDefault();
}
},
render: function() {
var TintableSvg = sdk.getComponent('elements.TintableSvg');

View File

@@ -71,7 +71,7 @@ module.exports = React.createClass({
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Failed to remove tag " + tagNameOff + " from room",
description: err.toString()
description: ((err && err.message) ? err.message : "Operation failed"),
});
});
}
@@ -88,7 +88,7 @@ module.exports = React.createClass({
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Failed to add tag " + tagNameOn + " to room",
description: err.toString()
description: ((err && err.message) ? err.message : "Operation failed"),
});
});
}
@@ -149,7 +149,7 @@ module.exports = React.createClass({
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Failed to set Direct Message status of room",
description: err.toString()
description: ((err && err.message) ? err.message : "Operation failed"),
});
});
},
@@ -187,8 +187,8 @@ module.exports = React.createClass({
var errCode = err.errcode || "unknown error code";
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Error",
description: `Failed to forget room (${errCode})`
title: `Failed to forget room (${errCode})`,
description: ((err && err.message) ? err.message : "Operation failed"),
});
});

View File

@@ -16,7 +16,7 @@ limitations under the License.
import React from 'react';
import sdk from 'matrix-react-sdk';
import rageshake from '../../../vector/rageshake';
import SdkConfig from 'matrix-react-sdk/lib/SdkConfig';
export default class BugReportDialog extends React.Component {
constructor(props, context) {
@@ -26,11 +26,18 @@ export default class BugReportDialog extends React.Component {
busy: false,
err: null,
text: "",
progress: null,
};
this._unmounted = false;
this._onSubmit = this._onSubmit.bind(this);
this._onCancel = this._onCancel.bind(this);
this._onTextChange = this._onTextChange.bind(this);
this._onSendLogsChange = this._onSendLogsChange.bind(this);
this._sendProgressCallback = this._sendProgressCallback.bind(this);
}
componentWillUnmount() {
this._unmounted = true;
}
_onCancel(ev) {
@@ -46,12 +53,27 @@ export default class BugReportDialog extends React.Component {
});
return;
}
this.setState({ busy: true, err: null });
rageshake.sendBugReport(userText, sendLogs).then(() => {
this.setState({ busy: false });
this.props.onFinished(false);
}, (err) => {
this.setState({ busy: false, err: `Failed: ${err.message}` });
this.setState({ busy: true, progress: null, err: null });
this._sendProgressCallback("Loading bug report module");
require(['../../../vector/submit-rageshake'], (s) => {
s(SdkConfig.get().bug_report_endpoint_url, {
userText: userText,
sendLogs: sendLogs,
progressCallback: this._sendProgressCallback,
}).then(() => {
if (!this._unmounted) {
this.setState({ busy: false, progress: null });
this.props.onFinished(false);
}
}, (err) => {
if (!this._unmounted) {
this.setState({
busy: false, progress: null,
err: `Failed to send report: ${err.message}`,
});
}
});
});
}
@@ -63,6 +85,13 @@ export default class BugReportDialog extends React.Component {
this.setState({ sendLogs: ev.target.checked });
}
_sendProgressCallback(progress) {
if (this._unmounted) {
return;
}
this.setState({progress: progress});
}
render() {
const Loader = sdk.getComponent("elements.Spinner");
@@ -73,8 +102,6 @@ export default class BugReportDialog extends React.Component {
</div>;
}
const okLabel = this.state.busy ? <Loader /> : 'Send';
let cancelButton = null;
if (!this.state.busy) {
cancelButton = <button onClick={this._onCancel}>
@@ -82,6 +109,16 @@ export default class BugReportDialog extends React.Component {
</button>;
}
let progress = null;
if (this.state.busy) {
progress = (
<div className="progress">
<Loader />
{this.state.progress} ...
</div>
);
}
return (
<div className="mx_BugReportDialog">
<div className="mx_Dialog_title">
@@ -104,6 +141,7 @@ export default class BugReportDialog extends React.Component {
<input type="checkbox" checked={this.state.sendLogs}
onChange={this._onSendLogsChange} id="mx_BugReportDialog_logs"/>
<label htmlFor="mx_BugReportDialog_logs">Send logs</label>
{progress}
{error}
</div>
<div className="mx_Dialog_buttons">
@@ -111,8 +149,9 @@ export default class BugReportDialog extends React.Component {
className="mx_Dialog_primary danger"
onClick={this._onSubmit}
autoFocus={true}
disabled={this.state.busy}
>
{okLabel}
Send
</button>
{cancelButton}

View File

@@ -176,7 +176,7 @@ module.exports = React.createClass({
{ this.getName() }
</div>
{ eventMeta }
<a className="mx_ImageView_link" href={ this.props.src } target="_blank" rel="noopener">
<a className="mx_ImageView_link" href={ this.props.src } download={ this.props.name } target="_blank" rel="noopener">
<div className="mx_ImageView_download">
Download this file<br/>
<span className="mx_ImageView_size">{ size_res }</span>

View File

@@ -0,0 +1,52 @@
/*
Copyright 2017 Vector Creations 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';
import React from 'react';
import sdk from 'matrix-react-sdk';
import Modal from 'matrix-react-sdk/lib/Modal';
export default React.createClass({
onUpdateClicked: function() {
// TODO: Implement dialog to set password
// const SetPasswordDialog = sdk.getComponent('dialogs.SetPasswordDialog');
// Modal.createDialog(SetPasswordDialog, {
// onFinished: () => {
// }
// });
},
render: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return (
<div className="mx_MatrixToolbar">
<img className="mx_MatrixToolbar_warning"
src="img/warning.svg"
width="24"
height="23"
alt="Warning"
/>
<div className="mx_MatrixToolbar_content">
To be able to return to your account, you need to set a password.
</div>
<button className="mx_MatrixToolbar_action" onClick={this.onUpdateClicked}>
Set Password
</button>
</div>
);
}
});

View File

@@ -18,6 +18,9 @@ limitations under the License.
var React = require('react');
const i = [1, 2, 3, 4, 5][Math.floor(Math.random() * 5)];
const DEFAULT_LOGO_URI = "img/logos/riot-logo-" + i + ".svg";
module.exports = React.createClass({
displayName: 'VectorLoginHeader',
statics: {
@@ -30,7 +33,7 @@ module.exports = React.createClass({
render: function() {
return (
<div className="mx_Login_logo">
<img src={this.props.icon || "img/logo.png"} alt="Riot"/>
<img src={this.props.icon || DEFAULT_LOGO_URI} alt="Riot"/>
</div>
);
}

View File

@@ -25,7 +25,7 @@ module.exports = React.createClass({
render: function() {
var date = new Date(this.props.ts);
return (
<span className="mx_MessageTimestamp">
<span className="mx_MessageTimestamp" title={ DateUtils.formatDate(date) }>
{ DateUtils.formatTime(date) }
</span>
);

View File

@@ -90,8 +90,8 @@ var roomTileSource = {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to set direct chat tag " + err);
Modal.createDialog(ErrorDialog, {
title: "Error",
description: "Failed to set direct chat tag",
title: "Failed to set direct chat tag",
description: ((err && err.message) ? err.message : "Operation failed"),
});
});
return;
@@ -115,8 +115,8 @@ var roomTileSource = {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to remove tag " + prevTag + " from room: " + err);
Modal.createDialog(ErrorDialog, {
title: "Error",
description: "Failed to remove tag " + prevTag + " from room",
title: "Failed to remove tag " + prevTag + " from room",
description: ((err && err.message) ? err.message : "Operation failed"),
});
});
}
@@ -137,8 +137,8 @@ var roomTileSource = {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to add tag " + newTag + " to room: " + err);
Modal.createDialog(ErrorDialog, {
title: "Error",
description: "Failed to add tag " + newTag + " to room",
title: "Failed to add tag " + newTag + " to room",
description: ((err && err.message) ? err.message : "Operation failed"),
});
});
}

View File

@@ -22,20 +22,12 @@ module.exports = React.createClass({
displayName: 'RoomDropTarget',
render: function() {
if (this.props.placeholder) {
return (
<div className="mx_RoomDropTarget mx_RoomDropTarget_placeholder">
return (
<div className="mx_RoomDropTarget">
<div className="mx_RoomDropTarget_label">
{ this.props.label }
</div>
);
}
else {
return (
<div className="mx_RoomDropTarget">
<div className="mx_RoomDropTarget_label">
{ this.props.label }
</div>
</div>
);
}
</div>
);
}
});

View File

@@ -240,8 +240,8 @@ module.exports = React.createClass({
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to change settings: " + error);
Modal.createDialog(ErrorDialog, {
title: "Error",
description: "Failed to change settings",
title: "Failed to change settings",
description: ((error && error.message) ? error.message : "Operation failed"),
onFinished: self._refreshFromServer
});
});
@@ -310,8 +310,8 @@ module.exports = React.createClass({
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Can't update user notification settings: " + error);
Modal.createDialog(ErrorDialog, {
title: "Error",
description: "Can't update user notification settings",
title: "Can't update user notification settings",
description: ((error && error.message) ? error.message : "Operation failed"),
onFinished: self._refreshFromServer
});
});
@@ -352,8 +352,8 @@ module.exports = React.createClass({
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to update keywords: " + error);
Modal.createDialog(ErrorDialog, {
title: "Error",
description: "Failed to update keywords",
title: "Failed to update keywords",
description: ((error && error.message) ? error.message : "Operation failed"),
onFinished: self._refreshFromServer
});
}

View File

@@ -65,7 +65,7 @@ input[type=text].error, input[type=password].error {
border: 1px solid $warning-color;
}
input[type=text]:focus, textarea:focus {
input[type=text]:focus, input[type=password]:focus, textarea:focus {
border: 1px solid $accent-color;
outline: none;
box-shadow: none;
@@ -225,6 +225,10 @@ textarea {
vertical-align: middle;
}
.mx_Dialog button:focus, .mx_Dialog input[type="submit"]:focus {
filter: brightness($focus-brightness);
}
.mx_Dialog button.mx_Dialog_primary, .mx_Dialog input[type="submit"].mx_Dialog_primary {
color: $accent-fg-color;
background-color: $accent-color;

View File

@@ -17,8 +17,9 @@
@import "./matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_ConfirmUserActionDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_EncryptedEventDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_SetMxIdDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_UnknownDeviceDialog.scss";
@import "./matrix-react-sdk/views/elements/_AccessibleButton.scss";
@import "./matrix-react-sdk/views/elements/_AddressSelector.scss";
@import "./matrix-react-sdk/views/elements/_AddressTile.scss";
@import "./matrix-react-sdk/views/elements/_DirectorySearchBox.scss";
@@ -26,6 +27,7 @@
@import "./matrix-react-sdk/views/elements/_MemberEventListSummary.scss";
@import "./matrix-react-sdk/views/elements/_ProgressBar.scss";
@import "./matrix-react-sdk/views/elements/_RichText.scss";
@import "./matrix-react-sdk/views/elements/_RoleButton.scss";
@import "./matrix-react-sdk/views/login/_InteractiveAuthEntryComponents.scss";
@import "./matrix-react-sdk/views/login/_ServerConfig.scss";
@import "./matrix-react-sdk/views/messages/_MEmoteBody.scss";

View File

@@ -160,7 +160,8 @@ hr.mx_RoomView_myReadMarker {
border-bottom: solid 1px $accent-color;
margin-top: 0px;
position: relative;
top: 5px;
top: -1px;
z-index: 1;
}
.mx_RoomView_statusArea {
@@ -171,7 +172,7 @@ hr.mx_RoomView_myReadMarker {
max-height: 0px;
background-color: $primary-bg-color;
z-index: 1000;
z-index: 5;
overflow: hidden;
-webkit-transition: all .2s ease-out;
@@ -259,4 +260,4 @@ hr.mx_RoomView_myReadMarker {
.mx_RoomView_ongoingConfCallNotification a {
color: $accent-fg-color ! important;
}
}

View File

@@ -176,6 +176,15 @@ limitations under the License.
cursor: pointer;
}
.mx_UserSettings_phoneSection {
display:table;
}
.mx_UserSettings_phoneCountry {
width: 70px;
display: table-cell;
}
input.mx_UserSettings_phoneNumberField {
margin-left: 3px;
width: 172px;
@@ -213,3 +222,9 @@ input.mx_UserSettings_phoneNumberField {
.mx_UserSettings_avatarPicker_edit > input {
display: none;
}
.mx_UserSettings_advanced_spoiler {
cursor: pointer;
color: $accent-color;
word-break: break-all;
}

View File

@@ -42,7 +42,8 @@ limitations under the License.
.mx_Login_logo {
text-align: center;
height: 195px;
height: 150px;
margin-bottom: 45px;
}
.mx_Login_logo img {
@@ -66,10 +67,6 @@ limitations under the License.
margin-bottom: 14px;
}
.mx_Login_username {
margin-bottom: 0px;
}
.mx_Login_fieldLabel {
margin-top: -10px;
margin-left: 8px;
@@ -167,16 +164,82 @@ limitations under the License.
margin-bottom: 12px;
}
.mx_Login_phoneSection {
display: table;
.mx_Login_type_container {
display: flex;
margin-bottom: 14px;
}
.mx_Login_type_label {
flex-grow: 1;
line-height: 35px;
}
.mx_Login_type_dropdown {
width: 125px;
align-self: flex-end;
}
.mx_Login_field_group {
display: flex;
}
.mx_Login_field_prefix {
height: 33px;
padding: 0px 5px;
line-height: 33px;
background-color: #eee;
border: 1px solid #c7c7c7;
border-right: 0px;
border-radius: 3px 0px 0px 3px;
text-align: center;
}
.mx_Login_field_suffix {
height: 33px;
padding: 0px 5px;
line-height: 33px;
background-color: #eee;
border: 1px solid #c7c7c7;
border-left: 0px;
border-radius: 0px 3px 3px 0px;
text-align: center;
flex-grow: 1;
}
.mx_Login_username {
flex-shrink: 1;
min-width: 0px;
border-radius: 3px;
}
.mx_Login_field_has_prefix {
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
.mx_Login_field_has_suffix {
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
}
.mx_Login_phoneCountry {
display: table-cell;
width: 70px;
margin-bottom: 14px;
}
.mx_Login_phoneNumberField {
width: 210px;
margin-left: 3px;
.mx_Login_phoneCountry .mx_Dropdown_option {
/*
To match height of mx_Login_field
33px + 2px border from mx_Dropdown_option = 35px
*/
height: 33px;
line-height: 33px;
}
.mx_Login_phoneCountry .mx_Dropdown_option img {
margin: 4px;
vertical-align: top;
}

View File

@@ -0,0 +1,50 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations 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_SetMxIdDialog .mx_Dialog_title {
padding-right: 40px;
}
.mx_SetMxIdDialog_input_group {
display: flex;
}
.mx_SetMxIdDialog_input {
border-radius: 3px;
border: 1px solid $input-border-color;
padding: 9px;
color: $primary-fg-color;
background-color: $primary-bg-color;
font-size: 15px;
width: 100%;
max-width: 280px;
}
.mx_SetMxIdDialog_input.error,
.mx_SetMxIdDialog_input.error:focus {
border: 1px solid $warning-color;
}
.mx_SetMxIdDialog_input_group .mx_Spinner {
height: 37px;
padding-left: 10px;
justify-content: flex-start;
}
.mx_SetMxIdDialog .success {
color: $accent-color;
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,11 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_SetDisplayNameDialog_input {
border-radius: 3px;
border: 1px solid $input-border-color;
padding: 9px;
color: $primary-fg-color;
background-color: $primary-bg-color;
font-size: 15px;
}
.mx_AccessibleButton:focus {
outline: 0;
filter: brightness($focus-brightness);
}

View File

@@ -27,6 +27,15 @@ limitations under the License.
user-select: none;
}
.mx_Dropdown_input:focus {
border-color: $accent-color;
}
/* Disable dropdown highlight on focus */
.mx_Dropdown_input.mx_AccessibleButton:focus {
filter: none;
}
.mx_Dropdown_arrow {
border-color: $primary-fg-color transparent transparent;
border-style: solid;
@@ -74,7 +83,7 @@ input.mx_Dropdown_option, input.mx_Dropdown_option:focus {
border: 1px solid $accent-color;
background-color: $primary-bg-color;
max-height: 200px;
overflow-y: scroll;
overflow-y: auto;
}
.mx_Dropdown_menu .mx_Dropdown_option_highlight {

View File

@@ -20,6 +20,7 @@ limitations under the License.
.mx_TextualEvent.mx_MemberEventListSummary_summary {
font-size: 14px;
display: inline-flex;
}
.mx_MemberEventListSummary_avatars {

View File

@@ -0,0 +1,33 @@
/*
Copyright 2107 Vector Creations 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_RoleButton {
margin-left: 4px;
margin-right: 4px;
cursor: pointer;
display: inline-block;
}
.mx_RoleButton object {
pointer-events: none;
}
.mx_RoleButton_tooltip {
display: inline-block;
position: relative;
top: -25px;
left: 6px;
}

View File

@@ -133,10 +133,18 @@ limitations under the License.
.mx_EventTile_redacted .mx_EventTile_line .mx_UnknownBody {
display: block;
width: 100%;
max-width: 300px;
height: 24px;
border-radius: 4px;
background-color: black;
height: 36px;
background-image: $event-redacted-img;
background-repeat: no-repeat;
background-size: contain;
}
.mx_EventTile.mx_EventTile_redacted .mx_EventTile_line {
/*
Prevent changing colour of the background because
$event-redacted-img matches $primary-bg-color
*/
background-color: initial !important;
}
.mx_EventTile_highlight,
@@ -210,8 +218,8 @@ limitations under the License.
}
.mx_EventTile_continuation .mx_EventTile_readAvatars,
.mx_EventTile_info .mx_EventTile_readAvatars
{
.mx_EventTile_info .mx_EventTile_readAvatars,
.mx_EventTile_emote .mx_EventTile_readAvatars {
top: 7px;
}
@@ -323,6 +331,14 @@ limitations under the License.
font-family: inherit ! important;
}
/* Make h1 and h2 the same size as h3. */
.mx_EventTile_content .markdown-body h1,
.mx_EventTile_content .markdown-body h2
{
font-size: 1.5em;
}
.mx_EventTile_content .markdown-body a {
color: $accent-color;
}

View File

@@ -31,6 +31,7 @@ limitations under the License.
margin-left: -2px;
order: 1;
flex: 1;
overflow: hidden;
}
.mx_RoomHeader_spinner {
@@ -95,6 +96,12 @@ limitations under the License.
float: right;
}
.mx_RoomHeader_simpleHeader .mx_RoomHeader_icon {
margin-left: 14px;
margin-right: 24px;
vertical-align: -4px;
}
.mx_RoomHeader_name {
vertical-align: middle;
width: 100%;

View File

@@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2107 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -37,3 +38,25 @@ limitations under the License.
.mx_RoomList_scrollbar .gm-scrollbar.-vertical {
z-index: 6;
}
.mx_RoomList_emptySubListTip {
font-size: 13px;
margin-left: 18px;
margin-right: 18px;
margin-top: 8px;
margin-bottom: 7px;
padding: 5px;
border: 1px dashed $accent-color;
color: $primary-fg-color;
background-color: $droptarget-bg-color;
border-radius: 4px;
}
.mx_RoomList_emptySubListTip .mx_RoleButton {
vertical-align: -3px;
}
.mx_RoomList_headerButtons {
position: absolute;
right: 60px;
}

View File

@@ -156,7 +156,7 @@ limitations under the License.
}
.mx_RoomTile:focus {
outline: 0;
filter: none ! important;
background-color: $roomtile-focused-bg-color;
}

View File

@@ -17,20 +17,15 @@ limitations under the License.
.mx_TopUnreadMessagesBar {
margin: auto; /* centre horizontally */
max-width: 960px;
padding-top: 5px;
padding-bottom: 5px;
padding-top: 10px;
padding-bottom: 10px;
border-bottom: 1px solid $primary-hairline-color;
/* in absence of img */
height: 24px;
}
.mx_TopUnreadMessagesBar_scrollUp {
display: inline;
cursor: pointer;
/* in absence of img */
padding-left: 65px;
text-decoration: underline;
}
.mx_TopUnreadMessagesBar_scrollUp img {

View File

@@ -15,6 +15,8 @@ $accent-color: #76CFA6;
$selection-fg-color: $primary-bg-color;
$focus-brightness: 125%;
// red warning colour
$warning-color: #ff0064;
@@ -93,6 +95,9 @@ $event-encrypting-color: #abddbc;
$event-sending-color: #ddd;
$event-notsent-color: #f44;
// event redaction
$event-redacted-img: url('../../img/redacted.jpg');
// event timestamp
$event-timestamp-color: #acacac;

View File

@@ -15,6 +15,8 @@ $accent-color: #76CFA6;
$selection-fg-color: $primary-fg-color;
$focus-brightness: 200%;
// red warning colour
$warning-color: #ff0064;
@@ -93,6 +95,9 @@ $event-encrypting-color: rgba(171, 221, 188, 0.4);
$event-sending-color: #888;
$event-notsent-color: #f44;
// event redaction
$event-redacted-img: url('../../img/redacted-dark.jpg');
// event timestamp
$event-timestamp-color: #acacac;

View File

@@ -64,43 +64,25 @@ limitations under the License.
pointer-events: none;
}
.mx_LeftPanel .mx_BottomLeftMenu_homePage,
.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_homePage,
.collapsed .mx_BottomLeftMenu_directory,
.collapsed .mx_BottomLeftMenu_createRoom,
.collapsed .mx_BottomLeftMenu_people,
.collapsed .mx_BottomLeftMenu_settings {
.collapsed .mx_RoleButton {
margin-right: 0px ! important;
padding-top: 3px ! important;
padding-bottom: 3px ! important;
}
.mx_LeftPanel .mx_BottomLeftMenu_homePage,
.mx_LeftPanel .mx_BottomLeftMenu_directory,
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
.mx_LeftPanel .mx_BottomLeftMenu_people {
.mx_BottomLeftMenu_options .mx_RoleButton {
margin-left: 0px;
margin-right: 10px;
}
.mx_LeftPanel .mx_BottomLeftMenu_settings {
.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings {
float: right;
}
.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings .mx_RoleButton {
margin-right: 0px;
}
.mx_LeftPanel.collapsed .mx_BottomLeftMenu_settings {
float: none;
}
.mx_LeftPanel .mx_BottomLeftMenu_tooltip {
display: inline-block;
position: relative;
top: -25px;
left: 6px;
}

View File

@@ -21,12 +21,17 @@ limitations under the License.
margin-right: auto;
margin-bottom: 12px;
color: $primary-fg-color;
word-break: break-word;
display: flex;
flex-direction: column;
}
.mx_RoomDirectory .mx_RoomHeader_simpleHeader {
margin-left: 0px;
}
.mx_RoomDirectory_list {
flex: 1;

View File

@@ -33,11 +33,6 @@ limitations under the License.
margin-left: 10px;
}
.mx_RoomDropTarget_placeholder {
padding-top: 1px;
padding-bottom: 1px;
}
.mx_RoomDropTarget_label {
position: relative;
margin-top: 3px;

View File

@@ -1,21 +1,24 @@
<?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 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<title>E34C64ED-EBD7-49B6-BDD9-CB729162705A</title>
<desc>Created with sketchtool.</desc>
<defs>
<rect id="path-1" x="6" y="10" width="13" height="8" rx="1"></rect>
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="13" height="8" fill="white">
<use xlink:href="#path-1"></use>
</mask>
</defs>
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>icons_directory</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Room-list-Copy-3" transform="translate(-58.000000, -726.000000)">
<g id="icons_directory" transform="translate(58.000000, 726.000000)">
<path d="M12.5,25 C19.4035594,25 25,19.4035594 25,12.5 C25,5.59644063 19.4035594,0 12.5,0 C5.59644063,0 0,5.59644063 0,12.5 C0,19.4035594 5.59644063,25 12.5,25 Z" id="Oval-1-Copy-7" fill="#76CFA6"></path>
<use id="Rectangle-9" stroke="#FFFFFF" mask="url(#mask-2)" stroke-width="2" opacity="0.8" xlink:href="#path-1"></use>
<path d="M6,9 L6,6.99895656 C6,6.44724809 6.45097518,6 6.99077797,6 L11.009222,6 C11.5564136,6 12,6.44386482 12,7 L12,8 L17.9970707,8 C18.5509732,8 19,8.45318604 19,9 L19,9 L6,9 Z" id="Path-Copy" fill="#FFFFFF" opacity="0.6"></path>
<g id="Left-panel" transform="translate(-83.000000, -726.000000)">
<g id="icons_directory">
<g transform="translate(83.000000, 726.000000)">
<path d="M12.5,25 C19.4035594,25 25,19.4035594 25,12.5 C25,5.59644063 19.4035594,0 12.5,0 C5.59644063,0 0,5.59644063 0,12.5 C0,19.4035594 5.59644063,25 12.5,25 Z" id="Oval-1-Copy-7" fill="#76CFA6"></path>
<g id="Lines" transform="translate(6.000000, 7.000000)" stroke="#FFFFFF" stroke-linecap="round">
<path d="M4,5.5 L9,5.5" id="Line"></path>
<path d="M4,1.5 L13,1.5" id="Line-Copy-4"></path>
<path d="M0,1.5 L2,1.5" id="Line" opacity="0.6"></path>
<path d="M0,5.5 L2,5.5" id="Line" opacity="0.6"></path>
<path d="M4,9.5 L11,9.5" id="Line-Copy-6"></path>
<path d="M0,9.5 L2,9.5" id="Line-Copy-3" opacity="0.6"></path>
</g>
</g>
</g>
</g>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>Slice 1</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="scrollup">
<g id="02-Chat" transform="translate(12.000000, 12.000000) scale(-1, 1) rotate(-180.000000) translate(-12.000000, -12.000000) ">
<g id="02_7-Chat-new-messages">
<g id="icon_newmessages">
<circle id="Oval-1909" fill-opacity="0.5" fill="#454545" fill-rule="nonzero" cx="12" cy="12" r="12"></circle>
<circle id="Oval" stroke="#FFFFFF" cx="12" cy="12" r="7"></circle>
<circle id="Oval" stroke="#FFFFFF" cx="12" cy="12" r="4"></circle>
<circle id="Oval" fill="#FFFFFF" cx="12" cy="12" r="1"></circle>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -259,11 +259,15 @@ async function loadApp() {
let configError;
try {
configJson = await getConfig();
rageshake.setBugReportEndpoint(configJson.bug_report_endpoint_url);
} catch (e) {
configError = e;
}
if (window.localStorage && window.localStorage.getItem('mx_accepts_unsupported_browser')) {
console.log('User has previously accepted risks in using an unsupported browser');
validBrowser = true;
}
console.log("Vector starting at "+window.location);
if (configError) {
window.matrixChat = ReactDOM.render(<div className="error">
@@ -295,6 +299,7 @@ async function loadApp() {
var CompatibilityPage = sdk.getComponent("structures.CompatibilityPage");
window.matrixChat = ReactDOM.render(
<CompatibilityPage onAccept={function() {
if (window.localStorage) window.localStorage.setItem('mx_accepts_unsupported_browser', true);
validBrowser = true;
console.log("User accepts the compatibility risks.");
loadApp();

View File

@@ -20,22 +20,20 @@ limitations under the License.
import VectorBasePlatform from './VectorBasePlatform';
import dis from 'matrix-react-sdk/lib/dispatcher';
import q from 'q';
import electron, {remote} from 'electron';
const electron = require('electron');
const remote = electron.remote;
remote.autoUpdater.on('update-downloaded', onUpdateDownloaded);
electron.remote.autoUpdater.on('update-downloaded', onUpdateDownloaded);
function onUpdateDownloaded(ev, releaseNotes, ver, date, updateURL) {
function onUpdateDownloaded(ev: Event, releaseNotes: string, ver: string, date: Date, updateURL: string) {
dis.dispatch({
action: 'new_version',
currentVersion: electron.remote.app.getVersion(),
currentVersion: remote.app.getVersion(),
newVersion: ver,
releaseNotes: releaseNotes,
});
}
function platformFriendlyName() {
function platformFriendlyName(): string {
console.log(window.process);
switch (window.process.platform) {
case 'darwin':
@@ -68,40 +66,52 @@ export default class ElectronPlatform extends VectorBasePlatform {
try {
remote.app.setBadgeCount(count);
} catch (e) {
console.error("Failed to set notification count", e);
console.error('Failed to set notification count', e);
}
}
supportsNotifications() : boolean {
supportsNotifications(): boolean {
return true;
}
maySendNotifications() : boolean {
maySendNotifications(): boolean {
return true;
}
displayNotification(title: string, msg: string, avatarUrl: string, room: Object): Notification {
// GNOME notification spec parses HTML tags for styling...
// Electron Docs state all supported linux notification systems follow this markup spec
// https://github.com/electron/electron/blob/master/docs/tutorial/desktop-environment-integration.md#linux
// maybe we should pass basic styling (italics, bold, underline) through from MD
// we only have to strip out < and > as the spec doesn't include anything about things like &amp;
// so we shouldn't assume that all implementations will treat those properly. Very basic tag parsing is done.
if (window.process.platform === 'linux') {
msg = msg.replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
// Notifications in Electron use the HTML5 notification API
const notification = new global.Notification(
title,
{
body: msg,
icon: avatarUrl,
tag: "vector",
tag: 'vector',
silent: true, // we play our own sounds
}
},
);
notification.onclick = function() {
dis.dispatch({
action: 'view_room',
room_id: room.roomId
room_id: room.roomId,
});
global.focus();
const currentWin = electron.remote.getCurrentWindow();
currentWin.show();
currentWin.restore();
currentWin.focus();
const win = remote.getCurrentWindow();
if (win.isMinimized()) win.restore();
else if (!win.isVisible()) win.show();
else win.focus();
};
return notification;
@@ -111,8 +121,8 @@ export default class ElectronPlatform extends VectorBasePlatform {
notif.close();
}
getAppVersion() {
return q(electron.remote.app.getVersion());
getAppVersion(): Promise<string> {
return q(remote.app.getVersion());
}
pollForUpdate() {
@@ -128,15 +138,19 @@ export default class ElectronPlatform extends VectorBasePlatform {
electron.ipcRenderer.send('install_update');
}
getDefaultDeviceDisplayName() {
return "Riot Desktop on " + platformFriendlyName();
getDefaultDeviceDisplayName(): string {
return 'Riot Desktop on ' + platformFriendlyName();
}
screenCaptureErrorString() {
screenCaptureErrorString(): ?string {
return null;
}
requestNotificationPermission() : Promise {
requestNotificationPermission(): Promise<string> {
return q('granted');
}
reload() {
remote.getCurrentWebContents().reload();
}
}

View File

@@ -44,7 +44,7 @@ export default class VectorBasePlatform extends BasePlatform {
* Get a sensible default display name for the
* device Vector is running on
*/
getDefaultDeviceDisplayName() {
getDefaultDeviceDisplayName(): string {
return "Unknown device";
}
}

View File

@@ -52,7 +52,7 @@ export default class WebPlatform extends VectorBasePlatform {
}
this.favicon.badge(notif, {
bgColor: bgColor
bgColor: bgColor,
});
} catch (e) {
console.warn(`Failed to set badge count: ${e.message}`);
@@ -75,7 +75,7 @@ export default class WebPlatform extends VectorBasePlatform {
* Returns true if the platform supports displaying
* notifications, otherwise false.
*/
supportsNotifications() : boolean {
supportsNotifications(): boolean {
return Boolean(global.Notification);
}
@@ -83,8 +83,8 @@ export default class WebPlatform extends VectorBasePlatform {
* Returns true if the application currently has permission
* to display notifications. Otherwise false.
*/
maySendNotifications() : boolean {
return global.Notification.permission == 'granted';
maySendNotifications(): boolean {
return global.Notification.permission === 'granted';
}
/**
@@ -94,7 +94,7 @@ export default class WebPlatform extends VectorBasePlatform {
* that is 'granted' if the user allowed the request or
* 'denied' otherwise.
*/
requestNotificationPermission() : Promise {
requestNotificationPermission(): Promise<string> {
// annoyingly, the latest spec says this returns a
// promise, but this is only supported in Chrome 46
// and Firefox 47, so adapt the callback API.
@@ -113,13 +113,13 @@ export default class WebPlatform extends VectorBasePlatform {
icon: avatarUrl,
tag: "vector",
silent: true, // we play our own sounds
}
},
);
notification.onclick = function() {
dis.dispatch({
action: 'view_room',
room_id: room.roomId
room_id: room.roomId,
});
global.focus();
notification.close();
@@ -132,7 +132,7 @@ export default class WebPlatform extends VectorBasePlatform {
}, 5 * 1000);
}
_getVersion() {
_getVersion(): Promise<string> {
const deferred = q.defer();
// We add a cachebuster to the request to make sure that we know about
@@ -148,19 +148,19 @@ export default class WebPlatform extends VectorBasePlatform {
},
(err, response, body) => {
if (err || response.status < 200 || response.status >= 300) {
if (err == null) err = { status: response.status };
if (err === null) err = { status: response.status };
deferred.reject(err);
return;
}
const ver = body.trim();
deferred.resolve(ver);
}
},
);
return deferred.promise;
}
getAppVersion() {
getAppVersion(): Promise<string> {
if (this.runningVersion !== null) {
return q(this.runningVersion);
}
@@ -169,9 +169,9 @@ export default class WebPlatform extends VectorBasePlatform {
pollForUpdate() {
this._getVersion().done((ver) => {
if (this.runningVersion == null) {
if (this.runningVersion === null) {
this.runningVersion = ver;
} else if (this.runningVersion != ver) {
} else if (this.runningVersion !== ver) {
dis.dispatch({
action: 'new_version',
currentVersion: this.runningVersion,
@@ -187,23 +187,28 @@ export default class WebPlatform extends VectorBasePlatform {
window.location.reload();
}
getDefaultDeviceDisplayName() {
getDefaultDeviceDisplayName(): string {
// strip query-string and fragment from uri
let u = url.parse(window.location.href);
const u = url.parse(window.location.href);
u.search = "";
u.hash = "";
let app_name = u.format();
const appName = u.format();
let ua = new UAParser();
return app_name + " via " + ua.getBrowser().name +
" on " + ua.getOS().name;
const ua = new UAParser();
return `${appName} via ${ua.getBrowser().name} on ${ua.getOS().name}`;
}
screenCaptureErrorString() {
screenCaptureErrorString(): ?string {
// it won't work at all if you're not on HTTPS so whine whine whine
if (!global.window || global.window.location.protocol !== "https:") {
return "You need to be using HTTPS to place a screen-sharing call.";
}
return null;
}
reload() {
// forceReload=false since we don't really need new HTML/JS files
// we just need to restart the JS runtime.
window.location.reload(false);
}
}

View File

@@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
import request from "browser-request";
import q from "q";
// This module contains all the code needed to log the console, persist it to
@@ -205,9 +203,6 @@ class IndexedDBLogStore {
}
let txn = this.db.transaction(["logs", "logslastmod"], "readwrite");
let objStore = txn.objectStore("logs");
objStore.add(this._generateLogEntry(lines));
let lastModStore = txn.objectStore("logslastmod");
lastModStore.put(this._generateLastModifiedTime());
txn.oncomplete = (event) => {
resolve();
};
@@ -219,6 +214,9 @@ class IndexedDBLogStore {
new Error("Failed to write logs: " + event.target.errorCode)
);
}
objStore.add(this._generateLogEntry(lines));
let lastModStore = txn.objectStore("logslastmod");
lastModStore.put(this._generateLastModifiedTime());
});
return this.flushPromise;
}
@@ -396,7 +394,6 @@ function selectQuery(store, keyRange, resultMapper) {
let store = null;
let logger = null;
let initPromise = null;
let bugReportEndpoint = null;
module.exports = {
/**
@@ -430,80 +427,29 @@ module.exports = {
await store.consume();
},
setBugReportEndpoint: function(url) {
bugReportEndpoint = url;
},
/**
* Send a bug report.
* @param {string} userText Any additional user input.
* @param {boolean} sendLogs True to send logs
* @return {Promise} Resolved when the bug report is sent.
* Get a recent snapshot of the logs, ready for attaching to a bug report
*
* @return {Array<{lines: string, id, string}>} list of log data
*/
sendBugReport: async function(userText, sendLogs) {
getLogsForReport: async function() {
if (!logger) {
throw new Error(
"No console logger, did you forget to call init()?"
);
}
if (!bugReportEndpoint) {
throw new Error("No bug report endpoint has been set.");
}
let version = "UNKNOWN";
try {
version = await PlatformPeg.get().getAppVersion();
}
catch (err) {} // PlatformPeg already logs this.
let userAgent = "UNKNOWN";
if (window.navigator && window.navigator.userAgent) {
userAgent = window.navigator.userAgent;
}
// If in incognito mode, store is null, but we still want bug report
// sending to work going off the in-memory console logs.
console.log("Sending bug report.");
let logs = [];
if (sendLogs) {
if (store) {
// flush most recent logs
await store.flush();
logs = await store.consume();
}
else {
logs.push({
lines: logger.flush(true),
id: "-",
});
}
if (store) {
// flush most recent logs
await store.flush();
return await store.consume();
}
await q.Promise((resolve, reject) => {
request({
method: "POST",
url: bugReportEndpoint,
body: {
logs: logs,
text: (
userText || "User did not supply any additional text."
),
version: version,
user_agent: userAgent,
},
json: true,
timeout: 5 * 60 * 1000,
}, (err, res) => {
if (err) {
reject(err);
return;
}
if (res.status < 200 || res.status >= 400) {
reject(new Error(`HTTP ${res.status}`));
return;
}
resolve();
})
});
}
else {
return [{
lines: logger.flush(true),
id: "-",
}];
}
},
};

View File

@@ -0,0 +1,124 @@
/*
Copyright 2017 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 pako from 'pako';
import q from "q";
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
import rageshake from './rageshake'
// polyfill textencoder if necessary
import * as TextEncodingUtf8 from 'text-encoding-utf-8';
let TextEncoder = window.TextEncoder;
if (!TextEncoder) {
TextEncoder = TextEncodingUtf8.TextEncoder;
}
/**
* Send a bug report.
*
* @param {string} bugReportEndpoint HTTP url to send the report to
*
* @param {object} opts optional dictionary of options
*
* @param {string} opts.userText Any additional user input.
*
* @param {boolean} opts.sendLogs True to send logs
*
* @param {function(string)} opts.progressCallback Callback to call with progress updates
*
* @return {Promise} Resolved when the bug report is sent.
*/
export default async function sendBugReport(bugReportEndpoint, opts) {
if (!bugReportEndpoint) {
throw new Error("No bug report endpoint has been set.");
}
opts = opts || {};
const progressCallback = opts.progressCallback || (() => {});
progressCallback("Collecting app version information");
let version = "UNKNOWN";
try {
version = await PlatformPeg.get().getAppVersion();
}
catch (err) {} // PlatformPeg already logs this.
let userAgent = "UNKNOWN";
if (window.navigator && window.navigator.userAgent) {
userAgent = window.navigator.userAgent;
}
const client = MatrixClientPeg.get();
console.log("Sending bug report.");
const body = new FormData();
body.append('text', opts.userText || "User did not supply any additional text.");
body.append('app', 'riot-web');
body.append('version', version);
body.append('user_agent', userAgent);
if (client) {
body.append('user_id', client.credentials.userId);
body.append('device_id', client.deviceId);
}
if (opts.sendLogs) {
progressCallback("Collecting logs");
const logs = await rageshake.getLogsForReport();
for (let entry of logs) {
// encode as UTF-8
const buf = new TextEncoder().encode(entry.lines);
// compress
const compressed = pako.gzip(buf);
body.append('compressed-log', new Blob([compressed]), entry.id);
}
}
progressCallback("Uploading report");
await _submitReport(bugReportEndpoint, body, progressCallback);
}
function _submitReport(endpoint, body, progressCallback) {
const deferred = q.defer();
const req = new XMLHttpRequest();
req.open("POST", endpoint);
req.timeout = 5 * 60 * 1000;
req.onreadystatechange = function() {
if (req.readyState === XMLHttpRequest.LOADING) {
progressCallback("Waiting for response from server");
} else if (req.readyState === XMLHttpRequest.DONE) {
on_done();
}
};
req.send(body);
return deferred.promise;
function on_done() {
if (req.status < 200 || req.status >= 400) {
deferred.reject(new Error(`HTTP ${req.status}`));
return;
}
deferred.resolve();
}
}

View File

@@ -72,14 +72,13 @@ describe('joining a room', function () {
var ROOM_ALIAS = '#alias:localhost';
var ROOM_ID = '!id:localhost';
httpBackend.when('PUT', '/presence/'+encodeURIComponent(USER_ID)+'/status')
.respond(200, {});
httpBackend.when('GET', '/pushrules').respond(200, {});
httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
httpBackend.when('GET', '/sync').respond(200, {});
httpBackend.when('POST', '/publicRooms').respond(200, {chunk: []});
httpBackend.when('GET', '/thirdparty/protocols').respond(200, {});
httpBackend.when('GET', '/directory/room/'+encodeURIComponent(ROOM_ALIAS)).respond(200, { room_id: ROOM_ID });
// note that we deliberately do *not* set an expectation for a
// presence update - setting one makes the first httpBackend.flush
// return before the first /sync arrives.
// start with a logged-in client
localStorage.setItem("mx_hs_url", HS_URL );
@@ -94,9 +93,18 @@ describe('joining a room', function () {
matrixChat._setPage(PageTypes.RoomDirectory);
var roomView;
// wait for /sync to happen
return q.delay(1).then(() => {
return httpBackend.flush();
}).then(() => {
// wait for the directory requests
httpBackend.when('POST', '/publicRooms').respond(200, {chunk: []});
httpBackend.when('GET', '/thirdparty/protocols').respond(200, {});
return q.all([
httpBackend.flush('/publicRooms'),
httpBackend.flush('/thirdparty/protocols'),
]);
}).then(() => {
var roomDir = ReactTestUtils.findRenderedComponentWithType(
matrixChat, RoomDirectory);
@@ -110,6 +118,7 @@ describe('joining a room', function () {
// that should create a roomview which will start a peek; wait
// for the peek.
httpBackend.when('GET', '/directory/room/'+encodeURIComponent(ROOM_ALIAS)).respond(200, { room_id: ROOM_ID });
httpBackend.when('GET', '/rooms/'+encodeURIComponent(ROOM_ID)+"/initialSync")
.respond(401, {errcode: 'M_GUEST_ACCESS_FORBIDDEN'});
return httpBackend.flush();

View File

@@ -1,7 +1,7 @@
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
@@ -19,11 +19,11 @@ module.exports = {
// CSS themes
"theme-light": "./src/skins/vector/css/themes/light.scss",
"theme-dark": "./src/skins/vector/css/themes/dark.scss"
"theme-dark": "./src/skins/vector/css/themes/dark.scss",
},
module: {
preLoaders: [
{ test: /\.js$/, loader: "source-map-loader" }
{ test: /\.js$/, loader: "source-map-loader" },
],
loaders: [
{ test: /\.json$/, loader: "json" },
@@ -38,9 +38,7 @@ module.exports = {
// would also drag in the imgs and fonts that our CSS refers to
// as webpack inputs.)
// 3. ExtractTextPlugin turns that string into a separate asset.
loader: ExtractTextPlugin.extract(
"css-raw-loader!postcss-loader?config=postcss.config.js"
),
loader: ExtractTextPlugin.extract("css-raw-loader!postcss-loader?config=postcss.config.js"),
},
{
// this works similarly to the scss case, without postcss.
@@ -49,15 +47,18 @@ module.exports = {
},
],
noParse: [
// for cross platform compatibility use [\\\/] as the path separator
// this ensures that the regex trips on both Windows and *nix
// don't parse the languages within highlight.js. They cause stack
// overflows (https://github.com/webpack/webpack/issues/1721), and
// there is no need for webpack to parse them - they can just be
// included as-is.
/highlight\.js\/lib\/languages/,
/highlight\.js[\\\/]lib[\\\/]languages/,
// olm takes ages for webpack to process, and it's already heavily
// optimised, so there is little to gain by us uglifying it.
/olm\/(javascript\/)?olm\.js$/,
/olm[\\\/](javascript[\\\/])?olm\.js$/,
],
},
output: {
@@ -83,7 +84,7 @@ module.exports = {
// various levels of '.' and '..'
// Also, sometimes the resource path is absolute.
return path.relative(process.cwd(), info.resourcePath).replace(/^[\/\.]*/, '');
}
},
},
resolve: {
alias: {
@@ -106,16 +107,13 @@ module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
},
}),
new ExtractTextPlugin(
"bundles/[hash]/[name].css",
{
allChunks: true
}
),
new ExtractTextPlugin("bundles/[hash]/[name].css", {
allChunks: true,
}),
new HtmlWebpackPlugin({
template: './src/vector/index.html',