diff --git a/res/css/_components.scss b/res/css/_components.scss index c43d9edc16..8fc1667fb5 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -18,7 +18,7 @@ @import "./structures/_RoomView.scss"; @import "./structures/_SearchBox.scss"; @import "./structures/_TagPanel.scss"; -@import "./structures/_TopLeftMenu.scss"; +@import "./structures/_TopLeftMenuButton.scss"; @import "./structures/_UploadBar.scss"; @import "./structures/_UserSettings.scss"; @import "./structures/_ViewSource.scss"; @@ -27,6 +27,7 @@ @import "./views/context_menus/_MessageContextMenu.scss"; @import "./views/context_menus/_RoomTileContextMenu.scss"; @import "./views/context_menus/_TagTileContextMenu.scss"; +@import "./views/context_menus/_TopLeftMenu.scss"; @import "./views/dialogs/_BugReportDialog.scss"; @import "./views/dialogs/_ChangelogDialog.scss"; @import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss"; diff --git a/res/css/structures/_ContextualMenu.scss b/res/css/structures/_ContextualMenu.scss index 7474c3d107..fa69c6fb90 100644 --- a/res/css/structures/_ContextualMenu.scss +++ b/res/css/structures/_ContextualMenu.scss @@ -30,12 +30,11 @@ limitations under the License. } .mx_ContextualMenu { - border: solid 1px $menu-border-color; - border-radius: 4px; + border-radius: 2px; + box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.21); background-color: $menu-bg-color; color: $primary-fg-color; position: absolute; - padding: 6px; font-size: 14px; z-index: 5001; } @@ -44,6 +43,10 @@ limitations under the License. right: 8px; } +.mx_ContextualMenu_noChevron { + border-radius: unset !important; +} + .mx_ContextualMenu_chevron_right { position: absolute; right: -8px; @@ -51,7 +54,7 @@ limitations under the License. width: 0; height: 0; border-top: 8px solid transparent; - border-left: 8px solid $menu-border-color; + border-left: 8px solid $menu-bg-color; border-bottom: 8px solid transparent; } @@ -78,7 +81,7 @@ limitations under the License. width: 0; height: 0; border-top: 8px solid transparent; - border-right: 8px solid $menu-border-color; + border-right: 8px solid $menu-bg-color; border-bottom: 8px solid transparent; } @@ -105,7 +108,7 @@ limitations under the License. width: 0; height: 0; border-left: 8px solid transparent; - border-bottom: 8px solid $menu-border-color; + border-bottom: 8px solid $menu-bg-color; border-right: 8px solid transparent; } @@ -132,7 +135,7 @@ limitations under the License. width: 0; height: 0; border-left: 8px solid transparent; - border-top: 8px solid $menu-border-color; + border-top: 8px solid $menu-bg-color; border-right: 8px solid transparent; } diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index e83f802012..1b73576246 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -139,9 +139,8 @@ limitations under the License. } .mx_RoomView_MessageList { - width: 100%; list-style-type: none; - padding: 0px; + padding: 18px; } .mx_RoomView_MessageList li { diff --git a/res/css/structures/_TopLeftMenu.scss b/res/css/structures/_TopLeftMenuButton.scss similarity index 69% rename from res/css/structures/_TopLeftMenu.scss rename to res/css/structures/_TopLeftMenuButton.scss index 86f88448a0..a80e06c620 100644 --- a/res/css/structures/_TopLeftMenu.scss +++ b/res/css/structures/_TopLeftMenuButton.scss @@ -14,28 +14,31 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_TopLeftMenu { +.mx_TopLeftMenuButton { height: 52px; border-bottom: 1px solid $panel-divider-color; color: $topleftmenu-color; background-color: $primary-bg-color; display: flex; + align-items: center; + min-width: 0; + padding: 0 7px; + overflow: hidden; } -.mx_TopLeftMenu_avatar { - position: relative; // to get avatar in the right place - margin-left: 15px; - margin-right: 15px; - margin-top: 14px; +.mx_TopLeftMenuButton .mx_BaseAvatar { + margin: 0 7px; } -.mx_TopLeftMenu_name { - margin-top: 15px; - margin-right: 9px; +.mx_TopLeftMenuButton_name { + margin: 0 7px; font-size: 18px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; font-weight: 600; } -.mx_TopLeftMenu_chevron { - margin-top: 24px; +.mx_TopLeftMenuButton_chevron { + margin: 0 7px; } diff --git a/res/css/views/context_menus/_MessageContextMenu.scss b/res/css/views/context_menus/_MessageContextMenu.scss index 85e8080c88..d15d566bdb 100644 --- a/res/css/views/context_menus/_MessageContextMenu.scss +++ b/res/css/views/context_menus/_MessageContextMenu.scss @@ -14,6 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ +.mx_MessageContextMenu { + padding: 6px; +} + .mx_MessageContextMenu_field { padding: 3px 6px 3px 6px; cursor: pointer; diff --git a/res/css/views/context_menus/_RoomTileContextMenu.scss b/res/css/views/context_menus/_RoomTileContextMenu.scss index 598f8ac249..f832691be4 100644 --- a/res/css/views/context_menus/_RoomTileContextMenu.scss +++ b/res/css/views/context_menus/_RoomTileContextMenu.scss @@ -14,6 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ +.mx_RoomTileContextMenu { + padding: 6px; +} + .mx_RoomTileContextMenu_tag_field, .mx_RoomTileContextMenu_leave { padding-top: 8px; padding-right: 20px; diff --git a/res/css/views/context_menus/_TopLeftMenu.scss b/res/css/views/context_menus/_TopLeftMenu.scss new file mode 100644 index 0000000000..960e052a30 --- /dev/null +++ b/res/css/views/context_menus/_TopLeftMenu.scss @@ -0,0 +1,39 @@ +/* +Copyright 2018 New Vector 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_TopLeftMenu { + min-width: 180px; + + .mx_TopLeftMenu_section:not(:last-child) { + border-bottom: 1px solid $menu-border-color; + } + + .mx_TopLeftMenu_section { + list-style: none; + margin: 5px 0; + padding: 0; + + li { + white-space: nowrap; + padding: 5px 20px; + } + + li:hover { + background-color: $menu-selected-color; + } + } + +} diff --git a/res/css/views/messages/_DateSeparator.scss b/res/css/views/messages/_DateSeparator.scss index f676d24bef..f8738f10e3 100644 --- a/res/css/views/messages/_DateSeparator.scss +++ b/res/css/views/messages/_DateSeparator.scss @@ -16,10 +16,21 @@ limitations under the License. .mx_DateSeparator { clear: both; - margin-top: 32px; - margin-bottom: 8px; - margin-left: 63px; - padding-bottom: 6px; - border-bottom: 1px solid $primary-hairline-color; + margin: 4px 0; + display: flex; + align-items: center; + font-size: 14px; + color: $roomtopic-color; } +.mx_DateSeparator > hr { + flex: 1 1 0; + height: 0; + border: none; + border-bottom: 1px solid $panel-divider-color; +} + +.mx_DateSeparator > date { + margin: 0 25px; + flex: 0 0 auto; +} diff --git a/res/css/views/messages/_SenderProfile.scss b/res/css/views/messages/_SenderProfile.scss index 060709b82e..a4a2aba11f 100644 --- a/res/css/views/messages/_SenderProfile.scss +++ b/res/css/views/messages/_SenderProfile.scss @@ -13,3 +13,41 @@ 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_SenderProfile_name { + font-weight: 600; +} + +.mx_SenderProfile_color1 { + color: $username-variant1-color; +} + +.mx_SenderProfile_color2 { + color: $username-variant2-color; +} + +.mx_SenderProfile_color3 { + color: $username-variant3-color; +} + +.mx_SenderProfile_color4 { + color: $username-variant4-color; +} + +.mx_SenderProfile_color5 { + color: $username-variant5-color; +} + +.mx_SenderProfile_color6 { + color: $username-variant6-color; +} + +.mx_SenderProfile_color7 { + color: $username-variant7-color; +} + +.mx_SenderProfile_color8 { + color: $username-variant8-color; +} + + diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index f74e2e0850..52074563f6 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -55,11 +55,6 @@ limitations under the License. line-height: 22px; } -.mx_EventTile .mx_SenderProfile .mx_SenderProfile_name, -.mx_EventTile .mx_SenderProfile .mx_SenderProfile_aux { - opacity: 0.5; -} - .mx_EventTile .mx_SenderProfile .mx_Flair { opacity: 0.7; margin-left: 5px; diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index 1cd368860f..39640575ba 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -57,26 +57,25 @@ limitations under the License. width: 100%; } -.mx_MessageComposer_row > div:last-child{ - padding-right: 0; -} - .mx_MessageComposer .mx_MessageComposer_avatar { - padding-left: 10px; - padding-right: 28px; + padding: 0 28px; } .mx_MessageComposer .mx_MessageComposer_avatar .mx_BaseAvatar { display: block; } +.mx_MessageComposer .mx_AccessibleButton { + padding: 0 12px 0 0; +} + .mx_MessageComposer_composecontrols { width: 100%; } .mx_MessageComposer_e2eIcon { position: absolute; - left: 44px; + left: 60px; } .mx_MessageComposer_noperm_error { diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 7e2e5683d9..fa28db69ae 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -24,17 +24,13 @@ limitations under the License. height: 52px; align-items: center; display: flex; -} - -.mx_RoomHeader_leftRow { - display: flex; - margin-left: 15px; - order: 1; - flex: 1; - overflow: hidden; + align-items: center; + min-width: 0; + padding: 0 10px 0 19px; } .mx_RoomHeader_spinner { + flex: 1; height: 36px; order: 2; padding-left: 12px; @@ -63,12 +59,11 @@ limitations under the License. padding-right: 12px; } -.mx_RoomHeader_rightRow { - margin-top: 4px; - background-color: $primary-bg-color; +.mx_RoomHeader_buttons { display: flex; align-items: center; - order: 3; + margin-top: 4px; + background-color: $primary-bg-color; } .mx_RoomHeader_info { @@ -99,19 +94,19 @@ limitations under the License. } .mx_RoomHeader_name { + flex: 0 1 auto; overflow: hidden; color: $roomheader-color; font-weight: 600; font-size: 18px; - padding-left: 15px; - padding-right: 15px; - /* why isn't text-overflow working? */ - text-overflow: ellipsis; + margin: 0 7px; border-bottom: 1px solid transparent; } .mx_RoomHeader_nametext { - display: inline-block; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; } .mx_RoomHeader_settingsHint { @@ -163,20 +158,23 @@ limitations under the License. } .mx_RoomHeader_topic { - max-height: 38px; + flex: 1; color: $roomtopic-color; font-weight: 400; font-size: 13px; - margin-right: 13px; + margin: 0 7px; overflow: hidden; text-overflow: ellipsis; border-bottom: 1px solid transparent; + line-height: 1.2em; + max-height: 2.4em; } .mx_RoomHeader_avatar { flex: 0; width: 28px; height: 28px; + margin: 0 7px; } .mx_RoomHeader_avatar .mx_BaseAvatar_image { diff --git a/res/css/views/rooms/_RoomTooltip.scss b/res/css/views/rooms/_RoomTooltip.scss index 9988425b8f..295786d2d3 100644 --- a/res/css/views/rooms/_RoomTooltip.scss +++ b/res/css/views/rooms/_RoomTooltip.scss @@ -21,7 +21,7 @@ limitations under the License. width: 0; height: 0; border-top: 8px solid transparent; - border-right: 8px solid $menu-border-color; + border-right: 8px solid $menu-bg-color; border-bottom: 8px solid transparent; } @@ -40,8 +40,8 @@ limitations under the License. .mx_RoomTooltip { display: none; position: fixed; - border: 1px solid $menu-border-color; border-radius: 5px; + box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.21); background-color: $primary-bg-color; z-index: 2000; padding: 5px; diff --git a/res/img/icon-call.svg b/res/img/icon-call.svg index 0ca5c29e9d..98677e3c70 100644 --- a/res/img/icon-call.svg +++ b/res/img/icon-call.svg @@ -1,8 +1,3 @@ - - - - - - - + + diff --git a/res/img/icon-invite-people.svg b/res/img/icon-invite-people.svg index f13a03ed70..3c168e173e 100644 --- a/res/img/icon-invite-people.svg +++ b/res/img/icon-invite-people.svg @@ -1,24 +1,5 @@ - - - - 9BA71BF4-DC4F-42D2-B2D0-9EAE0F7F8D45 - Created with sketchtool. - - - - - - - - - - - - - - - - - - + + + + diff --git a/res/img/icon_context.svg b/res/img/icon_context.svg new file mode 100644 index 0000000000..600c5bbd1d --- /dev/null +++ b/res/img/icon_context.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/res/img/icon_context_copy.svg b/res/img/icon_context_copy.svg new file mode 100644 index 0000000000..1f9c0b01e8 --- /dev/null +++ b/res/img/icon_context_copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/icon_context_edit.svg b/res/img/icon_context_edit.svg new file mode 100644 index 0000000000..6f7f1fd385 --- /dev/null +++ b/res/img/icon_context_edit.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/icon_context_fave.svg b/res/img/icon_context_fave.svg index da7b14a1f4..5c287787bb 100644 --- a/res/img/icon_context_fave.svg +++ b/res/img/icon_context_fave.svg @@ -1,12 +1,3 @@ - - - - - - - - - - - + + diff --git a/res/img/icon_context_leave.svg b/res/img/icon_context_leave.svg new file mode 100644 index 0000000000..3fdd452a59 --- /dev/null +++ b/res/img/icon_context_leave.svg @@ -0,0 +1,4 @@ + + + + diff --git a/res/img/icon_context_reply.svg b/res/img/icon_context_reply.svg new file mode 100644 index 0000000000..0a85f8e606 --- /dev/null +++ b/res/img/icon_context_reply.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/icons-apps.svg b/res/img/icons-apps.svg index affd8e6408..e2fe49b005 100644 --- a/res/img/icons-apps.svg +++ b/res/img/icons-apps.svg @@ -1,14 +1,12 @@ - - - - - - - - - - - + + + + + + + + + + diff --git a/res/img/icons-create-room.svg b/res/img/icons-create-room.svg index 252bd2df3b..78c45563d1 100644 --- a/res/img/icons-create-room.svg +++ b/res/img/icons-create-room.svg @@ -1,18 +1,4 @@ - - - - 0F9BCC43-B3A7-4C9F-8E34-1F38194362C2 - Created with sketchtool. - - - - - - - - - - - - + + + diff --git a/res/img/icons-files.svg b/res/img/icons-files.svg index 97ba4228e3..ea270fbc73 100644 --- a/res/img/icons-files.svg +++ b/res/img/icons-files.svg @@ -1,29 +1,5 @@ - - - - 7C98C075-AB4D-45A3-85F9-CCD46F84DA7F - Created with sketchtool. - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + diff --git a/res/img/icons-notifications.svg b/res/img/icons-notifications.svg index 66a49d6c0c..cde30713e1 100644 --- a/res/img/icons-notifications.svg +++ b/res/img/icons-notifications.svg @@ -1,19 +1,3 @@ - - - - 5E723325-BD0B-454D-BE25-638AF09A97AC - Created with sketchtool. - - - - - - - - - - - - - - \ No newline at end of file + + + diff --git a/res/img/icons-people.svg b/res/img/icons-people.svg index 8854506127..f3761c6c5f 100644 --- a/res/img/icons-people.svg +++ b/res/img/icons-people.svg @@ -1,22 +1,3 @@ - - - - 81230A28-D944-4572-B5DB-C03CAA2B1FCA - Created with sketchtool. - - - - - - - - - - - - - - - - + + diff --git a/res/img/icons-search.svg b/res/img/icons-search.svg index d85709e66c..8b1ce43264 100644 --- a/res/img/icons-search.svg +++ b/res/img/icons-search.svg @@ -2,8 +2,7 @@ - - - + + diff --git a/res/img/icons-settings-room.svg b/res/img/icons-settings-room.svg index 117d134c95..421eefdefa 100644 --- a/res/img/icons-settings-room.svg +++ b/res/img/icons-settings-room.svg @@ -1,15 +1,6 @@ - - - - 69011392-CE9D-4404-A85C-A8548C5D850B - Created with sketchtool. - - - - - - - - - + + + + + diff --git a/res/img/icons-share.svg b/res/img/icons-share.svg index b27616d5d5..aac19080f4 100644 --- a/res/img/icons-share.svg +++ b/res/img/icons-share.svg @@ -1,6 +1,6 @@ - + diff --git a/res/img/icons-stickers.svg b/res/img/icons-stickers.svg new file mode 100644 index 0000000000..564ebdac97 --- /dev/null +++ b/res/img/icons-stickers.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/res/img/icons-upload.svg b/res/img/icons-upload.svg index b0101e87a0..3aea924478 100644 --- a/res/img/icons-upload.svg +++ b/res/img/icons-upload.svg @@ -1,12 +1,3 @@ - - - - - - - - - - - + + diff --git a/res/img/icons-video.svg b/res/img/icons-video.svg index d367f49609..c61a782cc4 100644 --- a/res/img/icons-video.svg +++ b/res/img/icons-video.svg @@ -1,20 +1,3 @@ - - - - 05D354CE-86A7-4B6F-B9BE-F1CEBBD81B21 - Created with sketchtool. - - - - - - - - - - - - - - + + diff --git a/res/img/maximise.svg b/res/img/maximise.svg index 79c6c0ab8b..981e3796de 100644 --- a/res/img/maximise.svg +++ b/res/img/maximise.svg @@ -1,19 +1,19 @@ - - - -minimise -Created with sketchtool. - - - - - - - - - - - - + + + +minimise +Created with sketchtool. + + + + + + + + + + + + diff --git a/res/img/minimise.svg b/res/img/minimise.svg index 491756b15a..eecf181f61 100644 --- a/res/img/minimise.svg +++ b/res/img/minimise.svg @@ -5,7 +5,7 @@ Created with sketchtool. - + diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 8ab338790e..f571f6b0c2 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -1,6 +1,6 @@ // typical text (dark-on-white in light skin) -$primary-fg-color: #dddddd; +$primary-fg-color: #212121; $primary-bg-color: #2d2d2d; // used for focusing form controls @@ -72,9 +72,11 @@ $input-fg-color: $primary-fg-color; // context menus $menu-border-color: rgba(187, 187, 187, 0.5); $menu-bg-color: #373737; +$menu-selected-color: #f5f8fa; $avatar-initial-color: #2d2d2d; $avatar-bg-color: #ffffff; +$menu-selected-color: #f5f8fa; $h3-color: $primary-fg-color; @@ -105,6 +107,15 @@ $roomtile-name-color: rgba(186, 186, 186, 0.8); $roomtile-selected-bg-color: #333; $roomtile-focused-bg-color: rgba(255, 255, 255, 0.2); +$username-variant1-color: #1e7ddc; +$username-variant2-color: #a756a8; +$username-variant3-color: #7ac9a1; +$username-variant4-color: #f2809d; +$username-variant5-color: #ffc666; +$username-variant6-color: #76ddd7; +$username-variant7-color: #45529b; +$username-variant8-color: #bfd251; + $roomsublist-background: rgba(0, 0, 0, 0.2); $roomsublist-label-fg-color: $h3-color; $roomsublist-label-bg-color: $tertiary-accent-color; diff --git a/res/themes/dharma/css/_dharma.scss b/res/themes/dharma/css/_dharma.scss index f261285f39..aed8dfa60f 100644 --- a/res/themes/dharma/css/_dharma.scss +++ b/res/themes/dharma/css/_dharma.scss @@ -76,8 +76,9 @@ $input-underline-color: rgba(151, 151, 151, 0.5); $input-fg-color: rgba(74, 74, 74, 0.9); // context menus -$menu-border-color: rgba(187, 187, 187, 0.5); -$menu-bg-color: #f6f6f6; +$menu-border-color: #ebedf8; +$menu-bg-color: #fff; +$menu-selected-color: #f5f8fa; $avatar-initial-color: #ffffff; $avatar-bg-color: #ffffff; @@ -120,6 +121,15 @@ $roomtile-notified-color: #212121; $roomtile-selected-bg-color: #fff; $roomtile-focused-bg-color: #fff; +$username-variant1-color: #1e7ddc; +$username-variant2-color: #a756a8; +$username-variant3-color: #7ac9a1; +$username-variant4-color: #f2809d; +$username-variant5-color: #ffc666; +$username-variant6-color: #76ddd7; +$username-variant7-color: #45529b; +$username-variant8-color: #bfd251; + $roomtile-transparent-focused-color: rgba(0, 0, 0, 0.1); $roomsublist-background: $secondary-accent-color; diff --git a/res/themes/light/css/_base.scss b/res/themes/light/css/_base.scss index c17eba5398..9ece0363b3 100644 --- a/res/themes/light/css/_base.scss +++ b/res/themes/light/css/_base.scss @@ -77,6 +77,7 @@ $input-fg-color: rgba(74, 74, 74, 0.9); // context menus $menu-border-color: rgba(187, 187, 187, 0.5); $menu-bg-color: #f6f6f6; +$menu-selected-color: #f5f8fa; $avatar-initial-color: #ffffff; $avatar-bg-color: #ffffff; @@ -119,6 +120,15 @@ $roomtile-notified-color: $roomtile-name-color; $roomtile-selected-bg-color: rgba(255, 255, 255, 0.8); $roomtile-focused-bg-color: rgba(255, 255, 255, 0.9); +$username-variant1-color: #1e7ddc; +$username-variant2-color: #a756a8; +$username-variant3-color: #7ac9a1; +$username-variant4-color: #f2809d; +$username-variant5-color: #ffc666; +$username-variant6-color: #76ddd7; +$username-variant7-color: #45529b; +$username-variant8-color: #bfd251; + $roomtile-transparent-focused-color: rgba(0, 0, 0, 0.1); $roomsublist-background: rgba(0, 0, 0, 0.05); diff --git a/src/PhasedRollOut.js b/src/PhasedRollOut.js index a9029d07e6..b17ed37974 100644 --- a/src/PhasedRollOut.js +++ b/src/PhasedRollOut.js @@ -15,21 +15,7 @@ limitations under the License. */ import SdkConfig from './SdkConfig'; - -function hashCode(str) { - let hash = 0; - let i; - let chr; - if (str.length === 0) { - return hash; - } - for (i = 0; i < str.length; i++) { - chr = str.charCodeAt(i); - hash = ((hash << 5) - hash) + chr; - hash |= 0; - } - return Math.abs(hash); -} +import {hashCode} from './utils/FormattingUtils'; export function phasedRollOutExpiredForUser(username, feature, now, rollOutConfig = SdkConfig.get().phasedRollOut) { if (!rollOutConfig) { diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 7295fd45d3..2dfc1eeb34 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -49,7 +49,7 @@ export default class ContextualMenu extends React.Component { menuHeight: PropTypes.number, chevronOffset: PropTypes.number, menuColour: PropTypes.string, - chevronFace: PropTypes.string, // top, bottom, left, right + chevronFace: PropTypes.string, // top, bottom, left, right or none // Function to be called on menu close onFinished: PropTypes.func, menuPaddingTop: PropTypes.number, @@ -113,7 +113,6 @@ export default class ContextualMenu extends React.Component { render() { const position = {}; let chevronFace = null; - const props = this.props; if (props.top) { @@ -137,6 +136,8 @@ export default class ContextualMenu extends React.Component { if (props.chevronFace) { chevronFace = props.chevronFace; } + const hasChevron = chevronFace && chevronFace !== "none"; + if (chevronFace === 'top' || chevronFace === 'bottom') { chevronOffset.left = props.chevronOffset; } else { @@ -174,11 +175,12 @@ export default class ContextualMenu extends React.Component { `; } - const chevron =
; + const chevron = hasChevron ?
: undefined; const className = 'mx_ContextualMenu_wrapper'; const menuClasses = classNames({ 'mx_ContextualMenu': true, + 'mx_ContextualMenu_noChevron': chevronFace === 'none', 'mx_ContextualMenu_left': chevronFace === 'left', 'mx_ContextualMenu_right': chevronFace === 'right', 'mx_ContextualMenu_top': chevronFace === 'top', diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index ab491cc65e..2adb3dda34 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -178,11 +178,11 @@ var LeftPanel = React.createClass({ render: function() { const RoomList = sdk.getComponent('rooms.RoomList'); const TagPanel = sdk.getComponent('structures.TagPanel'); - const TopLeftMenu = sdk.getComponent('structures.TopLeftMenu'); + const TopLeftMenuButton = sdk.getComponent('structures.TopLeftMenuButton'); const BottomLeftMenu = sdk.getComponent('structures.BottomLeftMenu'); const CallPreview = sdk.getComponent('voip.CallPreview'); - let topBox = ; + let topBox = ; /* if (this.context.matrixClient.isGuest()) { const LoginBox = sdk.getComponent('structures.LoginBox'); diff --git a/src/components/structures/TopLeftMenu.js b/src/components/structures/TopLeftMenu.js deleted file mode 100644 index 5dfa8ed171..0000000000 --- a/src/components/structures/TopLeftMenu.js +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2018 New Vector 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 PropTypes from 'prop-types'; -import sdk from '../../index'; - -class TopLeftMenu extends React.Component { - - static propTypes = { - collapsed: PropTypes.bool.isRequired, - }; - - static displayName = 'TopLeftMenu'; - - render() { - const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); - const avatarHeight = 28; - const name = "My stuff"; - - return ( -
- -
- { name } -
- -
- ); - } -} - -module.exports = TopLeftMenu; diff --git a/src/components/structures/TopLeftMenuButton.js b/src/components/structures/TopLeftMenuButton.js new file mode 100644 index 0000000000..b2b375581d --- /dev/null +++ b/src/components/structures/TopLeftMenuButton.js @@ -0,0 +1,116 @@ +/* +Copyright 2018 New Vector 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 PropTypes from 'prop-types'; +import * as ContextualMenu from './ContextualMenu'; +import {TopLeftMenu} from './TopLeftMenu'; +import AccessibleButton from '../views/elements/AccessibleButton'; +import BaseAvatar from '../views/avatars/BaseAvatar'; +import MatrixClientPeg from '../../MatrixClientPeg'; +import Avatar from '../../Avatar'; + +const AVATAR_SIZE = 28; + +export default class TopLeftMenuButton extends React.Component { + + static propTypes = { + collapsed: PropTypes.bool.isRequired, + }; + + static displayName = 'TopLeftMenuButton'; + + constructor() { + super(); + this.state = { + menuDisplayed: false, + profileInfo: null, + }; + + this.onToggleMenu = this.onToggleMenu.bind(this); + } + + async _getProfileInfo() { + const cli = MatrixClientPeg.get(); + const userId = cli.getUserId(); + const profileInfo = await cli.getProfileInfo(userId); + const avatarUrl = Avatar.avatarUrlForUser( + {avatarUrl: profileInfo.avatar_url}, + AVATAR_SIZE, AVATAR_SIZE, "crop"); + + return { + userId, + name: profileInfo.displayname, + avatarUrl, + }; + } + + async componentDidMount() { + try { + const profileInfo = await this._getProfileInfo(); + this.setState({profileInfo}); + } catch(ex) { + console.log("could not fetch profile"); + console.error(ex); + } + } + + render() { + const fallbackUserId = MatrixClientPeg.get().getUserId(); + const profileInfo = this.state.profileInfo; + const name = profileInfo ? profileInfo.name : fallbackUserId; + let nameElement; + if (!this.props.collapsed) { + nameElement =
+ { name } +
; + } + + return ( + + + { nameElement } + + + ); + } + + onToggleMenu(e) { + e.preventDefault(); + e.stopPropagation(); + + const elementRect = e.currentTarget.getBoundingClientRect(); + const x = elementRect.left; + const y = elementRect.top + elementRect.height; + + ContextualMenu.createMenu(TopLeftMenu, { + chevronFace: "none", + left: x, + top: y, + onFinished: () => { + this.setState({ menuDisplayed: false }); + }, + }); + this.setState({ menuDisplayed: true }); + } +} diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index be718050c1..c990b5705d 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -333,7 +333,7 @@ module.exports = React.createClass({ } return ( -
+
{ resendButton } { redactButton } { cancelButton } diff --git a/src/components/views/context_menus/RoomTileContextMenu.js b/src/components/views/context_menus/RoomTileContextMenu.js index ce9895447e..8e56c055f9 100644 --- a/src/components/views/context_menus/RoomTileContextMenu.js +++ b/src/components/views/context_menus/RoomTileContextMenu.js @@ -243,7 +243,7 @@ module.exports = React.createClass({ }); return ( -
+
diff --git a/src/components/views/context_menus/TopLeftMenu.js b/src/components/views/context_menus/TopLeftMenu.js new file mode 100644 index 0000000000..ec3120cfea --- /dev/null +++ b/src/components/views/context_menus/TopLeftMenu.js @@ -0,0 +1,53 @@ +/* +Copyright 2018 New Vector 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 dis from '../../../dispatcher'; +import { _t } from '../../../languageHandler'; + +export class TopLeftMenu extends React.Component { + + constructor() { + super(); + this.openSettings = this.openSettings.bind(this); + this.signOut = this.signOut.bind(this); + } + + render() { + return
+
    +
  • {_t("Settings")}
  • +
+
    +
  • {_t("Sign out")}
  • +
+
; + } + + openSettings() { + dis.dispatch({action: 'view_user_settings'}); + this.closeMenu(); + } + + signOut() { + dis.dispatch({action: 'logout'}); + this.closeMenu(); + } + + closeMenu() { + if (this.props.onFinished) this.props.onFinished(); + } +} diff --git a/src/components/views/messages/DateSeparator.js b/src/components/views/messages/DateSeparator.js index a0ea704502..c72ed2517a 100644 --- a/src/components/views/messages/DateSeparator.js +++ b/src/components/views/messages/DateSeparator.js @@ -56,6 +56,6 @@ export default class DateSeparator extends React.Component { } render() { - return

{ this.getLabel() }

; + return


{ this.getLabel() }

; } } diff --git a/src/components/views/messages/SenderProfile.js b/src/components/views/messages/SenderProfile.js index 0f767675e2..a40addf0d1 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.js @@ -23,6 +23,7 @@ import sdk from '../../../index'; import Flair from '../elements/Flair.js'; import FlairStore from '../../../stores/FlairStore'; import { _t } from '../../../languageHandler'; +import {hashCode} from '../../../utils/FormattingUtils'; export default React.createClass({ displayName: 'SenderProfile', @@ -96,6 +97,7 @@ export default React.createClass({ render() { const EmojiText = sdk.getComponent('elements.EmojiText'); const {mxEvent} = this.props; + const colorNumber = hashCode(mxEvent.getSender()) % 8; const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); const {msgtype} = mxEvent.getContent(); @@ -119,7 +121,7 @@ export default React.createClass({ // Name + flair const nameFlair = - + { nameElem } { flair } diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 66f3fdaa97..e96dd27acc 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -297,16 +297,16 @@ export default class MessageComposer extends React.Component { if (this.props.callState && this.props.callState !== 'ended') { hangupButton = - {_t('Hangup')} + {_t('Hangup')} ; } else { callButton = - + ; videoCallButton = - + ; } @@ -320,7 +320,7 @@ export default class MessageComposer extends React.Component { const uploadButton = ( - + { topic }
; - } + topicElement = +
{ topic }
; } let roomAvatar = null; @@ -413,7 +411,7 @@ module.exports = React.createClass({ if (!this.props.editing) { rightRow = -
+
{ settingsButton } { pinnedEventsButton } { shareRoomButton } @@ -427,15 +425,9 @@ module.exports = React.createClass({ return (
-
-
- { roomAvatar } -
-
- { name } - { topicElement } -
-
+
{ roomAvatar }
+ { name } + { topicElement } { spinner } { saveButton } { cancelButton } diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 40b1768282..085303eafb 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -351,7 +351,7 @@ export default class Stickerpicker extends React.Component { onClick={this._onHideStickersClick} ref='target' title={_t("Hide Stickers")}> - + ; } else { // Show show-stickers button @@ -362,7 +362,7 @@ export default class Stickerpicker extends React.Component { className="mx_MessageComposer_stickers" onClick={this._onShowStickersClick} title={_t("Show Stickers")}> - + ; } return
diff --git a/src/utils/FormattingUtils.js b/src/utils/FormattingUtils.js index a27851951f..435b33ac5d 100644 --- a/src/utils/FormattingUtils.js +++ b/src/utils/FormattingUtils.js @@ -37,3 +37,24 @@ export function formatCount(count) { export function formatCryptoKey(key) { return key.match(/.{1,4}/g).join(" "); } +/** + * calculates a numeric hash for a given string + * + * @param {string} str string to hash + * + * @return {number} + */ +export function hashCode(str) { + let hash = 0; + let i; + let chr; + if (str.length === 0) { + return hash; + } + for (i = 0; i < str.length; i++) { + chr = str.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; + } + return Math.abs(hash); +}