diff --git a/res/css/_common.scss b/res/css/_common.scss index 97ae5412e1..bec4c02c18 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -30,8 +30,6 @@ body { color: $primary-fg-color; border: 0px; margin: 0px; - /* This should render the fonts the same accross browsers */ - -webkit-font-smoothing: subpixel-antialiased; } .error, .warning { @@ -49,20 +47,14 @@ h2 { a:hover, a:link, a:visited { - color: $accent-color; + color: $accent-color-alt; } input[type=text], input[type=password], textarea { background-color: transparent; - color: $primary-fg-color; -} - -input[type=text].error, input[type=password].error { - border: 1px solid $warning-color; } input[type=text]:focus, input[type=password]:focus, textarea:focus { - border: 1px solid $accent-color; outline: none; box-shadow: none; } @@ -83,11 +75,6 @@ textarea { transition: opacity 0.2s ease-in-out; } -.mx_fadable.mx_fadable_faded { - opacity: 0.3; - pointer-events: none; -} - /* XXX: critical hack to GeminiScrollbar to allow them to work in FF 42 and Chrome 48. Stop the scrollbar view from pushing out the container's overall sizing, which causes flexbox to adapt to the new size and cause the view to keep growing. @@ -314,7 +301,7 @@ textarea { } .mx_textButton { - @mixin mx_DialogButton_small; + @mixin mx_DialogButton_small; } .mx_textButton:hover { diff --git a/res/css/_components.scss b/res/css/_components.scss index 5633b7ec8f..d8f966603d 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -1,6 +1,6 @@ // autogenerated by rethemendex.sh @import "./_common.scss"; -@import "./_fonts.scss"; +@import "./structures/_AutoHideScrollbar.scss"; @import "./structures/_CompatibilityPage.scss"; @import "./structures/_ContextualMenu.scss"; @import "./structures/_CreateRoom.scss"; @@ -19,6 +19,7 @@ @import "./structures/_RoomView.scss"; @import "./structures/_SearchBox.scss"; @import "./structures/_TagPanel.scss"; +@import "./structures/_TopLeftMenuButton.scss"; @import "./structures/_UploadBar.scss"; @import "./structures/_UserSettings.scss"; @import "./structures/_ViewSource.scss"; @@ -29,6 +30,7 @@ @import "./views/context_menus/_RoomTileContextMenu.scss"; @import "./views/context_menus/_StatusMessageContextMenu.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"; @@ -62,6 +64,7 @@ @import "./views/elements/_MemberEventListSummary.scss"; @import "./views/elements/_ProgressBar.scss"; @import "./views/elements/_ReplyThread.scss"; +@import "./views/elements/_ResizeHandle.scss"; @import "./views/elements/_RichText.scss"; @import "./views/elements/_RoleButton.scss"; @import "./views/elements/_Spinner.scss"; @@ -112,6 +115,7 @@ @import "./views/rooms/_SearchableEntityList.scss"; @import "./views/rooms/_Stickers.scss"; @import "./views/rooms/_TopUnreadMessagesBar.scss"; +@import "./views/rooms/_WhoIsTypingTile.scss"; @import "./views/settings/_DevicesPanel.scss"; @import "./views/settings/_IntegrationsManager.scss"; @import "./views/settings/_KeyBackupPanel.scss"; diff --git a/res/css/structures/_AutoHideScrollbar.scss b/res/css/structures/_AutoHideScrollbar.scss new file mode 100644 index 0000000000..60aea7ce8f --- /dev/null +++ b/res/css/structures/_AutoHideScrollbar.scss @@ -0,0 +1,66 @@ +/* +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. +*/ + +/* +1. for browsers that support native overlay auto-hiding scrollbars +*/ +.mx_AutoHideScrollbar { + overflow-x: hidden; + overflow-y: auto; + -ms-overflow-style: -ms-autohiding-scrollbar; +} +/* +2. webkit also supports overflow:overlay where the scrollbars don't take any space +in the layout but they don't autohide, so do that only on hover +*/ +body.mx_scrollbar_overlay_noautohide .mx_AutoHideScrollbar { + overflow-y: hidden; +} + +body.mx_scrollbar_overlay_noautohide .mx_AutoHideScrollbar:hover { + overflow-y: overlay; +} +/* +3. as a last fallback, compensate for the scrollbar taking up space in the layout +by having giving the child element (.mx_AutoHideScrollbar_offset) a +negative right margin of the width of the scrollbar when the container +is overflowing. This is what Firefox ends up using. Overflow is detected +in javascript, and adds the mx_AutoHideScrollbar_overflow class to the container. +This only works in Firefox, which should be fine as this fallback is only needed there. +*/ +body.mx_scrollbar_nooverlay { + .mx_AutoHideScrollbar { + overflow-y: hidden; + } + + .mx_AutoHideScrollbar:hover { + overflow-y: auto; + } + + /* + offset scrollbar width with negative margin-right + + include before and after psuedo-elements here so they can + be used to do something interesting like scroll-indicating + gradients (see IndicatorScrollBar) + */ + .mx_AutoHideScrollbar:hover.mx_AutoHideScrollbar_overflow > .mx_AutoHideScrollbar_offset, + .mx_AutoHideScrollbar:hover.mx_AutoHideScrollbar_overflow::before, + .mx_AutoHideScrollbar:hover.mx_AutoHideScrollbar_overflow::after + { + margin-right: calc(-1 * var(--scrollbar-width)); + } +} 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/_FilePanel.scss b/res/css/structures/_FilePanel.scss index 87dc0aa756..677fa34c6f 100644 --- a/res/css/structures/_FilePanel.scss +++ b/res/css/structures/_FilePanel.scss @@ -16,11 +16,7 @@ limitations under the License. .mx_FilePanel { order: 2; - flex: 1 1 0; - - width: 100%; - overflow-y: auto; } diff --git a/res/css/structures/_GroupView.scss b/res/css/structures/_GroupView.scss index 02e5a948e9..398c51ba91 100644 --- a/res/css/structures/_GroupView.scss +++ b/res/css/structures/_GroupView.scss @@ -15,10 +15,6 @@ limitations under the License. */ .mx_GroupView { - max-width: 960px; - width: 100%; - margin-left: auto; - margin-right: auto; display: flex; flex-direction: column; overflow: hidden; @@ -29,7 +25,6 @@ limitations under the License. } .mx_GroupView_header { - max-width: 960px; min-height: 70px; align-items: center; display: flex; @@ -39,6 +34,8 @@ limitations under the License. .mx_GroupView_header_view { border-bottom: 1px solid $primary-hairline-color; padding-bottom: 0px; + padding-left: 8px; + padding-right: 8px; } .mx_GroupView_header_avatar, .mx_GroupView_header_info { @@ -162,6 +159,11 @@ limitations under the License. line-height: 2em; } +.mx_GroupView > .mx_MainSplit { + flex: 1; + display: flex; +} + .mx_GroupView_body { flex-grow: 1; } diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index 7cf6dd1119..47cb231b58 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -15,32 +15,22 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_LeftPanel { - position: relative; - - display: flex; - flex-direction: column; -} - .mx_LeftPanel_container { display: flex; - /* LeftPanel 235px */ - flex: 0 0 235px; + /* LeftPanel 260px */ + min-width: 260px; + flex: 0 0 auto; } -.mx_LeftPanel_container.mx_LeftPanel_container_hasTagPanel { - /* TagPanel 60px + LeftPanel 235px */ - flex: 0 0 295px; +.mx_LeftPanel_container.collapsed { + min-width: unset; + /* Collapsed LeftPanel 70px */ + flex: 0 0 70px; } -.mx_LeftPanel_container_collapsed { - /* Collapsed LeftPanel 60px */ - flex: 0 0 60px; -} - -.mx_LeftPanel_container_collapsed.mx_LeftPanel_container_hasTagPanel { - /* TagPanel 60px + Collapsed LeftPanel 60px */ - flex: 0 0 120px; +.mx_LeftPanel_container.collapsed.mx_LeftPanel_container_hasTagPanel { + /* TagPanel 70px + Collapsed LeftPanel 70px */ + flex: 0 0 140px; } .mx_LeftPanel_hideButton { @@ -55,6 +45,14 @@ limitations under the License. } +.mx_LeftPanel { + flex: 1; + overflow-x: hidden; + display: flex; + flex-direction: column; + min-height: 0; +} + .mx_LeftPanel .mx_AppTile_mini { height: 132px; } @@ -68,7 +66,7 @@ limitations under the License. z-index: 6; } -.mx_LeftPanel.collapsed .mx_BottomLeftMenu { +.mx_LeftPanel_container.collapsed .mx_BottomLeftMenu { flex: 0 0 160px; margin-bottom: 9px; } @@ -91,12 +89,6 @@ limitations under the License. pointer-events: none; } -.collapsed .mx_RoleButton { - margin-right: 0px ! important; - padding-top: 3px ! important; - padding-bottom: 3px ! important; -} - .mx_BottomLeftMenu_options > div { display: inline-block; } @@ -115,7 +107,7 @@ limitations under the License. margin-right: 0px; } -.mx_LeftPanel.collapsed .mx_BottomLeftMenu_settings { +.mx_LeftPanel_container.collapsed .mx_BottomLeftMenu_settings { float: none; } @@ -124,7 +116,7 @@ limitations under the License. flex: 0 0 50px; } - .mx_LeftPanel.collapsed .mx_BottomLeftMenu { + .mx_LeftPanel_container.collapsed .mx_BottomLeftMenu { flex: 0 0 160px; } diff --git a/res/css/structures/_MatrixChat.scss b/res/css/structures/_MatrixChat.scss index eae1f56180..1ccbd19391 100644 --- a/res/css/structures/_MatrixChat.scss +++ b/res/css/structures/_MatrixChat.scss @@ -54,6 +54,7 @@ limitations under the License. order: 2; flex: 1; + min-height: 0; } .mx_MatrixChat_syncError { @@ -68,23 +69,8 @@ limitations under the License. transform: translateX(-50%); } -.mx_MatrixChat .mx_LeftPanel { - order: 1; - - background-color: $secondary-accent-color; - - flex: 0 0 235px; -} - -.mx_MatrixChat .mx_LeftPanel.collapsed { - flex: 0 0 60px; -} - -.mx_MatrixChat .mx_MatrixChat_middlePanel { - order: 2; - - padding-left: 20px; - padding-right: 22px; +/* not the left panel, and not the resize handle, so the roomview/groupview/... */ +.mx_MatrixChat > :not(.mx_LeftPanel_container):not(.mx_ResizeHandle) { background-color: $primary-bg-color; flex: 1; @@ -96,21 +82,9 @@ limitations under the License. */ overflow-x: auto; - display: flex; - /* To fix https://github.com/vector-im/riot-web/issues/3298 where Safari needed height 100% all the way down to the HomePage. Height does not have to be auto, empirically. */ height: 100%; } - -.mx_MatrixChat .mx_RightPanel { - order: 3; - - flex: 0 0 235px; -} - -.mx_MatrixChat .mx_RightPanel.collapsed { - flex: 0 0 122px; -} diff --git a/res/css/structures/_MyGroups.scss b/res/css/structures/_MyGroups.scss index 6d140721c8..f9433909a5 100644 --- a/res/css/structures/_MyGroups.scss +++ b/res/css/structures/_MyGroups.scss @@ -15,10 +15,6 @@ limitations under the License. */ .mx_MyGroups { - max-width: 960px; - margin-left: auto; - margin-right: auto; - display: flex; flex-direction: column; } @@ -34,6 +30,11 @@ limitations under the License. flex-wrap: wrap; } +.mx_MyGroups > :not(.mx_RoomHeader) { + max-width: 960px; + margin: 40px; +} + .mx_MyGroups_headerCard { flex: 1 0 50%; margin-bottom: 30px; @@ -43,14 +44,31 @@ limitations under the License. } .mx_MyGroups_headerCard .mx_MyGroups_headerCard_button { + flex: 0 0 auto; margin-right: 13px; - height: 50px; + height: 40px; + width: 40px; + border-radius: 20px; + background-color: $roomheader-addroom-color; + position: relative; + + &:before { + background-color: $accent-fg-color; + mask: url('../../img/icons-create-room.svg'); + mask-repeat: no-repeat; + mask-position: center; + mask-size: 80%; + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + } } -.mx_MyGroups_headerCard_button object { - /* Otherwise the SVG object absorbs clicks and the button doesn't work */ - pointer-events: none; -} + + .mx_MyGroups_headerCard_header { font-weight: bold; diff --git a/res/css/structures/_NotificationPanel.scss b/res/css/structures/_NotificationPanel.scss index a899808d57..b171aa3e36 100644 --- a/res/css/structures/_NotificationPanel.scss +++ b/res/css/structures/_NotificationPanel.scss @@ -16,11 +16,7 @@ limitations under the License. .mx_NotificationPanel { order: 2; - flex: 1 1 0; - - width: 100%; - overflow-y: auto; } @@ -97,4 +93,4 @@ limitations under the License. .mx_NotificationPanel .mx_EventTile_content { margin-right: 0px; -} \ No newline at end of file +} diff --git a/res/css/structures/_RightPanel.scss b/res/css/structures/_RightPanel.scss index b4dff612ed..592eea067e 100644 --- a/res/css/structures/_RightPanel.scss +++ b/res/css/structures/_RightPanel.scss @@ -15,8 +15,10 @@ limitations under the License. */ .mx_RightPanel { + overflow-x: hidden; + flex: 0 0 auto; position: relative; - + min-width: 250px; display: flex; flex-direction: column; } @@ -25,55 +27,57 @@ limitations under the License. order: 1; border-bottom: 1px solid $primary-hairline-color; - margin-right: 20px; - flex: 0 0 70px; + flex: 0 0 52px; } /** Fixme - factor this out with the main header **/ .mx_RightPanel_headerButtonGroup { - margin-top: 6px; + height: 100%; display: flex; - width: 100%; background-color: $primary-bg-color; - margin-left: 0px; + padding: 0 9px; + align-items: center; } .mx_RightPanel_headerButton { cursor: pointer; flex: 0 0 auto; vertical-align: top; - padding-left: 4px; + margin-top: 4px; + padding-left: 5px; padding-right: 5px; text-align: center; position: relative; + border-bottom: 2px solid transparent; } .mx_RightPanel_headerButton object { pointer-events: none; - padding-bottom: 3px; } .mx_RightPanel_headerButton_highlight { - width: 25px; - height: 5px; - border-radius: 5px; - background-color: $accent-color; - opacity: 0.2; + border-color: $button-bg-color; } .mx_RightPanel_headerButton_badge { - font-size: 11px; - color: $accent-color; + font-size: 8px; + border-radius: 8px; + color: $accent-fg-color; + background-color: $accent-color; font-weight: bold; - padding-bottom: 2px; + position: absolute; + top: -4px; + left: 20px; + padding: 2px 4px; } .mx_RightPanel_collapsebutton { flex: 1; text-align: right; - margin-top: 20px; + height: 16px; + border: none; } .mx_RightPanel .mx_MemberList, @@ -88,46 +92,3 @@ limitations under the License. order: 2; margin: auto; } - -.mx_RightPanel_footer { - order: 3; - - border-top: 1px solid $primary-hairline-color; - margin-right: 20px; - - flex: 0 0 60px; -} - -.mx_RightPanel_footer .mx_RightPanel_invite { - font-size: 14px; - color: $primary-fg-color; - padding-top: 13px; - padding-left: 5px; - cursor: pointer; - display: flex; - align-items: center; -} - -.collapsed .mx_RightPanel_footer .mx_RightPanel_invite { - display: none; -} - -.mx_RightPanel_invite .mx_RightPanel_icon object { - pointer-events: none; -} - -.mx_RightPanel_invite .mx_RightPanel_message { - padding-left: 10px; - line-height: 18px; -} - -.mx_MatrixChat_useCompactLayout { - .mx_RightPanel_footer { - flex: 0 0 50px; - } - - .mx_RightPanel_footer .mx_RightPanel_invite { - line-height: 25px; - padding-top: 8px; - } -} diff --git a/res/css/structures/_RoomSubList.scss b/res/css/structures/_RoomSubList.scss index 6798f75a14..2d471ee198 100644 --- a/res/css/structures/_RoomSubList.scss +++ b/res/css/structures/_RoomSubList.scss @@ -14,235 +14,188 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_RoomSubList { - display: table; - table-layout: fixed; - width: 100%; +/* a word of explanation about the flex-shrink values employed here: + there are 3 priotized categories of screen real-estate grabbing, + each with a flex-shrink difference of 4 order of magnitude, + so they ideally wouldn't affect each other. + lowest category: .mx_RoomSubList + flex-shrink: 10000000 + distribute size of items within the same categery by their size + middle category: .mx_RoomSubList.resized-sized + flex-shrink: 1000 + applied when using the resizer, will have a max-height set to it, + to limit the size + highest category: .mx_RoomSubList.resized-all + flex-shrink: 1 + small flex-shrink value (1), is only added if you can drag the resizer so far + so in practice you can only assign this category if there is enough space. +*/ - background-color: $roomsublist-background; +.mx_RoomSubList { + min-height: 31px; + flex: 0 100000000 auto; + display: flex; + flex-direction: column; +} + +.mx_RoomSubList_nonEmpty { + min-height: 70px; + + .mx_AutoHideScrollbar_offset { + padding-bottom: 4px; + } +} + +.mx_RoomSubList_hidden { + flex: none !important; +} + +.mx_RoomSubList.resized-all { + flex: 0 1 auto; +} + +.mx_RoomSubList.resized-sized { + /* resizer set max-height on resized-sized, + so that limits the height and hence + needs a very small flex-shrink */ + flex: 0 10000 auto; } .mx_RoomSubList_labelContainer { - height: 31px; /* mx_RoomSubList_label height including border */ - width: 235px; /* LHS Panel width */ - position: relative; + display: flex; + flex-direction: row; + align-items: center; + flex: 0 0 auto; + margin: 0 16px; + height: 36px; } .mx_RoomSubList_label { - position: relative; + flex: 1; + cursor: pointer; + display: flex; + align-items: center; + padding: 0 6px; +} + +.mx_RoomSubList_label > span { + flex: 1 1 auto; text-transform: uppercase; color: $roomsublist-label-fg-color; - font-weight: 600; + font-weight: 700; font-size: 12px; - width: 203px; /* padding + width = LHS Panel width */ - height: 19px; /* height + padding = 31px = mx_RoomSubList_label height */ - padding-left: 16px; /* gutter */ - padding-right: 16px; /* gutter */ - padding-top: 6px; - padding-bottom: 6px; - cursor: pointer; - background-color: $secondary-accent-color; -} - -.mx_RoomSubList_label.mx_RoomSubList_fixed { - position: fixed; - top: 0; - z-index: 5; - /* pointer-events: none; */ -} - -.collapsed .mx_RoomSubList_label { - height: 17px; - width: 28px; /* collapsed LHS Panel width */ -} - -.collapsed .mx_RoomSubList_labelContainer { - width: 28px; /* collapsed LHS Panel width */ -} - -.mx_RoomSubList_roomCount { - display: inline-block; - font-size: 12px; - font-weight: normal; - color: $accent-color; - padding-left: 5px; - text-transform: none; -} - -.collapsed .mx_RoomSubList_roomCount { - display: none; + margin-left: 8px; } .mx_RoomSubList_badge { - display: inline-block; - min-width: 15px; - height: 15px; - position: absolute; - right: 8px; /*gutter */ - top: 7px; + flex: 0 0 auto; border-radius: 8px; color: $accent-fg-color; font-weight: 600; - font-size: 10px; - text-align: center; - padding-top: 1px; - padding-left: 4px; - padding-right: 4px; - background-color: $accent-color; + font-size: 12px; + padding: 0 5px; + background-color: $roomtile-name-color; } -.mx_RoomSubList_label .mx_RoomSubList_badge:hover { - filter: brightness($focus-brightness); +.mx_RoomSubList_addRoom, .mx_RoomSubList_badge { + margin-left: 7px; } -/* -.collapsed .mx_RoomSubList_badge { - display: none; +.mx_RoomSubList_addRoom { + background-color: $roomheader-addroom-color; + color: $roomsublist-background; + background-image: url('../../img/icons-room-add.svg'); + background-repeat: no-repeat; + background-position: center; + border-radius: 10px; // 16/2 + 2 padding + height: 16px; + flex: 0 0 16px; + background-clip: content-box; } -*/ .mx_RoomSubList_badgeHighlight { background-color: $warning-color; } -/* This is the bottom of the speech bubble */ -.mx_RoomSubList_badgeHighlight:after { - content: ""; - position: absolute; - display: block; - width: 0; - height: 0; - margin-left: 5px; - border-top: 5px solid $warning-color; - border-right: 7px solid transparent; -} - -/* Hide the bottom of speech bubble */ -.collapsed .mx_RoomSubList_badgeHighlight:after { - display: none; -} - .mx_RoomSubList_chevron { pointer-events: none; - position: absolute; - right: 41px; - top: 11px; + background-image: url('../../img/topleft-chevron.svg'); + background-repeat: no-repeat; + transition: transform 0.2s ease-in; + width: 10px; + height: 10px; + background-position: center; + margin-left: 2px; } .mx_RoomSubList_chevronDown { - width: 0; - height: 0; - border-left: 5px solid transparent; - border-right: 5px solid transparent; - border-top: 6px solid $roomsublist-chevron-color; + transform: rotateZ(0deg); } .mx_RoomSubList_chevronUp { - width: 0; - height: 0; - border-left: 5px solid transparent; - border-right: 5px solid transparent; - border-bottom: 6px solid $roomsublist-chevron-color; + transform: rotateZ(180deg); } .mx_RoomSubList_chevronRight { - width: 0; - height: 0; - border-top: 5px solid transparent; - border-left: 6px solid $roomsublist-chevron-color; - border-bottom: 5px solid transparent; + transform: rotateZ(-90deg); } -/* The overflow section */ -.mx_RoomSubList_ellipsis { - display: block; - line-height: 11px; - height: 18px; - position: relative; - cursor: pointer; - font-size: 13px; - - background-color: $secondary-accent-color; +.mx_RoomSubList_scroll { + /* let rooms list grab as much space as it needs (auto), + potentially overflowing and showing a scrollbar */ + flex: 0 1 auto; + padding: 0 8px; } -.collapsed .mx_RoomSubList_ellipsis { - height: 20px; +// overflow indicators +.mx_RoomSubList:not(.resized-all) > .mx_RoomSubList_scroll { + &.mx_IndicatorScrollbar_topOverflow::before, + &.mx_IndicatorScrollbar_bottomOverflow::after { + position: sticky; + left: 0; + right: 0; + height: 30px; + content: ""; + display: block; + z-index: 100; + pointer-events: none; + } + + &.mx_IndicatorScrollbar_topOverflow > .mx_AutoHideScrollbar_offset { + margin-top: -30px; + } + &.mx_IndicatorScrollbar_bottomOverflow > .mx_AutoHideScrollbar_offset { + margin-bottom: -30px; + } + + &.mx_IndicatorScrollbar_topOverflow::before { + top: 0; + background: linear-gradient(to top, rgba(242,245,248,0), rgba(242,245,248,1)); + } + + &.mx_IndicatorScrollbar_bottomOverflow::after { + bottom: 0; + background: linear-gradient(to bottom, rgba(242,245,248,0), rgba(242,245,248,1)); + } } -.mx_RoomSubList_line { - display: inline-block; - width: 159px; - border-top: dotted 2px $accent-color; - vertical-align: middle; +.collapsed { + + .mx_RoomSubList_scroll { + padding: 0; + } + + .mx_RoomSubList_labelContainer { + margin-right: 14px; + margin-left: 2px; + } + + .mx_RoomSubList_addRoom { + margin-left: 3px; + margin-right: 10px; + } + + .mx_RoomSubList_label > span { + display: none; + } } - -.collapsed .mx_RoomSubList_line { - display: none; -} - -.mx_RoomSubList_more { - display: inline-block; - text-transform: uppercase; - font-size: 10px; - font-weight: 600; - text-align: left; - color: $accent-color; - padding-left: 7px; - padding-right: 7px; - padding-left: 7px; - vertical-align: middle; -} - -.collapsed .mx_RoomSubList_more { - display: none; -} - -.mx_RoomSubList_moreBadge { - display: inline-block; - min-width: 15px; - height: 13px; - position: absolute; - right: 8px; /*gutter */ - top: -2px; - border-radius: 8px; - border: solid 1px $accent-color; - color: $accent-fg-color; - font-weight: 600; - font-size: 10px; - text-align: center; - padding-top: 1px; - padding-left: 3px; - padding-right: 3px; - background-color: $primary-bg-color; - vertical-align: middle; -} - -.mx_RoomSubList_moreBadge.mx_RoomSubList_moreBadgeNotify { - background-color: $accent-color; - border: 0; - padding-top: 3px; - padding-left: 4px; - padding-right: 4px; -} - -.mx_RoomSubList_moreBadge.mx_RoomSubList_moreBadgeHighlight { - background-color: $warning-color; - border: 0; - padding-top: 3px; - padding-left: 4px; - padding-right: 4px; -} - -.collapsed .mx_RoomSubList_moreBadge { - position: static; - margin-left: 16px; - margin-top: 2px; -} - -.mx_RoomSubList_ellipsis .mx_RoomSubList_chevronDown { - position: relative; - top: 4px; - left: 2px; -} - - diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index 02418f70db..72dca953f9 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -16,23 +16,12 @@ limitations under the License. .mx_RoomView { word-wrap: break-word; - position: relative; - display: flex; - width: 100%; - flex-direction: column; } -.mx_RoomView .mx_RoomHeader { - order: 1; - - flex: 0 0 70px; -} - .mx_RoomView_fileDropTarget { min-width: 0px; - max-width: 960px; width: 100%; font-size: 18px; text-align: center; @@ -50,7 +39,7 @@ limitations under the License. border: 2px #e1dddd solid; border-bottom: none; position: absolute; - top: 70px; + top: 52px; bottom: 0px; z-index: 3000; } @@ -63,33 +52,47 @@ limitations under the License. } .mx_RoomView_auxPanel { - order: 2; - min-width: 0px; - max-width: 960px; width: 100%; margin: 0px auto; overflow: auto; - border-bottom: 1px solid $primary-hairline-color; - flex: 0 0 auto; } +.mx_RoomView_auxPanel_fullHeight { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 3000; + background-color: $primary-bg-color; +} + .mx_RoomView_auxPanel_apps { max-width: 1920px ! important; } -.mx_RoomView_body { - order: 3; +.mx_RoomView .mx_MainSplit { flex: 1 1 0; - flex-direction: column; display: flex; } -.mx_RoomView_body .mx_RoomView_topUnreadMessagesBar { - order: 1; +.mx_RoomView_body { + position: relative; //for .mx_RoomView_auxPanel_fullHeight + display: flex; + flex-direction: column; + flex: 1; +} + +.mx_RoomView_body .mx_RoomView_timeline { + /* offset parent for mx_RoomView_topUnreadMessagesBar */ + position: relative; + flex: 1; + display: flex; + flex-direction: column; } .mx_RoomView_body .mx_RoomView_messagePanel { @@ -98,7 +101,6 @@ limitations under the License. .mx_RoomView_body .mx_RoomView_messagePanelSpinner { order: 2; - margin: auto; } .mx_RoomView_body .mx_RoomView_statusArea { @@ -115,9 +117,6 @@ limitations under the License. } .mx_RoomView_messageListWrapper { - max-width: 960px; - margin: auto; - min-height: 100%; display: flex; @@ -142,9 +141,8 @@ limitations under the License. } .mx_RoomView_MessageList { - width: 100%; list-style-type: none; - padding: 0px; + padding: 18px; } .mx_RoomView_MessageList li { @@ -184,7 +182,6 @@ hr.mx_RoomView_myReadMarker { } .mx_RoomView_statusAreaBox { - max-width: 960px; margin: auto; min-height: 50px; } diff --git a/res/css/structures/_SearchBox.scss b/res/css/structures/_SearchBox.scss index 6f08fd47b2..e559236569 100644 --- a/res/css/structures/_SearchBox.scss +++ b/res/css/structures/_SearchBox.scss @@ -14,55 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_SearchBox { - height: 24px; - margin-left: 16px; - margin-right: 16px; - padding-top: 24px; - padding-bottom: 22px; - - border-bottom: 1px solid $panel-divider-color; - - display: flex; -} - -.mx_SearchBox_searchButton { - margin-right: 10px; - margin-top: 5px; - pointer-events: none; -} - .mx_SearchBox_closeButton { cursor: pointer; - margin-top: -5px; -} - -.mx_SearchBox_search { - flex: 1 1 auto; - width: 0px; - font-family: $font-family; - font-size: 12px; - margin-top: -2px; - height: 24px; - border: 0px ! important; - /* border-bottom: 1px solid rgba(0, 0, 0, 0.1) ! important; */ - border: 0px; -} - -.mx_SearchBox_minimise, -.mx_SearchBox_maximise { - margin-top: 3px; - cursor: pointer; -} - -.mx_SearchBox_minimise { - margin-left: 10px; -} - -.mx_SearchBox_maximise { - margin-left: 9px; -} - -.mx_SearchBox object { - pointer-events: none; + background-image: url('../../img/icons-close.svg'); + background-repeat: no-repeat; + width: 16px; + height: 16px; + background-position: center; + padding: 9px; } diff --git a/res/css/structures/_TagPanel.scss b/res/css/structures/_TagPanel.scss index 415aafd924..77eefc7e10 100644 --- a/res/css/structures/_TagPanel.scss +++ b/res/css/structures/_TagPanel.scss @@ -15,8 +15,9 @@ limitations under the License. */ .mx_TagPanel { - flex: 0 0 60px; - background-color: $tertiary-accent-color; + flex: 0 0 70px; + background-color: $tagpanel-bg-color; + cursor: pointer; display: flex; flex-direction: column; @@ -38,6 +39,8 @@ limitations under the License. display: flex; justify-content: center; align-items: flex-start; + + display: none; } .mx_TagPanel .mx_TagPanel_clearButton object { @@ -50,6 +53,7 @@ limitations under the License. height: 0px; width: 42px; border-bottom: 1px solid $panel-divider-color; + display: none; } .mx_TagPanel .mx_TagPanel_scroller { @@ -60,19 +64,21 @@ limitations under the License. display: flex; flex-direction: column; align-items: center; + margin-top: 5px; height: 100%; } .mx_TagPanel .mx_TagTile { - padding: 6px 3px; - opacity: 0.5; + padding-top: 9px; + padding-bottom: 9px; +// opacity: 0.5; position: relative; } .mx_TagPanel .mx_TagTile:focus, .mx_TagPanel .mx_TagTile:hover, .mx_TagPanel .mx_TagTile.mx_TagTile_selected { - opacity: 1; +// opacity: 1; } .mx_TagPanel .mx_TagTile.mx_TagTile_selected { @@ -83,12 +89,12 @@ limitations under the License. .mx_TagPanel .mx_TagTile.mx_TagTile_selected .mx_TagTile_avatar .mx_BaseAvatar { border: 3px solid $accent-color; background-color: $accent-color; - border-radius: 60px; + border-radius: 40px; /* In case this is a "initial" avatar */ display: block; - height: 35px; - width: 35px; + height: 40px; + width: 40px; } .mx_TagPanel .mx_TagTile.mx_AccessibleButton:focus { @@ -119,11 +125,38 @@ limitations under the License. } .mx_TagPanel_groupsButton { - margin-bottom: 17px; - margin-top: 18px; - height: 25px; + flex: 0; + margin: 17px 0 3px 0; } -.mx_TagPanel_groupsButton object { - pointer-events: none; +.mx_TagPanel_groupsButton > .mx_GroupsButton:before { + mask: url('../../img/feather-icons/users.svg'); + mask-position: center 11px; +} + +.mx_TagPanel_groupsButton > .mx_TagPanel_report:before { + mask: url('../../img/feather-icons/life-buoy.svg'); + mask-position: center 9px; +} + +.mx_TagPanel_groupsButton > .mx_AccessibleButton { + margin-bottom: 12px; + height: 40px; + width: 40px; + border-radius: 20px; + background-color: $roomheader-addroom-color; + position: relative; + /* overwrite mx_RoleButton inline-block */ + display: block !important; + + &:before { + background-color: $tagpanel-bg-color; + mask-repeat: no-repeat; + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + } } diff --git a/res/css/structures/_TopLeftMenuButton.scss b/res/css/structures/_TopLeftMenuButton.scss new file mode 100644 index 0000000000..43a1e27ee4 --- /dev/null +++ b/res/css/structures/_TopLeftMenuButton.scss @@ -0,0 +1,44 @@ +/* +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_TopLeftMenuButton { + flex: 0 0 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_TopLeftMenuButton .mx_BaseAvatar { + margin: 0 7px; +} + +.mx_TopLeftMenuButton_name { + margin: 0 7px; + font-size: 18px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + font-weight: 600; +} + +.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/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index edf455049b..d6702a232c 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -16,9 +16,8 @@ limitations under the License. .mx_AccessibleButton:focus { outline: 0; - filter: brightness($focus-brightness); } .mx_AccessibleButton { cursor: pointer; -} \ No newline at end of file +} diff --git a/res/css/views/elements/_ResizeHandle.scss b/res/css/views/elements/_ResizeHandle.scss new file mode 100644 index 0000000000..42ff6e3825 --- /dev/null +++ b/res/css/views/elements/_ResizeHandle.scss @@ -0,0 +1,46 @@ +/* +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_ResizeHandle { + cursor: row-resize; + flex: 0 0 auto; + z-index: 100; +} + +.mx_ResizeHandle.mx_ResizeHandle_horizontal { + margin: 0 -5px; + padding: 0 5px; + cursor: col-resize; +} + +.mx_ResizeHandle.mx_ResizeHandle_vertical { + margin: -5px 0; + padding: 5px 0; + cursor: row-resize; +} + +.mx_ResizeHandle > div { + background: $panel-divider-color; +} + +.mx_ResizeHandle.mx_ResizeHandle_horizontal > div { + width: 1px; + height: 100%; +} + +.mx_ResizeHandle.mx_ResizeHandle_vertical > div { + height: 1px; +} diff --git a/res/css/views/groups/_GroupRoomList.scss b/res/css/views/groups/_GroupRoomList.scss index fb41ebaa9e..fefd17849c 100644 --- a/res/css/views/groups/_GroupRoomList.scss +++ b/res/css/views/groups/_GroupRoomList.scss @@ -18,4 +18,10 @@ limitations under the License. position: relative; color: $primary-fg-color; cursor: pointer; + display: flex; + align-items: center; +} + +.mx_GroupRoomList_wrapper { + padding: 10px; } 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/_EntityTile.scss b/res/css/views/rooms/_EntityTile.scss index 90d5dc9aa5..c4d4d944a6 100644 --- a/res/css/views/rooms/_EntityTile.scss +++ b/res/css/views/rooms/_EntityTile.scss @@ -15,12 +15,19 @@ limitations under the License. */ .mx_EntityTile { - display: table-row; - position: relative; + display: flex; + align-items: center; color: $primary-fg-color; cursor: pointer; } +.mx_EntityTile:hover { + background-image: url('../../img/member_chevron.png'); + background-position: center right 10px; + background-repeat: no-repeat; + padding-right: 30px; +} + .mx_EntityTile_invite { display: table-cell; vertical-align: middle; @@ -30,12 +37,10 @@ limitations under the License. .mx_EntityTile_avatar, .mx_GroupRoomTile_avatar { - display: table-cell; padding-left: 3px; padding-right: 12px; padding-top: 4px; padding-bottom: 4px; - vertical-align: middle; width: 36px; height: 36px; position: relative; @@ -51,32 +56,21 @@ limitations under the License. .mx_EntityTile_name, .mx_GroupRoomTile_name { - display: table-cell; - vertical-align: middle; + flex: 1 1 0; overflow: hidden; font-size: 14px; text-overflow: ellipsis; white-space: nowrap; - max-width: 155px; } .mx_EntityTile_details { - display: table-cell; - padding-right: 14px; - vertical-align: middle; + overflow: hidden; } .mx_EntityTile_name_hover { font-size: 13px; } -.mx_EntityTile_chevron { - margin-top: 8px; - margin-right: -4px; - margin-left: 6px; - float: right; -} - .mx_EntityTile_ellipsis .mx_EntityTile_name { font-style: italic; color: $primary-fg-color; @@ -87,6 +81,7 @@ limitations under the License. color: $primary-fg-color; } +/* .mx_EntityTile_unavailable .mx_EntityTile_avatar, .mx_EntityTile_unavailable .mx_EntityTile_name, .mx_EntityTile_unavailable .mx_EntityTile_name_hover, @@ -110,6 +105,7 @@ limitations under the License. { opacity: 0.25; } +*/ .mx_EntityTile_subtext { font-size: 11px; @@ -118,5 +114,3 @@ limitations under the License. white-space: nowrap; text-overflow: clip; } - - diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index f74e2e0850..154e5390c8 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; @@ -450,7 +445,7 @@ limitations under the License. } .mx_EventTile_content .markdown-body a { - color: $accent-color; + color: $accent-color-alt; } .mx_EventTile_content .markdown-body .hljs { diff --git a/res/css/views/rooms/_MemberInfo.scss b/res/css/views/rooms/_MemberInfo.scss index 2270e83743..4af181a464 100644 --- a/res/css/views/rooms/_MemberInfo.scss +++ b/res/css/views/rooms/_MemberInfo.scss @@ -15,14 +15,35 @@ limitations under the License. */ .mx_MemberInfo { - margin-top: 20px; - padding-right: 20px; - height: 100%; + display: flex; + flex-direction: column; + flex: 1; overflow-y: auto; } +.mx_MemberInfo_name { + align-items: center; + display: flex; +} + +.mx_MemberInfo_cancel { + height: 16px; + padding: 10px 15px; + cursor: pointer; +} + +.mx_MemberInfo_name h2 { + flex: 1; +} + .mx_MemberInfo h2 { - margin-top: 6px; + font-size: 18px; + font-weight: 600; + margin: 16px 0; +} + +.mx_MemberInfo_container { + padding: 8px; } .mx_MemberInfo .mx_RoomTile_nameContainer { @@ -37,14 +58,16 @@ limitations under the License. width: 160px; } -.mx_MemberInfo_cancel { - float: right; - margin-right: 10px; - cursor: pointer; +.mx_MemberInfo_avatar { + background: $tagpanel-bg-color; } -.mx_MemberInfo_avatar { - clear: both; +.mx_MemberInfo_avatar > img { + height: auto; + width: 100%; + max-height: 30vh; + object-fit: contain; + display: block; } .mx_MemberInfo_avatar .mx_BaseAvatar { @@ -70,7 +93,6 @@ limitations under the License. .mx_MemberInfo_profileField { font-size: 13px; position: relative; - background-color: $primary-bg-color; } .mx_MemberInfo_buttons { @@ -117,3 +139,6 @@ limitations under the License. white-space: nowrap; text-overflow: clip; } +.mx_MemberInfo .mx_MemberInfo_scrollContainer { + flex: 1; +} diff --git a/res/css/views/rooms/_MemberList.scss b/res/css/views/rooms/_MemberList.scss index cfac8797b9..6f9491b22f 100644 --- a/res/css/views/rooms/_MemberList.scss +++ b/res/css/views/rooms/_MemberList.scss @@ -17,20 +17,24 @@ limitations under the License. .mx_MemberList, .mx_GroupMemberList, .mx_GroupRoomList { - height: 100%; - - margin-top: 12px; - margin-right: 20px; - flex: 1; - display: flex; - flex-direction: column; -} -.mx_MemberList .mx_Spinner { - flex: 0 0 auto; + .mx_Spinner { + flex: 1 0 auto; + } + + h2 { + text-transform: uppercase; + color: $h3-color; + font-weight: 600; + font-size: 13px; + padding-left: 3px; + padding-right: 12px; + margin-top: 8px; + margin-bottom: 4px; + } } .mx_MemberList_chevron { @@ -49,65 +53,39 @@ limitations under the License. .mx_MemberList_query, .mx_GroupMemberList_query, .mx_GroupRoomList_query { - font-family: $font-family; - border-radius: 3px; - border: 1px solid $input-border-color; - padding: 9px; - color: $primary-fg-color; - background-color: $primary-bg-color; - margin-left: 3px; - font-size: 14px; - margin-bottom: 8px; - width: 189px; + flex: 1 1 0; } -.mx_MemberList_query::-moz-placeholder, -.mx_GroupMemberList_query::-moz-placeholder, -.mx_GroupRoomList_query::-moz-placeholder { - color: $primary-fg-color; - opacity: 0.5; - font-size: 14px; -} -.mx_MemberList_query::-webkit-input-placeholder, -.mx_GroupMemberList_query::-webkit-input-placeholder, -.mx_GroupRoomList_query::-webkit-input-placeholder { - color: $primary-fg-color; - opacity: 0.5; - font-size: 14px; -} -.mx_MemberList_joined { - order: 2; - flex: 1 0 0; - - overflow-y: auto; -} - -/* -.mx_MemberList_invited { - order: 3; - flex: 0 0 100px; - overflow-y: auto; -} -*/ - -.mx_GroupMemberList_invited h2, -.mx_MemberList_invited h2 { - text-transform: uppercase; - color: $h3-color; - font-weight: 600; - font-size: 13px; - padding-left: 3px; - padding-right: 12px; - margin-top: 8px; - margin-bottom: 4px; -} - -/* we have to have display: table in order for the horizontal wrapping to work */ .mx_MemberList_wrapper { - display: table; - table-layout: fixed; - width: 100%; + padding: 10px; } + +.mx_MemberList_invite, +.mx_RightPanel_invite { + flex: 0 0 auto; + position: relative; + background-color: $button-bg-color; + border-radius: 4px; + padding: 8px; + margin: 9px; + display: flex; + color: $button-fg-color; + font-weight: 600; + + .mx_RightPanel_icon { + padding-right: 5px; + padding-top: 2px; + } +} + +.mx_MemberList_invite span { + margin: 0 auto; + background-image: url('../../img/feather-icons/user-add.svg'); + background-repeat: no-repeat; + background-position: center left; + padding-left: 25px; + +} diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index e6a532d072..39640575ba 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -16,7 +16,6 @@ limitations under the License. */ .mx_MessageComposer_wrapper { - max-width: 960px; vertical-align: middle; margin: auto; border-top: 1px solid $primary-hairline-color; @@ -58,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 { @@ -216,7 +214,6 @@ limitations under the License. .mx_MessageComposer_formatbar { margin: auto; - max-width: 960px; display: flex; height: 30px; diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 9c1349adbc..0697ccf40f 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -14,29 +14,24 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* add 20px to the height of the header when editing */ -.mx_RoomHeader_editing { - flex: 0 0 93px ! important; +.mx_RoomHeader { + flex: 0 0 52px; + border-bottom: 1px solid $primary-hairline-color; } .mx_RoomHeader_wrapper { - max-width: 960px; margin: auto; - height: 70px; + height: 52px; align-items: center; display: flex; -} - -.mx_RoomHeader_leftRow { - margin-left: -2px; - 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; padding-right: 12px; } @@ -45,7 +40,6 @@ limitations under the License. @mixin mx_DialogButton; margin-right: 8px; margin-top: -5px; - order: 2; } .mx_RoomHeader_textButton:hover { @@ -57,31 +51,29 @@ limitations under the License. } .mx_RoomHeader_cancelButton { - order: 2; cursor: pointer; padding-left: 12px; padding-right: 12px; } -.mx_RoomHeader_rightRow { - margin-top: 4px; - background-color: $primary-bg-color; +.mx_RoomHeader_buttons { display: flex; align-items: center; - order: 3; + background-color: $primary-bg-color; + padding-right: 5px; } .mx_RoomHeader_info { - display: table-cell; - width: 100%; - vertical-align: middle; + display: flex; + flex: 1; + align-items: center; } .mx_RoomHeader_simpleHeader { - line-height: 70px; - color: $primary-fg-color; - font-size: 22px; - font-weight: bold; + line-height: 52px; + color: $roomheader-color; + font-size: 18px; + font-weight: 600; overflow: hidden; margin-left: 63px; text-overflow: ellipsis; @@ -99,22 +91,19 @@ limitations under the License. } .mx_RoomHeader_name { - vertical-align: middle; - width: 100%; - height: 31px; + flex: 0 1 auto; overflow: hidden; - color: $primary-fg-color; - font-weight: bold; - font-size: 22px; - padding-left: 19px; - padding-right: 16px; - /* why isn't text-overflow working? */ - text-overflow: ellipsis; + color: $roomheader-color; + font-weight: 600; + font-size: 18px; + 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 { @@ -166,25 +155,23 @@ limitations under the License. } .mx_RoomHeader_topic { - vertical-align: bottom; - float: left; - max-height: 38px; - color: $settings-grey-fg-color; - font-weight: 300; + flex: 1; + color: $roomtopic-color; + font-weight: 400; font-size: 13px; - margin-left: 19px; - margin-right: 16px; + margin: 0 7px; overflow: hidden; text-overflow: ellipsis; border-bottom: 1px solid transparent; - column-width: 960px; + line-height: 1.2em; + max-height: 2.4em; } .mx_RoomHeader_avatar { - display: table-cell; - width: 48px; - height: 50px; - vertical-align: middle; + flex: 0; + width: 28px; + height: 28px; + margin: 0 7px; } .mx_RoomHeader_avatar .mx_BaseAvatar_image { @@ -192,13 +179,13 @@ limitations under the License. } .mx_RoomHeader_avatarPicker { - margin-top: 23px; position: relative; } .mx_RoomHeader_avatarPicker_edit { - margin-left: 16px; - margin-top: 4px; + position: absolute; + left: 16px; + top: 18px; } .mx_RoomHeader_avatarPicker_edit > label { @@ -210,7 +197,7 @@ limitations under the License. } .mx_RoomHeader_button { - margin-left: 12px; + margin-left: 10px; cursor: pointer; } @@ -218,6 +205,10 @@ limitations under the License. pointer-events: none; } +.mx_RoomHeader_showPanel { + height: 16px; +} + .mx_RoomHeader_voipButton { display: table-cell; } diff --git a/res/css/views/rooms/_RoomList.scss b/res/css/views/rooms/_RoomList.scss index a346a06a20..8f78e3bb7a 100644 --- a/res/css/views/rooms/_RoomList.scss +++ b/res/css/views/rooms/_RoomList.scss @@ -16,8 +16,21 @@ limitations under the License. */ .mx_RoomList { - padding-bottom: 12px; - min-height: 400px; + /* take up remaining space below TopLeftMenu */ + flex: 1 1 auto; + /* use flexbox to layout sublists */ + display: flex; + flex-direction: column; + min-height: 0; +} + +.mx_SearchBox { + flex: none; +} + +/* hide resize handles next to collapsed / empty sublists */ +.mx_RoomList .mx_RoomSubList:not(.mx_RoomSubList_nonEmpty) + .mx_ResizeHandle { + display: none; } .mx_RoomList_expandButton { @@ -27,20 +40,7 @@ limitations under the License. padding-right: 12px; } -/* Evil hacky override until Chrome fixes drop and drag table cells - and we can correctly fix horizontal wrapping in the sidebar again */ -.mx_RoomList_scrollbar .gm-scroll-view { - overflow-x: hidden ! important; - overflow-y: scroll ! important; -} - -/* Make sure the scrollbar is above the sticky headers from RoomList */ -.mx_RoomList_scrollbar .gm-scrollbar.-vertical { - z-index: 6; -} - .mx_RoomList_emptySubListTip_container { - background-color: $secondary-accent-color; padding-left: 18px; padding-right: 18px; padding-top: 8px; diff --git a/res/css/views/rooms/_RoomSettings.scss b/res/css/views/rooms/_RoomSettings.scss index b3858f3ba7..4454cd479c 100644 --- a/res/css/views/rooms/_RoomSettings.scss +++ b/res/css/views/rooms/_RoomSettings.scss @@ -16,8 +16,7 @@ limitations under the License. */ .mx_RoomSettings { - margin-left: 65px; - margin-bottom: 20px; + margin: 40px; } .mx_RoomSettings_upgradeButton, diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index b5ac9aadc6..ab33f4e2d4 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -15,13 +15,30 @@ limitations under the License. */ .mx_RoomTile { - position: relative; + display: flex; + flex-direction: row; + align-items: center; cursor: pointer; - font-size: 13px; - display: block; height: 34px; + margin: 0; + padding: 0 8px 0 10px; + position: relative; +} - background-color: $secondary-accent-color; +.mx_RoomTile_menuButton { + display: none; + flex: 0 0 16px; + height: 16px; + background-image: url('../../img/icon_context.svg'); + background-repeat: no-repeat; + background-position: center; +} + +// toggle menuButton and badge on hover/menu displayed +.mx_LeftPanel_container:not(.collapsed) .mx_RoomTile:hover, .mx_RoomTile_menuDisplayed { + .mx_RoomTile_menuButton { + display: block; + } } .mx_RoomTile_tooltip { @@ -38,6 +55,11 @@ limitations under the License. vertical-align: middle; } +.mx_RoomTile_avatar { + flex: 0; + padding: 4px; +} + .mx_RoomTile_subtext { display: inline-block; font-size: 11px; @@ -78,87 +100,53 @@ limitations under the License. } .mx_RoomTile_name { - display: inline-block; - position: relative; - width: 165px; - vertical-align: middle; - padding-left: 6px; - padding-right: 6px; - padding-top: 2px; - padding-bottom: 3px; + flex: 1 5 auto; + font-size: 14px; + font-weight: 600; + padding: 6px; color: $roomtile-name-color; white-space: nowrap; - overflow: hidden; + overflow-x: hidden; text-overflow: ellipsis; } -.mx_RoomTile_invite { -/* color: rgba(69, 69, 69, 0.5); */ -} +.collapsed { + .mx_RoomTile { + margin: 0 2px; + padding: 0 2px; + position: relative; + justify-content: center; + } -.collapsed .mx_RoomTile_nameContainer { - width: 60px; /* colapsed panel width */ -} + .mx_RoomTile_name { + display: none; + } -.collapsed .mx_RoomTile_name { - display: none; -} + .mx_RoomTile_badge { + position: absolute; + right: 6px; + top: 0px; + border-radius: 16px; + z-index: 3; + border: 0.18em solid $secondary-accent-color; + } -.collapsed .mx_RoomTile_badge { - top: 0px; - min-width: 12px; - border-radius: 16px; - padding: 0px 4px 0px 4px; - z-index: 3; -} - -/* Hide the bottom of speech bubble */ -.collapsed .mx_RoomTile_highlight .mx_RoomTile_badge:after { - display: none; -} - -/* This is the bottom of the speech bubble */ -.mx_RoomTile_highlight .mx_RoomTile_badge:after { - content: ""; - position: absolute; - display: block; - width: 0; - height: 0; - margin-left: 5px; - border-top: 5px solid $warning-color; - border-right: 7px solid transparent; + .mx_RoomTile_menuButton { + display: none; //no design for this for now + } } .mx_RoomTile_badge { - display: inline-block; - min-width: 15px; - height: 15px; - position: absolute; - right: 8px; /*gutter */ - top: 9px; - border-radius: 8px; + flex: 0 1 content; + border-radius: 0.8em; + padding: 0 0.4em; color: $accent-fg-color; font-weight: 600; - font-size: 10px; - text-align: center; - padding-top: 1px; - padding-left: 4px; - padding-right: 4px; -} - -.mx_RoomTile .mx_RoomTile_badge.mx_RoomTile_badgeButton, -.mx_RoomTile.mx_RoomTile_menuDisplayed .mx_RoomTile_badge { - letter-spacing: 0.1em; - opacity: 1; -} - -.mx_RoomTile.mx_RoomTile_noBadges .mx_RoomTile_badge.mx_RoomTile_badgeButton, -.mx_RoomTile.mx_RoomTile_menuDisplayed.mx_RoomTile_noBadges .mx_RoomTile_badge { - background-color: $neutral-badge-color; + font-size: 12px; } .mx_RoomTile_unreadNotify .mx_RoomTile_badge { - background-color: $accent-color; + background-color: $roomtile-name-color; } .mx_RoomTile_highlight .mx_RoomTile_badge { @@ -167,9 +155,14 @@ limitations under the License. .mx_RoomTile_unread, .mx_RoomTile_highlight { font-weight: 800; + + .mx_RoomTile_name { + color: $roomtile-selected-color; + } } .mx_RoomTile_selected { + border-radius: 4px; background-color: $roomtile-selected-bg-color; } @@ -187,10 +180,6 @@ limitations under the License. background-color: $roomtile-focused-bg-color; } -.mx_RoomTile .mx_RoomTile_name.mx_RoomTile_badgeShown { - width: 140px; -} - .mx_RoomTile_arrow { position: absolute; right: 0px; @@ -203,4 +192,3 @@ limitations under the License. .mx_RoomTile.mx_RoomTile_transparent:focus { background-color: $roomtile-transparent-focused-color; } - 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/css/views/rooms/_TopUnreadMessagesBar.scss b/res/css/views/rooms/_TopUnreadMessagesBar.scss index 1ee56d9532..67579552c1 100644 --- a/res/css/views/rooms/_TopUnreadMessagesBar.scss +++ b/res/css/views/rooms/_TopUnreadMessagesBar.scss @@ -14,40 +14,48 @@ See the License for the specific language governing permissions and limitations under the License. */ +@charset "utf-8"; + .mx_TopUnreadMessagesBar { - margin: auto; /* centre horizontally */ - max-width: 960px; - padding-top: 10px; - padding-bottom: 10px; - border-bottom: 1px solid $primary-hairline-color; + z-index: 1000; + position: absolute; + top: 24px; + right: 24px; + width: 38px; +} + +.mx_TopUnreadMessagesBar:after { + content: "·"; + position: absolute; + top: -8px; + left: 11px; + width: 16px; + height: 16px; + border-radius: 16px; + font-weight: 600; + font-size: 30px; + line-height: 14px; + text-align: center; + color: $secondary-accent-color; + background-color: $accent-color; } .mx_TopUnreadMessagesBar_scrollUp { - display: inline; - cursor: pointer; - text-decoration: underline; -} - -.mx_TopUnreadMessagesBar_scrollUp img { - padding-left: 10px; - padding-right: 31px; - vertical-align: middle; -} - -.mx_TopUnreadMessagesBar_scrollUp span { - opacity: 0.5; -} - -.mx_TopUnreadMessagesBar_close { - float: right; - padding-right: 14px; - padding-top: 3px; + height: 38px; + border-radius: 19px; + box-sizing: border-box; + background: $primary-bg-color; + border: 1.3px solid $roomtile-name-color; cursor: pointer; } -.mx_MatrixChat_useCompactLayout { - .mx_TopUnreadMessagesBar { - padding-top: 4px; - padding-bottom: 4px; - } +.mx_TopUnreadMessagesBar_scrollUp:before { + content: ""; + position: absolute; + width: 38px; + height: 38px; + mask: url('../../img/icon-jump-to-first-unread.svg'); + mask-repeat: no-repeat; + mask-position: 9px 13px; + background: $roomtile-name-color; } diff --git a/res/css/views/rooms/_WhoIsTypingTile.scss b/res/css/views/rooms/_WhoIsTypingTile.scss new file mode 100644 index 0000000000..217a10be8d --- /dev/null +++ b/res/css/views/rooms/_WhoIsTypingTile.scss @@ -0,0 +1,77 @@ +/* +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_WhoIsTypingTile { + margin-left: -18px; //offset padding from mx_RoomView_MessageList to center avatars + padding-top: 18px; + display: flex; + align-items: center; +} + +/* position the indicator in the same place horizontally as .mx_EventTile_avatar. */ +.mx_WhoIsTypingTile_avatars { + flex: 0 0 83px; // 18 + 65 + text-align: center; +} + +.mx_WhoIsTypingTile_avatars > :not(:first-child) { + margin-left: -12px; +} + +.mx_WhoIsTypingTile_avatars .mx_BaseAvatar_image { + border: 1px solid $primary-bg-color; +} + +.mx_WhoIsTypingTile_avatars .mx_BaseAvatar_initial { + padding-top: 1px; +} + +.mx_WhoIsTypingTile_remainingAvatarPlaceholder { + display: inline-block; + color: #acacac; + background-color: #ddd; + border: 1px solid $primary-bg-color; + border-radius: 40px; + width: 24px; + height: 24px; + line-height: 24px; + font-size: 0.8em; + vertical-align: top; + text-align: center; +} + +.mx_WhoIsTypingTile_label { + flex: 1; + font-size: 14px; + font-weight: 600; + color: $eventtile-meta-color; +} + +.mx_WhoIsTypingTile_label > span { + background-image: url('../../img/typing-indicator-2x.gif'); + background-size: 25px; + background-position: left bottom; + background-repeat: no-repeat; + padding-bottom: 15px; + display: block; +} + +.mx_MatrixChat_useCompactLayout { + + .mx_WhoIsTypingTile { + padding-top: 4px; + } +} diff --git a/res/fonts/Nunito/XRXQ3I6Li01BKofIMN44Y9vKUTo.ttf b/res/fonts/Nunito/XRXQ3I6Li01BKofIMN44Y9vKUTo.ttf new file mode 100644 index 0000000000..4387fb67c4 Binary files /dev/null and b/res/fonts/Nunito/XRXQ3I6Li01BKofIMN44Y9vKUTo.ttf differ diff --git a/res/fonts/Nunito/XRXQ3I6Li01BKofIMN5cYtvKUTo.ttf b/res/fonts/Nunito/XRXQ3I6Li01BKofIMN5cYtvKUTo.ttf new file mode 100644 index 0000000000..68fb3ff5cb Binary files /dev/null and b/res/fonts/Nunito/XRXQ3I6Li01BKofIMN5cYtvKUTo.ttf differ diff --git a/res/fonts/Nunito/XRXV3I6Li01BKofINeaE.ttf b/res/fonts/Nunito/XRXV3I6Li01BKofINeaE.ttf new file mode 100644 index 0000000000..c40e599260 Binary files /dev/null and b/res/fonts/Nunito/XRXV3I6Li01BKofINeaE.ttf differ diff --git a/res/fonts/Nunito/XRXW3I6Li01BKofA6sKUYevN.ttf b/res/fonts/Nunito/XRXW3I6Li01BKofA6sKUYevN.ttf new file mode 100644 index 0000000000..0c4fd17dfa Binary files /dev/null and b/res/fonts/Nunito/XRXW3I6Li01BKofA6sKUYevN.ttf differ diff --git a/res/fonts/Nunito/XRXW3I6Li01BKofAjsOUYevN.ttf b/res/fonts/Nunito/XRXW3I6Li01BKofAjsOUYevN.ttf new file mode 100644 index 0000000000..339d59ac00 Binary files /dev/null and b/res/fonts/Nunito/XRXW3I6Li01BKofAjsOUYevN.ttf differ diff --git a/res/fonts/Nunito/XRXX3I6Li01BKofIMNaDRss.ttf b/res/fonts/Nunito/XRXX3I6Li01BKofIMNaDRss.ttf new file mode 100644 index 0000000000..b5fcd891af Binary files /dev/null and b/res/fonts/Nunito/XRXX3I6Li01BKofIMNaDRss.ttf differ diff --git a/res/img/feather-icons/face.svg b/res/img/feather-icons/face.svg new file mode 100644 index 0000000000..0a359b2dea --- /dev/null +++ b/res/img/feather-icons/face.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/res/img/feather-icons/files.svg b/res/img/feather-icons/files.svg new file mode 100644 index 0000000000..c66d9ad121 --- /dev/null +++ b/res/img/feather-icons/files.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/res/img/feather-icons/grid.svg b/res/img/feather-icons/grid.svg new file mode 100644 index 0000000000..e6912b0cc7 --- /dev/null +++ b/res/img/feather-icons/grid.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/res/img/feather-icons/life-buoy.svg b/res/img/feather-icons/life-buoy.svg new file mode 100644 index 0000000000..20bd0f0b5d --- /dev/null +++ b/res/img/feather-icons/life-buoy.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/res/img/feather-icons/notifications.svg b/res/img/feather-icons/notifications.svg new file mode 100644 index 0000000000..2fe85e810c --- /dev/null +++ b/res/img/feather-icons/notifications.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/res/img/feather-icons/paperclip.svg b/res/img/feather-icons/paperclip.svg new file mode 100644 index 0000000000..ed2bb88681 --- /dev/null +++ b/res/img/feather-icons/paperclip.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/res/img/feather-icons/phone.svg b/res/img/feather-icons/phone.svg new file mode 100644 index 0000000000..58b257f113 --- /dev/null +++ b/res/img/feather-icons/phone.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/res/img/feather-icons/search-input.svg b/res/img/feather-icons/search-input.svg new file mode 100644 index 0000000000..3be5acb32e --- /dev/null +++ b/res/img/feather-icons/search-input.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/res/img/feather-icons/search.svg b/res/img/feather-icons/search.svg new file mode 100644 index 0000000000..8b14246f64 --- /dev/null +++ b/res/img/feather-icons/search.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/res/img/feather-icons/settings.svg b/res/img/feather-icons/settings.svg new file mode 100644 index 0000000000..ea7ce5c55b --- /dev/null +++ b/res/img/feather-icons/settings.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/res/img/feather-icons/share.svg b/res/img/feather-icons/share.svg new file mode 100644 index 0000000000..a012e1b7a5 --- /dev/null +++ b/res/img/feather-icons/share.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/res/img/feather-icons/user-add.svg b/res/img/feather-icons/user-add.svg new file mode 100644 index 0000000000..cbb25934c1 --- /dev/null +++ b/res/img/feather-icons/user-add.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/res/img/feather-icons/user.svg b/res/img/feather-icons/user.svg new file mode 100644 index 0000000000..a789e580d5 --- /dev/null +++ b/res/img/feather-icons/user.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/res/img/feather-icons/users.svg b/res/img/feather-icons/users.svg new file mode 100644 index 0000000000..b0deac0a9e --- /dev/null +++ b/res/img/feather-icons/users.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/res/img/feather-icons/video.svg b/res/img/feather-icons/video.svg new file mode 100644 index 0000000000..a4c456832f --- /dev/null +++ b/res/img/feather-icons/video.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + 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..73500ebe06 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-jump-to-first-unread.svg b/res/img/icon-jump-to-first-unread.svg new file mode 100644 index 0000000000..652ccec20d --- /dev/null +++ b/res/img/icon-jump-to-first-unread.svg @@ -0,0 +1,16 @@ + + + + + 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-close.svg b/res/img/icons-close.svg index 453b51082f..b2dd44fc26 100644 --- a/res/img/icons-close.svg +++ b/res/img/icons-close.svg @@ -1,23 +1,96 @@ - - - - -icons_create_room -Created with sketchtool. - - - - - - - - - - - - - - + + + +image/svg+xmlicons_create_room + +icons_create_room +Created with sketchtool. + + + + + + + + + + + + + + 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-groups-nobg.svg b/res/img/icons-groups-nobg.svg new file mode 100644 index 0000000000..a3d223b76d --- /dev/null +++ b/res/img/icons-groups-nobg.svg @@ -0,0 +1,60 @@ + +image/svg+xml + + + + + + + + + + + + + + + \ 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-room-add.svg b/res/img/icons-room-add.svg index fc0ab750b6..f0b7584df9 100644 --- a/res/img/icons-room-add.svg +++ b/res/img/icons-room-add.svg @@ -1,23 +1,9 @@ - - - - - - - - - - - - - - + + + + + + + + diff --git a/res/img/icons-room-nobg.svg b/res/img/icons-room-nobg.svg new file mode 100644 index 0000000000..8ca7ab272b --- /dev/null +++ b/res/img/icons-room-nobg.svg @@ -0,0 +1,28 @@ + +image/svg+xml + + + + + + + \ No newline at end of file diff --git a/res/img/icons-search-copy.svg b/res/img/icons-search-copy.svg deleted file mode 100644 index b026718b84..0000000000 --- a/res/img/icons-search-copy.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/res/img/icons-search.svg b/res/img/icons-search.svg index d85709e66c..9d3e98106b 100644 --- a/res/img/icons-search.svg +++ b/res/img/icons-search.svg @@ -1,9 +1,15 @@ - - - - - - - - + + + Shape + Created with Sketch. + + + + + + + + + + \ No newline at end of file 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/img/search.svg b/res/img/search.svg deleted file mode 100644 index bd4cd9200c..0000000000 --- a/res/img/search.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - icons_search - Created with bin/sketchtool. - - - - - - - - - - - - \ No newline at end of file diff --git a/res/img/topleft-chevron.svg b/res/img/topleft-chevron.svg new file mode 100644 index 0000000000..1cfeaf6352 --- /dev/null +++ b/res/img/topleft-chevron.svg @@ -0,0 +1,86 @@ + + + + + + image/svg+xml + + dropdown + + + + + + dropdown + Created with Sketch. + + + + + + + + + + + + diff --git a/res/img/typing-indicator-2x.gif b/res/img/typing-indicator-2x.gif new file mode 100644 index 0000000000..86e34c7555 Binary files /dev/null and b/res/img/typing-indicator-2x.gif differ diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 5dbc00af4e..636db5b39e 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 @@ -12,6 +12,7 @@ $light-fg-color: #747474; // button UI (white-on-green in light skin) $accent-fg-color: $primary-bg-color; $accent-color: #76CFA6; +$accent-color-alt: $accent-color; $accent-color-50pct: #76CFA67F; $selection-fg-color: $primary-fg-color; @@ -63,6 +64,10 @@ $primary-hairline-color: #474747; // used for the border of input text fields $input-border-color: #3a3a3a; +$input-darker-bg-color: #c1c9d6; +$input-darker-fg-color: #9fa9ba; +$button-bg-color: #7ac9a1; +$button-fg-color: white; // apart from login forms, which have stronger border $strong-input-border-color: #656565; @@ -73,9 +78,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; @@ -108,6 +115,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 new file mode 100644 index 0000000000..0851762be2 --- /dev/null +++ b/res/themes/dharma/css/_dharma.scss @@ -0,0 +1,322 @@ +@import "_fonts.scss"; + +// XXX: check this? +/* Nunito lacks combining diacritics, so these will fall through + to the next font. Helevetica's diacritics however do not combine + nicely with Open Sans (on OSX, at least) and result in a huge + horizontal mess. Arial empirically gets it right, hence prioritising + Arial here. */ +$font-family: 'Nunito', Arial, Helvetica, Sans-Serif; + +// typical text (dark-on-white in light skin) +$primary-fg-color: #454545; +$primary-bg-color: #ffffff; + +// used for dialog box text +$light-fg-color: #747474; + +// used for focusing form controls +$focus-bg-color: #dddddd; + +// button UI (white-on-green in light skin) +$accent-fg-color: #ffffff; +$accent-color: #7ac9a1; +$accent-color-50pct: #92caad; +$accent-color-alt: #238CF5; + +$selection-fg-color: $primary-bg-color; + +$focus-brightness: 105%; + +// red warning colour +$warning-color: #f56679; +// background colour for warnings +$warning-bg-color: #DF2A8B; +$info-bg-color: #2A9EDF; +$mention-user-pill-bg-color: $warning-color; +$other-user-pill-bg-color: rgba(0, 0, 0, 0.1); + +// pinned events indicator +$pinned-unread-color: #ff0064; // $warning-color +$pinned-color: #888; + +// informational plinth +$info-plinth-bg-color: #f7f7f7; +$info-plinth-fg-color: #888; + +$preview-bar-bg-color: #f7f7f7; + +// left-panel style muted accent color +$secondary-accent-color: #f2f5f8; +$tertiary-accent-color: #d3efe1; + +$tagpanel-bg-color: #2e3649; + +// used by RoomDirectory permissions +$plinth-bg-color: $secondary-accent-color; + +// used by RoomDropTarget +$droptarget-bg-color: rgba(255,255,255,0.5); + +// used by AddressSelector +$selected-color: $secondary-accent-color; + +// selected for hoverover & selected event tiles +$event-selected-color: #f7f7f7; + +// used for the hairline dividers in RoomView +$primary-hairline-color: #e5e5e5; + +// used for the border of input text fields +$input-border-color: #f0f0f0; +$input-darker-bg-color: rgba(193, 201, 214, 0.29); +$input-darker-fg-color: #9fa9ba; +$input-lighter-bg-color: #f2f5f8; +$input-lighter-fg-color: $input-darker-fg-color; + +$button-bg-color: #7ac9a1; +$button-fg-color: white; + +// apart from login forms, which have stronger border +$strong-input-border-color: #c7c7c7; + +// used for UserSettings EditableText +$input-underline-color: rgba(151, 151, 151, 0.5); +$input-fg-color: rgba(74, 74, 74, 0.9); + +// context menus +$menu-border-color: #ebedf8; +$menu-bg-color: #fff; +$menu-selected-color: #f5f8fa; + +$avatar-initial-color: #ffffff; +$avatar-bg-color: #ffffff; + +$h3-color: #3d3b39; + +$dialog-background-bg-color: #e9e9e9; +$lightbox-background-bg-color: #000; + +$imagebody-giflabel: rgba(0, 0, 0, 0.7); +$imagebody-giflabel-border: rgba(0, 0, 0, 0.2); + +$greyed-fg-color: #888; + +$neutral-badge-color: #dbdbdb; + +$preview-widget-bar-color: #ddd; +$preview-widget-fg-color: $greyed-fg-color; + +$blockquote-bar-color: #ddd; +$blockquote-fg-color: #777; + +$settings-grey-fg-color: #a2a2a2; + +$voip-decline-color: #f48080; +$voip-accept-color: #80f480; + +$rte-bg-color: #e9e9e9; +$rte-code-bg-color: rgba(0, 0, 0, 0.04); +$rte-room-pill-color: #aaa; +$rte-group-pill-color: #aaa; + +$topleftmenu-color: #212121; +$roomheader-color: #45474a; +$roomheader-addroom-color: #91A1C0; +$roomtopic-color: #9fa9ba; +$eventtile-meta-color: $roomtopic-color; + +// ******************** + +$roomtile-name-color: #61708b; +$roomtile-selected-color: #212121; +$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; +$roomsublist-label-fg-color: $roomtile-name-color; +$roomsublist-label-bg-color: $tertiary-accent-color; +$roomsublist-chevron-color: $accent-color; + +$panel-divider-color: #dee1f3; + +// ******************** + +$widget-menu-bar-bg-color: $tertiary-accent-color; + +// ******************** + +// event tile lifecycle +$event-encrypting-color: #abddbc; +$event-sending-color: #ddd; +$event-notsent-color: #f44; + +// event redaction +$event-redacted-fg-color: #e2e2e2; +$event-redacted-border-color: #cccccc; + +// event timestamp +$event-timestamp-color: #acacac; + +$edit-button-url: "../../img/icon_context_message.svg"; +$copy-button-url: "../../img/icon_copy_message.svg"; + +// e2e +$e2e-verified-color: #76cfa5; // N.B. *NOT* the same as $accent-color +$e2e-unverified-color: #e8bf37; +$e2e-warning-color: #ba6363; + +/*** ImageView ***/ +$lightbox-bg-color: #454545; +$lightbox-fg-color: #ffffff; +$lightbox-border-color: #ffffff; + +// unused? +$progressbar-color: #000; + +/*** form elements ***/ + +// .mx_textinput is a container for a text input +// + some other controls like buttons, ... +// it has the appearance of a text box so the controls +// appear to be part of the input + +.mx_MatrixChat { + + :not(.mx_textinput) > input[type=text], + :not(.mx_textinput) > input[type=search], + .mx_textinput { + display: block; + margin: 9px; + box-sizing: border-box; + background-color: transparent; + color: $input-darker-fg-color; + border-radius: 4px; + border: 1px solid #c1c1c1; + flex: 0 0 auto; + } + + .mx_textinput { + display: flex; + align-items: center; + + > input[type=text], + > input[type=search] { + border: none; + flex: 1; + color: $primary-fg-color; + }, + input::placeholder { + color: $roomsublist-label-fg-color; + } + } +} + +input[type=text], +input[type=search], +input[type=password] { + padding: 9px; + font-family: $font-family; + font-size: 14px; + font-weight: 600; + min-width: 0; +} + +/*** panels ***/ +.dark-panel { + background-color: $secondary-accent-color; +} + +.dark-panel { + :not(.mx_textinput) > input[type=text], + :not(.mx_textinput) > input[type=search], + .mx_textinput { + color: $input-darker-fg-color; + background-color: $input-darker-bg-color; + border: none; + } +} + +.light-panel { + :not(.mx_textinput) > input[type=text], + :not(.mx_textinput) > input[type=search], + .mx_textinput { + color: $input-lighter-fg-color; + background-color: $input-lighter-bg-color; + border: none; + } +} + +input[type=text].mx_textinput_icon, +input[type=search].mx_textinput_icon { + padding-left: 36px; + background-repeat: no-repeat; + background-position: 10px center; +} + + +// FIXME THEME - Tint by CSS rather than referencing a duplicate asset +input[type=text].mx_textinput_icon.mx_textinput_search, +input[type=search].mx_textinput_icon.mx_textinput_search { + background-image: url('../../img/feather-icons/search-input.svg'); +} + +// dont search UI as not all browsers support it, +// we implement it ourselves where needed instead +input[type=search]::-webkit-search-decoration, +input[type=search]::-webkit-search-cancel-button, +input[type=search]::-webkit-search-results-button, +input[type=search]::-webkit-search-results-decoration { + display: none; +} + +.input[type=text]::-webkit-input-placeholder, +.input[type=text]::-moz-placeholder, +.input[type=search]::-webkit-input-placeholder, +.input[type=search]::-moz-placeholder { + color: #a5aab2; +} +// ***** Mixins! ***** + +@define-mixin mx_DialogButton { + /* align images in buttons (eg spinners) */ + vertical-align: middle; + border: 0px; + border-radius: 4px; + font-family: $font-family; + font-size: 14px; + color: $button-fg-color; + background-color: $button-bg-color; + width: auto; + padding: 7px; + padding-left: 1.5em; + padding-right: 1.5em; + cursor: pointer; + display: inline-block; + outline: none; +} + +@define-mixin mx_DialogButton_hover { +} + +@define-mixin mx_DialogButton_danger { + background-color: $accent-color; +} + +@define-mixin mx_DialogButton_small { + @mixin mx_DialogButton; + font-size: 15px; + padding: 0px 1.5em 0px 1.5em; +} diff --git a/res/themes/dharma/css/_fonts.scss b/res/themes/dharma/css/_fonts.scss new file mode 100644 index 0000000000..bb45432262 --- /dev/null +++ b/res/themes/dharma/css/_fonts.scss @@ -0,0 +1,64 @@ +/* + * Nunito. + * Includes extended Latin and Vietnamese character sets + * Current URLs are v9, derived from the contents of + * https://fonts.googleapis.com/css?family=Nunito:400,400i,600,600i,700,700i&subset=latin-ext,vietnamese + */ + +/* the 'src' links are relative to the bundle.css, which is in a subdirectory. + */ +@font-face { + font-family: 'Nunito'; + font-style: italic; + font-weight: 400; + src: url('../../fonts/Nunito/XRXX3I6Li01BKofIMNaDRss.ttf') format('truetype'); +} +@font-face { + font-family: 'Nunito'; + font-style: italic; + font-weight: 600; + src: url('../../fonts/Nunito/XRXQ3I6Li01BKofIMN5cYtvKUTo.ttf') format('truetype'); +} +@font-face { + font-family: 'Nunito'; + font-style: italic; + font-weight: 700; + src: url('../../fonts/Nunito/XRXQ3I6Li01BKofIMN44Y9vKUTo.ttf') format('truetype'); +} +@font-face { + font-family: 'Nunito'; + font-style: normal; + font-weight: 400; + src: url('../../fonts/Nunito/XRXV3I6Li01BKofINeaE.ttf') format('truetype'); +} +@font-face { + font-family: 'Nunito'; + font-style: normal; + font-weight: 600; + src: url('../../fonts/Nunito/XRXW3I6Li01BKofA6sKUYevN.ttf') format('truetype'); +} +@font-face { + font-family: 'Nunito'; + font-style: normal; + font-weight: 700; + src: url('../../fonts/Nunito/XRXW3I6Li01BKofAjsOUYevN.ttf') format('truetype'); +} + +/* + * Fira Mono + * Used for monospace copy, i.e. code + */ + +@font-face { + font-family: 'Fira Mono'; + src: url('../../fonts/Fira_Mono/FiraMono-Regular.ttf') format('truetype'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'Fira Mono'; + src: url('../../fonts/Fira_Mono/FiraMono-Bold.ttf') format('truetype'); + font-weight: 700; + font-style: normal; +} diff --git a/res/themes/dharma/css/dharma.scss b/res/themes/dharma/css/dharma.scss new file mode 100644 index 0000000000..0f4db55fd2 --- /dev/null +++ b/res/themes/dharma/css/dharma.scss @@ -0,0 +1,3 @@ +@import "_dharma.scss"; +@import "../../../../res/css/_components.scss"; + diff --git a/res/themes/light/css/_base.scss b/res/themes/light/css/_base.scss index c275b94fb5..9fcb58d7f1 100644 --- a/res/themes/light/css/_base.scss +++ b/res/themes/light/css/_base.scss @@ -1,3 +1,5 @@ +@import "_fonts.scss"; + /* Open Sans lacks combining diacritics, so these will fall through to the next font. Helevetica's diacritics however do not combine nicely with Open Sans (on OSX, at least) and result in a huge @@ -18,6 +20,7 @@ $focus-bg-color: #dddddd; // button UI (white-on-green in light skin) $accent-fg-color: #ffffff; $accent-color: #76CFA6; +$accent-color-alt: $accent-color; $accent-color-50pct: #76CFA67F; $selection-fg-color: $primary-bg-color; @@ -46,6 +49,8 @@ $preview-bar-bg-color: #f7f7f7; $secondary-accent-color: #eaf5f0; $tertiary-accent-color: #d3efe1; +$tagpanel-bg-color: $tertiary-accent-color; + // used by RoomDirectory permissions $plinth-bg-color: $secondary-accent-color; @@ -64,6 +69,10 @@ $primary-hairline-color: #e5e5e5; // used for the border of input text fields $input-border-color: #f0f0f0; +$input-darker-bg-color: #c1c9d6; +$input-darker-fg-color: #9fa9ba; +$button-bg-color: #7ac9a1; +$button-fg-color: white; // apart from login forms, which have stronger border $strong-input-border-color: #c7c7c7; @@ -74,6 +83,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; @@ -103,12 +113,28 @@ $rte-code-bg-color: rgba(0, 0, 0, 0.04); $rte-room-pill-color: #aaa; $rte-group-pill-color: #aaa; +$topleftmenu-color: $primary-fg-color; +$roomheader-color: $primary-fg-color; +$roomheader-addroom-color: $primary-bg-color; +$roomtopic-color: $settings-grey-fg-color; +$eventtile-meta-color: $roomtopic-color; // ******************** $roomtile-name-color: rgba(69, 69, 69, 0.8); +$roomtile-selected-color: $roomtile-name-color; +$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/res/css/_fonts.scss b/res/themes/light/css/_fonts.scss similarity index 100% rename from res/css/_fonts.scss rename to res/themes/light/css/_fonts.scss diff --git a/scripts/fetchdep.sh b/scripts/fetchdep.sh index 4f42859439..95fc4b0603 100755 --- a/scripts/fetchdep.sh +++ b/scripts/fetchdep.sh @@ -1,7 +1,5 @@ #!/bin/sh -set -e - org="$1" repo="$2" defbranch="$3" @@ -10,16 +8,20 @@ defbranch="$3" rm -r "$repo" || true -curbranch="$TRAVIS_PULL_REQUEST_BRANCH" -[ -z "$curbranch" ] && curbranch="$TRAVIS_BRANCH" -[ -z "$curbranch" ] && curbranch=`"echo $GIT_BRANCH" | sed -e 's/^origin\///'` # jenkins +clone() { + branch=$1 + if [ -n "$branch" ] + then + echo "Trying to use the branch $branch" + git clone https://github.com/$org/$repo.git $repo --branch "$branch" && exit 0 + fi +} -if [ -n "$curbranch" ] -then - echo "Determined branch to be $curbranch" - - git clone https://github.com/$org/$repo.git $repo --branch "$curbranch" && exit 0 -fi - -echo "Checking out default branch $defbranch" -git clone https://github.com/$org/$repo.git $repo --branch $defbranch +# Try the PR author's branch in case it exists on the deps as well. +clone $TRAVIS_PULL_REQUEST_BRANCH +# Try the target branch of the push or PR. +clone $TRAVIS_BRANCH +# Try the current branch from Jenkins. +clone `"echo $GIT_BRANCH" | sed -e 's/^origin\///'` +# Use the default branch as the last resort. +clone $defbranch diff --git a/src/PageTypes.js b/src/PageTypes.js index 66d930c288..60111723fb 100644 --- a/src/PageTypes.js +++ b/src/PageTypes.js @@ -20,7 +20,6 @@ export default { HomePage: "home_page", RoomView: "room_view", UserSettings: "user_settings", - CreateRoom: "create_room", RoomDirectory: "room_directory", UserView: "user_view", GroupView: "group_view", 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/Presence.js b/src/Presence.js index b1e85e4bc7..849efdef1c 100644 --- a/src/Presence.js +++ b/src/Presence.js @@ -17,21 +17,33 @@ limitations under the License. const MatrixClientPeg = require("./MatrixClientPeg"); const dis = require("./dispatcher"); +import Timer from './utils/Timer'; // Time in ms after that a user is considered as unavailable/away const UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins const PRESENCE_STATES = ["online", "offline", "unavailable"]; class Presence { + + constructor() { + this._activitySignal = null; + this._unavailableTimer = null; + this._onAction = this._onAction.bind(this); + this._dispatcherRef = null; + } /** * Start listening the user activity to evaluate his presence state. * Any state change will be sent to the Home Server. */ - start() { - this.running = true; - if (undefined === this.state) { - this._resetTimer(); - this.dispatcherRef = dis.register(this._onAction.bind(this)); + async start() { + this._unavailableTimer = new Timer(UNAVAILABLE_TIME_MS); + // the user_activity_start action starts the timer + this._dispatcherRef = dis.register(this._onAction); + while (this._unavailableTimer) { + try { + await this._unavailableTimer.finished(); + this.setState("unavailable"); + } catch(e) { /* aborted, stop got called */ } } } @@ -39,13 +51,14 @@ class Presence { * Stop tracking user activity */ stop() { - this.running = false; - if (this.timer) { - clearInterval(this.timer); - this.timer = undefined; - dis.unregister(this.dispatcherRef); + if (this._dispatcherRef) { + dis.unregister(this._dispatcherRef); + this._dispatcherRef = null; + } + if (this._unavailableTimer) { + this._unavailableTimer.abort(); + this._unavailableTimer = null; } - this.state = undefined; } /** @@ -56,21 +69,25 @@ class Presence { return this.state; } + _onAction(payload) { + if (payload.action === 'user_activity') { + this.setState("online"); + this._unavailableTimer.restart(); + } + } + /** * Set the presence state. * If the state has changed, the Home Server will be notified. * @param {string} newState the new presence state (see PRESENCE enum) */ - setState(newState) { + async setState(newState) { if (newState === this.state) { return; } if (PRESENCE_STATES.indexOf(newState) === -1) { throw new Error("Bad presence state: " + newState); } - if (!this.running) { - return; - } const old_state = this.state; this.state = newState; @@ -78,42 +95,14 @@ class Presence { return; // don't try to set presence when a guest; it won't work. } - const self = this; - MatrixClientPeg.get().setPresence(this.state).done(function() { + try { + await MatrixClientPeg.get().setPresence(this.state); console.log("Presence: %s", newState); - }, function(err) { + } catch(err) { console.error("Failed to set presence: %s", err); - self.state = old_state; - }); - } - - /** - * Callback called when the user made no action on the page for UNAVAILABLE_TIME ms. - * @private - */ - _onUnavailableTimerFire() { - this.setState("unavailable"); - } - - _onAction(payload) { - if (payload.action === "user_activity") { - this._resetTimer(); + this.state = old_state; } } - - /** - * Callback called when the user made an action on the page - * @private - */ - _resetTimer() { - const self = this; - this.setState("online"); - // Re-arm the timer - clearTimeout(this.timer); - this.timer = setTimeout(function() { - self._onUnavailableTimerFire(); - }, UNAVAILABLE_TIME_MS); - } } module.exports = new Presence(); diff --git a/src/Tinter.js b/src/Tinter.js index d24a4c3e74..de9ae94097 100644 --- a/src/Tinter.js +++ b/src/Tinter.js @@ -154,6 +154,8 @@ class Tinter { } tint(primaryColor, secondaryColor, tertiaryColor) { + return; + // eslint-disable-next-line no-unreachable this.currentTint[0] = primaryColor; this.currentTint[1] = secondaryColor; this.currentTint[2] = tertiaryColor; diff --git a/src/UserActivity.js b/src/UserActivity.js index c628ab4186..4e3667274c 100644 --- a/src/UserActivity.js +++ b/src/UserActivity.js @@ -15,32 +15,72 @@ limitations under the License. */ import dis from './dispatcher'; +import Timer from './utils/Timer'; -const MIN_DISPATCH_INTERVAL_MS = 500; -const CURRENTLY_ACTIVE_THRESHOLD_MS = 2000; +// important this is larger than the timeouts of timers +// used with UserActivity.timeWhileActive, +// such as READ_MARKER_INVIEW_THRESHOLD_MS, +// READ_MARKER_OUTOFVIEW_THRESHOLD_MS, +// READ_RECEIPT_INTERVAL_MS in TimelinePanel +const CURRENTLY_ACTIVE_THRESHOLD_MS = 2 * 60 * 1000; /** * This class watches for user activity (moving the mouse or pressing a key) - * and dispatches the user_activity action at times when the user is interacting - * with the app (but at a much lower frequency than mouse move events) + * and starts/stops attached timers while the user is active. */ class UserActivity { + constructor() { + this._attachedTimers = []; + this._activityTimeout = new Timer(CURRENTLY_ACTIVE_THRESHOLD_MS); + this._onUserActivity = this._onUserActivity.bind(this); + this._onDocumentBlurred = this._onDocumentBlurred.bind(this); + this._onPageVisibilityChanged = this._onPageVisibilityChanged.bind(this); + this.lastScreenX = 0; + this.lastScreenY = 0; + } + + /** + * Runs the given timer while the user is active, aborting when the user becomes inactive. + * Can be called multiple times with the same already running timer, which is a NO-OP. + * Can be called before the user becomes active, in which case it is only started + * later on when the user does become active. + */ + timeWhileActive(timer) { + // important this happens first + const index = this._attachedTimers.indexOf(timer); + if (index === -1) { + this._attachedTimers.push(timer); + // remove when done or aborted + timer.finished().finally(() => { + const index = this._attachedTimers.indexOf(timer); + if (index !== -1) { // should never be -1 + this._attachedTimers.splice(index, 1); + } + // as we fork the promise here, + // avoid unhandled rejection warnings + }).catch((err) => {}); + } + if (this.userCurrentlyActive()) { + timer.start(); + } + } + /** * Start listening to user activity */ start() { - document.onmousedown = this._onUserActivity.bind(this); - document.onmousemove = this._onUserActivity.bind(this); - document.onkeydown = this._onUserActivity.bind(this); + document.onmousedown = this._onUserActivity; + document.onmousemove = this._onUserActivity; + document.onkeydown = this._onUserActivity; + document.addEventListener("visibilitychange", this._onPageVisibilityChanged); + document.addEventListener("blur", this._onDocumentBlurred); + document.addEventListener("focus", this._onUserActivity); // can't use document.scroll here because that's only the document // itself being scrolled. Need to use addEventListener's useCapture. // also this needs to be the wheel event, not scroll, as scroll is // fired when the view scrolls down for a new message. - window.addEventListener('wheel', this._onUserActivity.bind(this), + window.addEventListener('wheel', this._onUserActivity, { passive: true, capture: true }); - this.lastActivityAtTs = new Date().getTime(); - this.lastDispatchAtTs = 0; - this.activityEndTimer = undefined; } /** @@ -50,8 +90,12 @@ class UserActivity { document.onmousedown = undefined; document.onmousemove = undefined; document.onkeydown = undefined; - window.removeEventListener('wheel', this._onUserActivity.bind(this), + window.removeEventListener('wheel', this._onUserActivity, { passive: true, capture: true }); + + document.removeEventListener("visibilitychange", this._onPageVisibilityChanged); + document.removeEventListener("blur", this._onDocumentBlurred); + document.removeEventListener("focus", this._onUserActivity); } /** @@ -60,10 +104,22 @@ class UserActivity { * @returns {boolean} true if user is currently/very recently active */ userCurrentlyActive() { - return this.lastActivityAtTs > new Date().getTime() - CURRENTLY_ACTIVE_THRESHOLD_MS; + return this._activityTimeout.isRunning(); } - _onUserActivity(event) { + _onPageVisibilityChanged(e) { + if (document.visibilityState === "hidden") { + this._activityTimeout.abort(); + } else { + this._onUserActivity(e); + } + } + + _onDocumentBlurred() { + this._activityTimeout.abort(); + } + + async _onUserActivity(event) { if (event.screenX && event.type === "mousemove") { if (event.screenX === this.lastScreenX && event.screenY === this.lastScreenY) { // mouse hasn't actually moved @@ -73,30 +129,20 @@ class UserActivity { this.lastScreenY = event.screenY; } - this.lastActivityAtTs = new Date().getTime(); - if (this.lastDispatchAtTs < this.lastActivityAtTs - MIN_DISPATCH_INTERVAL_MS) { - this.lastDispatchAtTs = this.lastActivityAtTs; - dis.dispatch({ - action: 'user_activity', - }); - if (!this.activityEndTimer) { - this.activityEndTimer = setTimeout(this._onActivityEndTimer.bind(this), MIN_DISPATCH_INTERVAL_MS); - } - } - } - - _onActivityEndTimer() { - const now = new Date().getTime(); - const targetTime = this.lastActivityAtTs + MIN_DISPATCH_INTERVAL_MS; - if (now >= targetTime) { - dis.dispatch({ - action: 'user_activity_end', - }); - this.activityEndTimer = undefined; + dis.dispatch({action: 'user_activity'}); + if (!this._activityTimeout.isRunning()) { + this._activityTimeout.start(); + dis.dispatch({action: 'user_activity_start'}); + this._attachedTimers.forEach((t) => t.start()); + try { + await this._activityTimeout.finished(); + } catch (_e) { /* aborted */ } + this._attachedTimers.forEach((t) => t.abort()); } else { - this.activityEndTimer = setTimeout(this._onActivityEndTimer.bind(this), targetTime - now); + this._activityTimeout.restart(); } } } + module.exports = new UserActivity(); diff --git a/src/WhoIsTyping.js b/src/WhoIsTyping.js index 0edad8d4a5..78ca77ce5a 100644 --- a/src/WhoIsTyping.js +++ b/src/WhoIsTyping.js @@ -63,16 +63,16 @@ module.exports = { if (whoIsTyping.length == 0) { return ''; } else if (whoIsTyping.length == 1) { - return _t('%(displayName)s is typing', {displayName: whoIsTyping[0].name}); + return _t('%(displayName)s is typing …', {displayName: whoIsTyping[0].name}); } const names = whoIsTyping.map(function(m) { return m.name; }); if (othersCount>=1) { - return _t('%(names)s and %(count)s others are typing', {names: names.slice(0, limit - 1).join(', '), count: othersCount}); + return _t('%(names)s and %(count)s others are typing …', {names: names.slice(0, limit - 1).join(', '), count: othersCount}); } else { const lastPerson = names.pop(); - return _t('%(names)s and %(lastPerson)s are typing', {names: names.join(', '), lastPerson: lastPerson}); + return _t('%(names)s and %(lastPerson)s are typing …', {names: names.join(', '), lastPerson: lastPerson}); } }, }; diff --git a/src/components/structures/AutoHideScrollbar.js b/src/components/structures/AutoHideScrollbar.js new file mode 100644 index 0000000000..47ae24ba0f --- /dev/null +++ b/src/components/structures/AutoHideScrollbar.js @@ -0,0 +1,137 @@ +/* +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"; + +// derived from code from github.com/noeldelgado/gemini-scrollbar +// Copyright (c) Noel Delgado (pixelia.me) +function getScrollbarWidth(alternativeOverflow) { + const div = document.createElement('div'); + div.style.position = 'absolute'; + div.style.top = '-9999px'; + div.style.width = '100px'; + div.style.height = '100px'; + div.style.overflow = "scroll"; + if (alternativeOverflow) { + div.style.overflow = alternativeOverflow; + } + div.style.msOverflowStyle = '-ms-autohiding-scrollbar'; + document.body.appendChild(div); + const scrollbarWidth = (div.offsetWidth - div.clientWidth); + document.body.removeChild(div); + return scrollbarWidth; +} + +function install() { + const scrollbarWidth = getScrollbarWidth(); + if (scrollbarWidth !== 0) { + const hasForcedOverlayScrollbar = getScrollbarWidth('overlay') === 0; + // overflow: overlay on webkit doesn't auto hide the scrollbar + if (hasForcedOverlayScrollbar) { + document.body.classList.add("mx_scrollbar_overlay_noautohide"); + } else { + document.body.classList.add("mx_scrollbar_nooverlay"); + const style = document.createElement('style'); + style.type = 'text/css'; + style.innerText = + `body.mx_scrollbar_nooverlay { --scrollbar-width: ${scrollbarWidth}px; }`; + document.head.appendChild(style); + } + } +} + +const installBodyClassesIfNeeded = (function() { + let installed = false; + return function() { + if (!installed) { + install(); + installed = true; + } + }; +})(); + +export default class AutoHideScrollbar extends React.Component { + constructor(props) { + super(props); + this.onOverflow = this.onOverflow.bind(this); + this.onUnderflow = this.onUnderflow.bind(this); + this._collectContainerRef = this._collectContainerRef.bind(this); + this._needsOverflowListener = null; + } + + onOverflow() { + this.containerRef.classList.add("mx_AutoHideScrollbar_overflow"); + this.containerRef.classList.remove("mx_AutoHideScrollbar_underflow"); + } + + onUnderflow() { + this.containerRef.classList.remove("mx_AutoHideScrollbar_overflow"); + this.containerRef.classList.add("mx_AutoHideScrollbar_underflow"); + } + + checkOverflow() { + if (!this._needsOverflowListener) { + return; + } + if (this.containerRef.scrollHeight > this.containerRef.clientHeight) { + this.onOverflow(); + } else { + this.onUnderflow(); + } + } + + componentDidUpdate() { + this.checkOverflow(); + } + + componentDidMount() { + installBodyClassesIfNeeded(); + this._needsOverflowListener = + document.body.classList.contains("mx_scrollbar_nooverlay"); + if (this._needsOverflowListener) { + this.containerRef.addEventListener("overflow", this.onOverflow); + this.containerRef.addEventListener("underflow", this.onUnderflow); + } + this.checkOverflow(); + } + + _collectContainerRef(ref) { + if (ref && !this.containerRef) { + this.containerRef = ref; + } + if (this.props.wrappedRef) { + this.props.wrappedRef(ref); + } + } + + componentWillUnmount() { + if (this._needsOverflowListener && this.containerRef) { + this.containerRef.removeEventListener("overflow", this.onOverflow); + this.containerRef.removeEventListener("underflow", this.onUnderflow); + } + } + + render() { + return (
+
+ { this.props.children } +
+
); + } +} diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 7295fd45d3..d551a6fe27 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,14 @@ 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/CreateRoom.js b/src/components/structures/CreateRoom.js deleted file mode 100644 index a8aac71479..0000000000 --- a/src/components/structures/CreateRoom.js +++ /dev/null @@ -1,284 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -'use strict'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import { _t } from '../../languageHandler'; -import sdk from '../../index'; -import MatrixClientPeg from '../../MatrixClientPeg'; -const PresetValues = { - PrivateChat: "private_chat", - PublicChat: "public_chat", - Custom: "custom", -}; - -module.exports = React.createClass({ - displayName: 'CreateRoom', - - propTypes: { - onRoomCreated: PropTypes.func, - collapsedRhs: PropTypes.bool, - }, - - phases: { - CONFIG: "CONFIG", // We're waiting for user to configure and hit create. - CREATING: "CREATING", // We're sending the request. - CREATED: "CREATED", // We successfully created the room. - ERROR: "ERROR", // There was an error while trying to create room. - }, - - getDefaultProps: function() { - return { - onRoomCreated: function() {}, - }; - }, - - getInitialState: function() { - return { - phase: this.phases.CONFIG, - error_string: "", - is_private: true, - share_history: false, - default_preset: PresetValues.PrivateChat, - topic: '', - room_name: '', - invited_users: [], - }; - }, - - onCreateRoom: function() { - const options = {}; - - if (this.state.room_name) { - options.name = this.state.room_name; - } - - if (this.state.topic) { - options.topic = this.state.topic; - } - - if (this.state.preset) { - if (this.state.preset != PresetValues.Custom) { - options.preset = this.state.preset; - } else { - options.initial_state = [ - { - type: "m.room.join_rules", - content: { - "join_rule": this.state.is_private ? "invite" : "public", - }, - }, - { - type: "m.room.history_visibility", - content: { - "history_visibility": this.state.share_history ? "shared" : "invited", - }, - }, - ]; - } - } - - options.invite = this.state.invited_users; - - const alias = this.getAliasLocalpart(); - if (alias) { - options.room_alias_name = alias; - } - - const cli = MatrixClientPeg.get(); - if (!cli) { - // TODO: Error. - console.error("Cannot create room: No matrix client."); - return; - } - - const deferred = cli.createRoom(options); - - if (this.state.encrypt) { - // TODO - } - - this.setState({ - phase: this.phases.CREATING, - }); - - const self = this; - - deferred.then(function(resp) { - self.setState({ - phase: self.phases.CREATED, - }); - self.props.onRoomCreated(resp.room_id); - }, function(err) { - self.setState({ - phase: self.phases.ERROR, - error_string: err.toString(), - }); - }); - }, - - getPreset: function() { - return this.refs.presets.getPreset(); - }, - - getName: function() { - return this.refs.name_textbox.getName(); - }, - - getTopic: function() { - return this.refs.topic.getTopic(); - }, - - getAliasLocalpart: function() { - return this.refs.alias.getAliasLocalpart(); - }, - - getInvitedUsers: function() { - return this.refs.user_selector.getUserIds(); - }, - - onPresetChanged: function(preset) { - switch (preset) { - case PresetValues.PrivateChat: - this.setState({ - preset: preset, - is_private: true, - share_history: false, - }); - break; - case PresetValues.PublicChat: - this.setState({ - preset: preset, - is_private: false, - share_history: true, - }); - break; - case PresetValues.Custom: - this.setState({ - preset: preset, - }); - break; - } - }, - - onPrivateChanged: function(ev) { - this.setState({ - preset: PresetValues.Custom, - is_private: ev.target.checked, - }); - }, - - onShareHistoryChanged: function(ev) { - this.setState({ - preset: PresetValues.Custom, - share_history: ev.target.checked, - }); - }, - - onTopicChange: function(ev) { - this.setState({ - topic: ev.target.value, - }); - }, - - onNameChange: function(ev) { - this.setState({ - room_name: ev.target.value, - }); - }, - - onInviteChanged: function(invited_users) { - this.setState({ - invited_users: invited_users, - }); - }, - - onAliasChanged: function(alias) { - this.setState({ - alias: alias, - }); - }, - - onEncryptChanged: function(ev) { - this.setState({ - encrypt: ev.target.checked, - }); - }, - - render: function() { - const curr_phase = this.state.phase; - if (curr_phase == this.phases.CREATING) { - const Loader = sdk.getComponent("elements.Spinner"); - return ( - - ); - } else { - let error_box = ""; - if (curr_phase == this.phases.ERROR) { - error_box = ( -
- { _t('An error occurred: %(error_string)s', {error_string: this.state.error_string}) } -
- ); - } - - const CreateRoomButton = sdk.getComponent("create_room.CreateRoomButton"); - const RoomAlias = sdk.getComponent("create_room.RoomAlias"); - const Presets = sdk.getComponent("create_room.Presets"); - const UserSelector = sdk.getComponent("elements.UserSelector"); - const SimpleRoomHeader = sdk.getComponent("rooms.SimpleRoomHeader"); - - const domain = MatrixClientPeg.get().getDomain(); - - return ( -
- -
-
-