diff --git a/res/css/_common.scss b/res/css/_common.scss index aaefb859e4..4399fb224e 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -50,8 +50,54 @@ a:visited { color: $accent-color-alt; } +input[type=text], +input[type=search], +input[type=password] { + padding: 9px; + font-family: $font-family; + font-size: 14px; + font-weight: 600; + min-width: 0; +} + +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('$(res)/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; +} + +// Override Firefox's UA style so we get a consistent look across browsers +input::placeholder, +textarea::placeholder { + opacity: initial; +} + input[type=text], input[type=password], textarea { background-color: transparent; + color: $primary-fg-color; } input[type=text]:focus, input[type=password]:focus, textarea:focus { @@ -62,6 +108,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { /* Required by Firefox */ textarea { font-family: $font-family; + color: $primary-fg-color; } /* Prevent ugly dotted highlight around selected elements in Firefox */ @@ -242,7 +289,7 @@ textarea { font-weight: 600; border: 1px solid $accent-color ! important; color: $accent-color; - background-color: $accent-fg-color; + background-color: $button-secondary-bg-color; } .mx_Dialog button:hover, .mx_Dialog input[type="submit"]:hover { diff --git a/res/css/_components.scss b/res/css/_components.scss index dbf6e7b8b9..18c3597db0 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -7,6 +7,7 @@ @import "./structures/_CustomRoomTagPanel.scss"; @import "./structures/_FilePanel.scss"; @import "./structures/_GroupView.scss"; +@import "./structures/_HeaderButtons.scss"; @import "./structures/_HomePage.scss"; @import "./structures/_LeftPanel.scss"; @import "./structures/_MatrixChat.scss"; diff --git a/res/css/structures/_ContextualMenu.scss b/res/css/structures/_ContextualMenu.scss index 001c405e15..3788929bf3 100644 --- a/res/css/structures/_ContextualMenu.scss +++ b/res/css/structures/_ContextualMenu.scss @@ -31,7 +31,7 @@ limitations under the License. .mx_ContextualMenu { border-radius: 4px; - box-shadow: 4px 4px 12px 0 rgba(118, 131, 156, 0.6);; + box-shadow: 4px 4px 12px 0 $menu-box-shadow-color; background-color: $menu-bg-color; color: $primary-fg-color; position: absolute; diff --git a/res/css/structures/_GroupView.scss b/res/css/structures/_GroupView.scss index ace310ee5b..1c477a959a 100644 --- a/res/css/structures/_GroupView.scss +++ b/res/css/structures/_GroupView.scss @@ -44,13 +44,22 @@ limitations under the License. } .mx_GroupHeader_button { - margin-left: 12px; + margin-left: 5px; + margin-right: 5px; cursor: pointer; + height: 20px; + width: 20px; + background-color: $groupheader-button-color; + mask-repeat: no-repeat; + mask-size: contain; } -.mx_GroupHeader_button object { - // prevents clicks from being swallowed by svg in 'object' tag - pointer-events: none; +.mx_GroupHeader_editButton { + mask-image: url('$(res)/img/icons-settings-room.svg'); +} + +.mx_GroupHeader_shareButton { + mask-image: url('$(res)/img/icons-share.svg'); } .mx_GroupView_editable { diff --git a/res/css/structures/_HeaderButtons.scss b/res/css/structures/_HeaderButtons.scss new file mode 100644 index 0000000000..eef7653b24 --- /dev/null +++ b/res/css/structures/_HeaderButtons.scss @@ -0,0 +1,28 @@ +/* +Copyright 2019 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_HeaderButtons { + display: flex; +} + +.mx_HeaderButtons::before { + content: ""; + background-color: $header-divider-color; + opacity: 0.5; + margin: 0 15px; + border-radius: 1px; + width: 1px; +} diff --git a/res/css/structures/_RightPanel.scss b/res/css/structures/_RightPanel.scss index 592eea067e..474040a626 100644 --- a/res/css/structures/_RightPanel.scss +++ b/res/css/structures/_RightPanel.scss @@ -25,9 +25,7 @@ limitations under the License. .mx_RightPanel_header { order: 1; - border-bottom: 1px solid $primary-hairline-color; - flex: 0 0 52px; } @@ -45,20 +43,55 @@ limitations under the License. cursor: pointer; flex: 0 0 auto; vertical-align: top; - margin-top: 4px; - padding-left: 5px; - padding-right: 5px; + margin-left: 5px; + margin-right: 5px; text-align: center; - position: relative; border-bottom: 2px solid transparent; + height: 20px; + width: 20px; + position: relative; } -.mx_RightPanel_headerButton object { - pointer-events: none; +.mx_RightPanel_headerButton::before { + content: ''; + position: absolute; + top: 0; + left: 0; + height: 20px; + width: 20px; + background-color: $rightpanel-button-color; + mask-repeat: no-repeat; + mask-size: contain; } -.mx_RightPanel_headerButton_highlight { - border-color: $button-bg-color; +.mx_RightPanel_membersButton::before { + mask-image: url('$(res)/img/feather-icons/user.svg'); +} + +.mx_RightPanel_filesButton::before { + mask-image: url('$(res)/img/feather-icons/files.svg'); +} + +.mx_RightPanel_notifsButton::before { + mask-image: url('$(res)/img/feather-icons/notifications.svg'); +} + +.mx_RightPanel_groupMembersButton::before { + mask-image: url('$(res)/img/icons-people.svg'); +} + +.mx_RightPanel_roomsButton::before { + mask-image: url('$(res)/img/icons-room-nobg.svg'); +} + +.mx_RightPanel_headerButton_highlight::after { + content: ''; + position: absolute; + bottom: -6px; + left: 0; + right: 0; + height: 2px; + background-color: $button-bg-color; } .mx_RightPanel_headerButton_badge { diff --git a/res/css/structures/_RoomSubList.scss b/res/css/structures/_RoomSubList.scss index 9791be902f..f76df1f683 100644 --- a/res/css/structures/_RoomSubList.scss +++ b/res/css/structures/_RoomSubList.scss @@ -152,7 +152,7 @@ limitations under the License. &.mx_IndicatorScrollbar_topOverflow::before { top: 0; transition: background-image 0.1s ease-in; - background: linear-gradient(to top, rgba(242,245,248,0), rgba(242,245,248,1)); + background: linear-gradient(to top, $panel-gradient); } /* diff --git a/res/css/structures/_TagPanelButtons.scss b/res/css/structures/_TagPanelButtons.scss index f7cb189e25..323d77a405 100644 --- a/res/css/structures/_TagPanelButtons.scss +++ b/res/css/structures/_TagPanelButtons.scss @@ -38,7 +38,7 @@ limitations under the License. height: 40px; width: 40px; border-radius: 20px; - background-color: $roomheader-addroom-color; + background-color: $tagpanel-button-color; position: relative; /* overwrite mx_RoleButton inline-block */ display: block !important; diff --git a/res/css/structures/auth/_Login.scss b/res/css/structures/auth/_Login.scss index b48021c27a..d4b5e7402c 100644 --- a/res/css/structures/auth/_Login.scss +++ b/res/css/structures/auth/_Login.scss @@ -79,7 +79,7 @@ limitations under the License. .mx_Login_type_container { display: flex; margin-bottom: 14px; - color: $primary-fg-color; + color: $authpage-primary-color; } .mx_Login_type_label { diff --git a/res/css/views/auth/_AuthBody.scss b/res/css/views/auth/_AuthBody.scss index fd54cd135a..6216bdd4b8 100644 --- a/res/css/views/auth/_AuthBody.scss +++ b/res/css/views/auth/_AuthBody.scss @@ -21,19 +21,41 @@ limitations under the License. padding: 25px 60px; box-sizing: border-box; font-size: 12px; - color: $authpage-body-color; + color: $authpage-secondary-color; } .mx_AuthBody h2 { font-size: 24px; font-weight: 600; margin-top: 8px; + color: $authpage-primary-color; } .mx_AuthBody h3 { font-size: 14px; font-weight: 600; - color: $primary-fg-color; + color: $authpage-primary-color; +} + +.mx_AuthBody input[type=text], +.mx_AuthBody input[type=password] { + color: $authpage-primary-color; +} + +.mx_AuthBody .mx_Field input, +.mx_AuthBody .mx_Field select { + color: $authpage-primary-color; + background-color: $authpage-body-bg-color; +} + +.mx_AuthBody .mx_Field label { + color: $authpage-primary-color; +} + +.mx_AuthBody .mx_Field input:focus + label, +.mx_AuthBody .mx_Field input:not(:placeholder-shown) + label, +.mx_AuthBody .mx_Field select + label /* Always show a select's label on top to not collide with the value */ { + background-color: $authpage-body-bg-color; } .mx_AuthBody_editServerDetails { diff --git a/res/css/views/auth/_ServerTypeSelector.scss b/res/css/views/auth/_ServerTypeSelector.scss index 03f5386501..ed781726b7 100644 --- a/res/css/views/auth/_ServerTypeSelector.scss +++ b/res/css/views/auth/_ServerTypeSelector.scss @@ -34,7 +34,7 @@ limitations under the License. .mx_ServerTypeSelector_label { text-align: center; font-weight: 600; - color: $primary-fg-color; + color: $authpage-primary-color; margin: 8px 0; } @@ -54,7 +54,7 @@ limitations under the License. height: 18px; margin-bottom: 12px; font-weight: 600; - color: $primary-fg-color; + color: $authpage-primary-color; } .mx_ServerTypeSelector_logo > div { diff --git a/res/css/views/context_menus/_TopLeftMenu.scss b/res/css/views/context_menus/_TopLeftMenu.scss index f305f0fae3..b3ef703144 100644 --- a/res/css/views/context_menus/_TopLeftMenu.scss +++ b/res/css/views/context_menus/_TopLeftMenu.scss @@ -31,10 +31,18 @@ limitations under the License. mask-image: url('$(res)/img/feather-icons/home.svg'); } + li.mx_TopLeftMenu_icon_welcome::after { + mask-image: url('$(res)/img/feather-icons/gift.svg'); + } + li.mx_TopLeftMenu_icon_settings::after { mask-image: url('$(res)/img/feather-icons/settings.svg'); } + li.mx_TopLeftMenu_icon_signin::after { + mask-image: url('$(res)/img/feather-icons/sign-in.svg'); + } + li.mx_TopLeftMenu_icon_signout::after { mask-image: url('$(res)/img/feather-icons/sign-out.svg'); } diff --git a/res/css/views/dialogs/_CreateGroupDialog.scss b/res/css/views/dialogs/_CreateGroupDialog.scss index 500e12ee49..128eacc3ce 100644 --- a/res/css/views/dialogs/_CreateGroupDialog.scss +++ b/res/css/views/dialogs/_CreateGroupDialog.scss @@ -43,10 +43,9 @@ limitations under the License. .mx_CreateGroupDialog_prefix, .mx_CreateGroupDialog_suffix { - height: 35px; padding: 0px 5px; line-height: 37px; - background-color: $input-border-color; + background-color: $input-darker-bg-color; border: 1px solid $input-border-color; text-align: center; } diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index 8de0b82554..25ad51a3fb 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -40,8 +40,7 @@ limitations under the License. } .mx_AccessibleButton_kind_primary.mx_AccessibleButton_disabled { - color: $button-primary-disabled-fg-color; - background-color: $button-primary-disabled-bg-color; + opacity: 0.4; } .mx_AccessibleButton_hasKind.mx_AccessibleButton_kind_primary_sm { @@ -51,8 +50,7 @@ limitations under the License. } .mx_AccessibleButton_kind_primary_sm.mx_AccessibleButton_disabled { - color: $button-primary-disabled-fg-color; - background-color: $button-primary-disabled-bg-color; + opacity: 0.4; } .mx_AccessibleButton_kind_danger { @@ -74,4 +72,4 @@ limitations under the License. .mx_AccessibleButton_kind_danger_sm.mx_AccessibleButton_disabled { color: $button-danger-disabled-fg-color; background-color: $button-danger-disabled-bg-color; -} \ No newline at end of file +} diff --git a/res/css/views/elements/_Field.scss b/res/css/views/elements/_Field.scss index 6ce6b33a05..075bd28a11 100644 --- a/res/css/views/elements/_Field.scss +++ b/res/css/views/elements/_Field.scss @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* TODO: Consider unifying with general input styles in _dharma.scss */ +/* TODO: Consider unifying with general input styles in _light.scss */ .mx_Field { position: relative; @@ -31,6 +31,7 @@ limitations under the License. transition: border-color 0.25s; border: 1px solid $input-border-color; padding: 8px 9px; + color: $primary-fg-color; background-color: $primary-bg-color; } diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index 7ee7efcaff..db8eb4995d 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -180,27 +180,36 @@ limitations under the License. color: $accent-color; } -.mx_MessageComposer_upload, -.mx_MessageComposer_hangup, -.mx_MessageComposer_voicecall, -.mx_MessageComposer_videocall, -.mx_MessageComposer_apps, -.mx_MessageComposer_stickers { - /*display: table-cell;*/ - /*vertical-align: middle;*/ - /*padding-left: 10px;*/ - padding-right: 12px; +.mx_MessageComposer_button { + margin-right: 12px; cursor: pointer; padding-top: 4px; + height: 20px; + width: 20px; + background-color: $composer-button-color; + mask-repeat: no-repeat; + mask-size: contain; + mask-position: center; } -.mx_MessageComposer_upload object, -.mx_MessageComposer_hangup object, -.mx_MessageComposer_voicecall object, -.mx_MessageComposer_videocall object, -.mx_MessageComposer_apps object, -.mx_MessageComposer_stickers object { - pointer-events: none; +.mx_MessageComposer_upload { + mask-image: url('$(res)/img/feather-icons/paperclip.svg'); +} + +.mx_MessageComposer_hangup { + mask-image: url('$(res)/img/hangup.svg'); +} + +.mx_MessageComposer_voicecall { + mask-image: url('$(res)/img/feather-icons/phone.svg'); +} + +.mx_MessageComposer_videocall { + mask-image: url('$(res)/img/feather-icons/video.svg'); +} + +.mx_MessageComposer_stickers { + mask-image: url('$(res)/img/feather-icons/face.svg'); } .mx_MessageComposer_formatting { diff --git a/res/css/views/rooms/_RoomBreadcrumbs.scss b/res/css/views/rooms/_RoomBreadcrumbs.scss index ba4aec3b6e..c5a149d5cd 100644 --- a/res/css/views/rooms/_RoomBreadcrumbs.scss +++ b/res/css/views/rooms/_RoomBreadcrumbs.scss @@ -36,7 +36,7 @@ limitations under the License. top: 0; right: 0; height: 100%; - background: linear-gradient(to right, rgba(242,245,248,0), rgba(242,245,248,1)); + background: linear-gradient(to right, $panel-gradient); } .mx_RoomBreadcrumbs_animate { diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 1359bc5f57..93f984e65b 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -58,7 +58,6 @@ limitations under the License. .mx_RoomHeader_buttons { display: flex; - align-items: center; background-color: $primary-bg-color; padding-right: 5px; } @@ -116,10 +115,6 @@ limitations under the License. opacity: 0.6; } -.mx_RoomHeader_settingsButton object { - pointer-events: none; -} - .mx_RoomHeader_name, .mx_RoomHeader_avatar, .mx_RoomHeader_avatarPicker, @@ -160,6 +155,7 @@ limitations under the License. font-weight: 400; font-size: 13px; margin: 0 7px; + margin-top: 4px; // to align baseline of topic with room name overflow: hidden; text-overflow: ellipsis; border-bottom: 1px solid transparent; @@ -199,10 +195,32 @@ limitations under the License. .mx_RoomHeader_button { margin-left: 10px; cursor: pointer; + height: 20px; + width: 20px; + background-color: $roomheader-button-color; + mask-repeat: no-repeat; + mask-size: contain; } -.mx_RoomHeader_button object { - pointer-events: none; +.mx_RoomHeader_settingsButton { + mask-image: url('$(res)/img/feather-icons/settings.svg'); +} + +.mx_RoomHeader_forgetButton { + mask-image: url('$(res)/img/leave.svg'); + width: 26px; +} + +.mx_RoomHeader_searchButton { + mask-image: url('$(res)/img/feather-icons/search.svg'); +} + +.mx_RoomHeader_shareButton { + mask-image: url('$(res)/img/feather-icons/share.svg'); +} + +.mx_RoomHeader_manageIntegsButton { + mask-image: url('$(res)/img/feather-icons/grid.svg'); } .mx_RoomHeader_showPanel { @@ -219,6 +237,7 @@ limitations under the License. .mx_RoomHeader_pinnedButton { position: relative; + mask-image: url('$(res)/img/icons-pin.svg'); } .mx_RoomHeader_pinsIndicator { diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index 2024a503ae..6b2e2573e5 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -154,9 +154,8 @@ limitations under the License. } .mx_RoomTile_unread, .mx_RoomTile_highlight { - font-weight: 700 !important; - .mx_RoomTile_name { + // font-weight: 700; // bold is too loud in the end color: $roomtile-selected-color; } } diff --git a/res/img/feather-icons/e2e/blacklisted.svg b/res/img/feather-icons/e2e/blacklisted.svg index 63897c2227..ac99d23f05 100644 --- a/res/img/feather-icons/e2e/blacklisted.svg +++ b/res/img/feather-icons/e2e/blacklisted.svg @@ -2,5 +2,5 @@ - + diff --git a/res/img/feather-icons/e2e/verified.svg b/res/img/feather-icons/e2e/verified.svg index f143f854e6..459a552a40 100644 --- a/res/img/feather-icons/e2e/verified.svg +++ b/res/img/feather-icons/e2e/verified.svg @@ -1,3 +1,3 @@ - + diff --git a/res/img/feather-icons/e2e/warning.svg b/res/img/feather-icons/e2e/warning.svg index e6c246dba9..3d5fba550c 100644 --- a/res/img/feather-icons/e2e/warning.svg +++ b/res/img/feather-icons/e2e/warning.svg @@ -2,5 +2,5 @@ - + diff --git a/res/img/feather-icons/face.svg b/res/img/feather-icons/face.svg index 0a359b2dea..a8ca856b67 100644 --- a/res/img/feather-icons/face.svg +++ b/res/img/feather-icons/face.svg @@ -3,9 +3,9 @@ - - - + + + diff --git a/res/img/feather-icons/files.svg b/res/img/feather-icons/files.svg index c66d9ad121..e3bfe30ab0 100644 --- a/res/img/feather-icons/files.svg +++ b/res/img/feather-icons/files.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/gift.svg b/res/img/feather-icons/gift.svg new file mode 100644 index 0000000000..c225b50f9d --- /dev/null +++ b/res/img/feather-icons/gift.svg @@ -0,0 +1 @@ + diff --git a/res/img/feather-icons/grid.svg b/res/img/feather-icons/grid.svg index e6912b0cc7..4f7ab30d97 100644 --- a/res/img/feather-icons/grid.svg +++ b/res/img/feather-icons/grid.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/life-buoy.svg b/res/img/feather-icons/life-buoy.svg index 20bd0f0b5d..6318f7df9a 100644 --- a/res/img/feather-icons/life-buoy.svg +++ b/res/img/feather-icons/life-buoy.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/notifications.svg b/res/img/feather-icons/notifications.svg index 2fe85e810c..a590031ac3 100644 --- a/res/img/feather-icons/notifications.svg +++ b/res/img/feather-icons/notifications.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/paperclip.svg b/res/img/feather-icons/paperclip.svg index ed2bb88681..74a90e0fa3 100644 --- a/res/img/feather-icons/paperclip.svg +++ b/res/img/feather-icons/paperclip.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/phone.svg b/res/img/feather-icons/phone.svg index 58b257f113..85661c5320 100644 --- a/res/img/feather-icons/phone.svg +++ b/res/img/feather-icons/phone.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/search-input.svg b/res/img/feather-icons/search-input.svg index 3be5acb32e..028b84d559 100644 --- a/res/img/feather-icons/search-input.svg +++ b/res/img/feather-icons/search-input.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/search.svg b/res/img/feather-icons/search.svg index 8b14246f64..9ce0724ea7 100644 --- a/res/img/feather-icons/search.svg +++ b/res/img/feather-icons/search.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/settings.svg b/res/img/feather-icons/settings.svg index ea7ce5c55b..a65a15a75f 100644 --- a/res/img/feather-icons/settings.svg +++ b/res/img/feather-icons/settings.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/share.svg b/res/img/feather-icons/share.svg index a012e1b7a5..7098af58aa 100644 --- a/res/img/feather-icons/share.svg +++ b/res/img/feather-icons/share.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/sign-in.svg b/res/img/feather-icons/sign-in.svg new file mode 100644 index 0000000000..9fe617eee1 --- /dev/null +++ b/res/img/feather-icons/sign-in.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/res/img/feather-icons/sign-out.svg b/res/img/feather-icons/sign-out.svg index 06ab9903ec..172eb98afb 100644 --- a/res/img/feather-icons/sign-out.svg +++ b/res/img/feather-icons/sign-out.svg @@ -1,5 +1,5 @@ - + diff --git a/res/img/feather-icons/upload.svg b/res/img/feather-icons/upload.svg index 8ec5d95c2c..30c89d3819 100644 --- a/res/img/feather-icons/upload.svg +++ b/res/img/feather-icons/upload.svg @@ -1,5 +1,5 @@ - + diff --git a/res/img/feather-icons/user-add.svg b/res/img/feather-icons/user-add.svg index cbb25934c1..6b5210c1d6 100644 --- a/res/img/feather-icons/user-add.svg +++ b/res/img/feather-icons/user-add.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/user.svg b/res/img/feather-icons/user.svg index a789e580d5..210ef99e6a 100644 --- a/res/img/feather-icons/user.svg +++ b/res/img/feather-icons/user.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/users.svg b/res/img/feather-icons/users.svg index b0deac0a9e..b90aafdd4a 100644 --- a/res/img/feather-icons/users.svg +++ b/res/img/feather-icons/users.svg @@ -1,7 +1,7 @@ - + diff --git a/res/img/feather-icons/video.svg b/res/img/feather-icons/video.svg index a4c456832f..da77b6c57a 100644 --- a/res/img/feather-icons/video.svg +++ b/res/img/feather-icons/video.svg @@ -1,7 +1,7 @@ - + diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index ee5e1cf5d6..c0d0f15613 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -1,186 +1,196 @@ +// unified palette +// try to use these colors when possible +$bg-color: #181b21; +$base-color: #1b1f25; +$base-text-color: #edf3ff; +$header-panel-bg-color: #22262e; +$header-panel-border-color: #000000; +$header-panel-text-primary-color: #a1b2d1; +$header-panel-text-secondary-color: #c8c8cd; +$text-primary-color: #edf3ff; +$text-secondary-color: #a1b2d1; +$search-bg-color: #181b21; +$search-placeholder-color: #61708b; +$room-highlight-color: #343a46; // typical text (dark-on-white in light skin) -$primary-fg-color: #212121; -$primary-bg-color: #2d2d2d; - -// used for focusing form controls -$focus-bg-color: #101010; +$primary-fg-color: $text-primary-color; +$primary-bg-color: $bg-color; // used for dialog box text -$light-fg-color: #747474; +$light-fg-color: $header-panel-text-secondary-color; -// 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; +// used for focusing form controls +$focus-bg-color: $room-highlight-color; -$selection-fg-color: $primary-fg-color; +$mention-user-pill-bg-color: $warning-color; +$other-user-pill-bg-color: $room-highlight-color; -$focus-brightness: 200%; +// informational plinth +$info-plinth-bg-color: $header-panel-bg-color; +$info-plinth-fg-color: #888; -// red warning colour -$warning-color: #ff0064; -$warning-bg-color: #DF2A8B; -$info-bg-color: #2A9EDF; +$preview-bar-bg-color: $header-panel-bg-color; -// groups -$info-plinth-bg-color: #454545; - -$other-user-pill-bg-color: rgba(255, 255, 255, 0.1); - -$preview-bar-bg-color: #333; - -// left-panel style muted accent color -$secondary-accent-color: $primary-bg-color; -$tertiary-accent-color: #454545; - -// stop the tinter trying to change the secondary accent color -// by overriding the key to something untintable -// XXX: this is a bit of a hack. -#mx_theme_secondaryAccentColor { - color: #c0ffee ! important; -} - -#mx_theme_tertiaryAccentColor { - color: #c0ffee ! important; -} - -// used by RoomDirectory permissions -$plinth-bg-color: #474747; - -// used by RoomDropTarget -$droptarget-bg-color: rgba(45,45,45,0.5); +$tagpanel-bg-color: $base-color; // used by AddressSelector -$selected-color: #000000; +$selected-color: $room-highlight-color; // selected for hoverover & selected event tiles -$event-selected-color: #353535; +$event-selected-color: $search-bg-color; // used for the hairline dividers in RoomView -$primary-hairline-color: #474747; +$primary-hairline-color: $header-panel-border-color; // used for the border of input text fields -$input-border-color: #3a3a3a; +$input-border-color: #e7e7e7; +$input-darker-bg-color: $search-bg-color; +$input-darker-fg-color: $search-placeholder-color; +$input-lighter-bg-color: #f2f5f8; +$input-lighter-fg-color: $input-darker-fg-color; +$input-focused-border-color: #238cf5; +$input-valid-border-color: $accent-color; -$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; +$field-focused-label-bg-color: $bg-color; -// used for UserSettings EditableText -$input-underline-color: $primary-fg-color; -$input-fg-color: $primary-fg-color; // scrollbars $scrollbar-thumb-color: rgba(255, 255, 255, 0.2); $scrollbar-track-color: transparent; + // context menus -$menu-border-color: rgba(187, 187, 187, 0.5); -$menu-bg-color: #373737; -$menu-selected-color: #f5f8fa; +$menu-border-color: $header-panel-border-color; +$menu-bg-color: $header-panel-bg-color; +$menu-box-shadow-color: $bg-color; +$menu-selected-color: $room-highlight-color; -$avatar-initial-color: #2d2d2d; -$avatar-bg-color: #ffffff; -$menu-selected-color: #f5f8fa; +$avatar-initial-color: #ffffff; +$avatar-bg-color: $bg-color; -$h3-color: $primary-fg-color; - -$dialog-background-bg-color: #000; +$dialog-background-bg-color: $header-panel-bg-color; $lightbox-background-bg-color: #000; -$greyed-fg-color: #888; - -$neutral-badge-color: #888; - -$preview-widget-bar-color: $menu-bg-color; -$preview-widget-fg-color: $greyed-fg-color; - -$blockquote-bar-color: #ddd; -$blockquote-fg-color: #777; - $settings-grey-fg-color: #a2a2a2; +$settings-profile-placeholder-bg-color: #e7e7e7; +$settings-profile-overlay-bg-color: #000; +$settings-profile-overlay-placeholder-bg-color: transparent; +$settings-profile-overlay-fg-color: #fff; +$settings-profile-overlay-placeholder-fg-color: #454545; +$settings-subsection-fg-color: $text-secondary-color; -$voip-decline-color: #f48080; -$voip-accept-color: #80f480; +$topleftmenu-color: $text-primary-color; +$roomheader-color: $text-primary-color; +$roomheader-addroom-color: $header-panel-text-primary-color; +$tagpanel-button-color: $header-panel-text-primary-color; +$roomheader-button-color: $header-panel-text-primary-color; +$groupheader-button-color: $header-panel-text-primary-color; +$rightpanel-button-color: $header-panel-text-primary-color; +$composer-button-color: $header-panel-text-primary-color; +$roomtopic-color: $text-secondary-color; +$eventtile-meta-color: $roomtopic-color; -$rte-bg-color: #353535; -$rte-code-bg-color: #000; +$header-divider-color: $header-panel-text-primary-color; -$room-warning-bg-color: #2d2d2d; +$roomtile-name-color: $header-panel-text-primary-color; +$roomtile-selected-color: $text-primary-color; +$roomtile-notified-color: $text-primary-color; +$roomtile-selected-bg-color: $room-highlight-color; +$roomtile-focused-bg-color: $room-highlight-color; -// ******************** +$roomtile-transparent-focused-color: rgba(0, 0, 0, 0.1); -$roomtile-name-color: rgba(186, 186, 186, 0.8); -$roomtile-selected-bg-color: #333; -$roomtile-focused-bg-color: rgba(255, 255, 255, 0.2); +$panel-divider-color: $header-panel-border-color; -$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; -$roomsublist-chevron-color: $accent-color; - -$panel-divider-color: rgba(118, 207, 166, 0.2); - -// ******************** - -$widget-menu-bar-bg-color: $tertiary-accent-color; - -// ******************** - -// event tile lifecycle -$event-encrypting-color: rgba(171, 221, 188, 0.4); -$event-sending-color: #888; -$event-notsent-color: #f44; - -// event redaction -$event-redacted-fg-color: #606060; -$event-redacted-border-color: #000000; +$widget-menu-bar-bg-color: $search-bg-color; // event timestamp -$event-timestamp-color: #acacac; +$event-timestamp-color: $text-secondary-color; -$edit-button-url: "$(res)/img/icon_context_message_dark.svg"; -$copy-button-url: "$(res)/img/icon_copy_message_dark.svg"; +// Tabbed views +$tab-label-fg-color: $text-primary-color; +$tab-label-active-fg-color: $text-primary-color; +$tab-label-bg-color: transparent; +$tab-label-active-bg-color: $accent-color; +$tab-label-icon-bg-color: $text-primary-color; +$tab-label-active-icon-bg-color: $text-primary-color; -// e2e -$e2e-verified-color: #76cfa5; // N.B. *NOT* the same as $accent-color -$e2e-unverified-color: #e8bf37; -$e2e-warning-color: #ba6363; +// Buttons +$button-primary-fg-color: #ffffff; +$button-primary-bg-color: $accent-color; +$button-secondary-bg-color: transparent; +$button-danger-fg-color: #ffffff; +$button-danger-bg-color: $notice-primary-color; +$button-danger-disabled-fg-color: #ffffff; +$button-danger-disabled-bg-color: #f5b6bb; // TODO: Verify color -/*** ImageView ***/ -$lightbox-bg-color: #454545; -$lightbox-fg-color: #ffffff; -$lightbox-border-color: #ffffff; +$room-warning-bg-color: $header-panel-bg-color; -$imagebody-giflabel: rgba(1, 1, 1, 0.7); -$imagebody-giflabel-border: rgba(1, 1, 1, 0.2); -$imagebody-giflabel-color: rgba(0, 0, 0, 1); +$panel-gradient: rgba(34, 38, 46, 0), rgba(34, 38, 46, 1); -// 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_Dialog, .mx_MatrixChat { + + :not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=text], + :not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=search], + .mx_textinput { + background-color: transparent; + color: $input-darker-fg-color; + border: 1px solid #c1c1c1; + } + + .mx_textinput { + > input[type=text], + > input[type=search] { + color: $primary-fg-color; + } + input::placeholder { + color: $roomsublist-label-fg-color; + } + } +} + +/*** panels ***/ +.dark-panel { + background-color: $header-panel-bg-color; +} + +.dark-panel { + :not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=text], + :not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=search], + .mx_textinput { + color: $input-darker-fg-color; + background-color: $input-darker-bg-color; + border: none; + } +} + +.light-panel { + :not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=text], + :not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=search], + .mx_textinput { + color: $input-lighter-fg-color; + background-color: $input-lighter-bg-color; + border: none; + } +} + +// ***** Mixins! ***** -// XXX: copypasted from _base in order to pick up the right FG color... @define-mixin mx_DialogButton { /* align images in buttons (eg spinners) */ vertical-align: middle; border: 0px; - border-radius: 36px; + border-radius: 4px; font-family: $font-family; font-size: 14px; - color: $accent-fg-color; - background-color: $accent-color; + color: $button-fg-color; + background-color: $button-bg-color; width: auto; padding: 7px; padding-left: 1.5em; @@ -190,12 +200,16 @@ $progressbar-color: #000; outline: none; } +@define-mixin mx_DialogButton_danger { + background-color: $accent-color; +} + @define-mixin mx_DialogButton_secondary { // flip colours for the secondary ones font-weight: 600; border: 1px solid $accent-color ! important; color: $accent-color; - background-color: $accent-fg-color; + background-color: $button-secondary-bg-color; } // Nasty hacks to apply a filter to arbitrary monochrome artwork to make it @@ -232,8 +246,3 @@ $progressbar-color: #000; } } } - -// Add a line to the right side of the left panel to distinguish it from the middle panel -.mx_LeftPanel { - border-right: 1px solid $tertiary-accent-color; -} diff --git a/res/themes/dark/css/dark.scss b/res/themes/dark/css/dark.scss index a7d18fa1a6..e7ae7c8cf8 100644 --- a/res/themes/dark/css/dark.scss +++ b/res/themes/dark/css/dark.scss @@ -1,5 +1,5 @@ @import "../../light/css/_paths.scss"; @import "../../light/css/_fonts.scss"; -@import "../../light/css/_base.scss"; +@import "../../light/css/_light.scss"; @import "_dark.scss"; @import "../../../../res/css/_components.scss"; diff --git a/res/themes/dharma/css/_fonts.scss b/res/themes/dharma/css/_fonts.scss deleted file mode 100644 index ac15847e44..0000000000 --- a/res/themes/dharma/css/_fonts.scss +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Nunito. - * Includes extended Latin and Vietnamese character sets - * Current URLs are taken from - * https://github.com/alexeiva/NunitoFont/releases/tag/v3.500 - * ...in order to include cyrillic. - * - * Previously, they were - * https://fonts.googleapis.com/css?family=Nunito:400,400i,600,600i,700,700i&subset=latin-ext,vietnamese - * - * We explicitly do not include Nunito's italic variants, as they are not italic enough - * and it's better to rely on the browser's built-in obliquing behaviour. - */ - -/* the 'src' links are relative to the bundle.css, which is in a subdirectory. - */ -@font-face { - font-family: 'Nunito'; - font-style: normal; - font-weight: 400; - src: url('$(res)/fonts/Nunito/Nunito-Regular.ttf') format('truetype'); -} -@font-face { - font-family: 'Nunito'; - font-style: normal; - font-weight: 600; - src: url('$(res)/fonts/Nunito/Nunito-SemiBold.ttf') format('truetype'); -} -@font-face { - font-family: 'Nunito'; - font-style: normal; - font-weight: 700; - src: url('$(res)/fonts/Nunito/Nunito-Bold.ttf') format('truetype'); -} - -/* - * Fira Mono - * Used for monospace copy, i.e. code - */ - -@font-face { - font-family: 'Fira Mono'; - src: url('$(res)/fonts/Fira_Mono/FiraMono-Regular.ttf') format('truetype'); - font-weight: 400; - font-style: normal; -} - -@font-face { - font-family: 'Fira Mono'; - src: url('$(res)/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 deleted file mode 100644 index 24dc0ce18d..0000000000 --- a/res/themes/dharma/css/dharma.scss +++ /dev/null @@ -1,4 +0,0 @@ -@import "../../light/css/_paths.scss"; -@import "_fonts.scss"; -@import "_dharma.scss"; -@import "../../../../res/css/_components.scss"; diff --git a/res/themes/light/css/_base.scss b/res/themes/light/css/_base.scss deleted file mode 100644 index 8185ba0ace..0000000000 --- a/res/themes/light/css/_base.scss +++ /dev/null @@ -1,276 +0,0 @@ -/* 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 - horizontal mess. Arial empirically gets it right, hence prioritising - Arial here. */ -$font-family: 'Open Sans', 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: #76CFA6; -$accent-color-alt: $accent-color; -$accent-color-50pct: #76CFA67F; - -$selection-fg-color: $primary-bg-color; - -$focus-brightness: 125%; - -// red warning colour -$warning-color: #ff0064; -// background colour for warnings -$warning-bg-color: #DF2A8B; -$info-bg-color: #2A9EDF; -$mention-user-pill-bg-color: #ff0064; -$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: #eaf5f0; -$tertiary-accent-color: #d3efe1; - -$tagpanel-bg-color: $tertiary-accent-color; - -// 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-border-dark-color: #b8b8b8; - -$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; -$input-focused-border-color: #238cf5; -$input-valid-border-color: #7ac9a1; - -$field-focused-label-bg-color: #ffffff; - -// used for UserSettings EditableText -$input-underline-color: rgba(151, 151, 151, 0.5); -$input-fg-color: rgba(74, 74, 74, 0.9); -// scrollbars -$scrollbar-thumb-color: rgba(0, 0, 0, 0.2); -$scrollbar-track-color: transparent; -// 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; - -$h3-color: #3d3b39; - -$dialog-title-fg-color: #454545; -$dialog-backdrop-color: rgba(46, 48, 51, 0.38); -$dialog-shadow-color: rgba(0, 0, 0, 0.48); -$dialog-close-fg-color: #9fa9ba; - -$dialog-background-bg-color: #e9e9e9; -$lightbox-background-bg-color: #000; - -$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; -$settings-profile-placeholder-bg-color: #e7e7e7; -$settings-profile-overlay-bg-color: #000; -$settings-profile-overlay-placeholder-bg-color: transparent; -$settings-profile-overlay-fg-color: #fff; -$settings-profile-overlay-placeholder-fg-color: #454545; -$settings-subsection-fg-color: #61708b; - -$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: $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; - -$composer-e2e-icon-color: #c9ced6; - -// ******************** - -$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); -$roomsublist-label-fg-color: $h3-color; -$roomsublist-label-bg-color: $tertiary-accent-color; -$roomsublist-chevron-color: $accent-color; - -$panel-divider-color: rgba(118, 207, 166, 0.2); - -// ******************** - -$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: "$(res)/img/icon_context_message.svg"; -$copy-button-url: "$(res)/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; - -$imagebody-giflabel: rgba(0, 0, 0, 0.7); -$imagebody-giflabel-border: rgba(0, 0, 0, 0.2); -$imagebody-giflabel-color: rgba(255, 255, 255, 1); - -// Tabbed views -$tab-label-fg-color: #45474a; -$tab-label-active-fg-color: #ffffff; -$tab-label-bg-color: transparent; -$tab-label-active-bg-color: #7ac9a1; -$tab-label-icon-bg-color: #454545; -$tab-label-active-icon-bg-color: #ffffff; - -// Buttons -$button-primary-fg-color: #ffffff; -$button-primary-bg-color: #7ac9a1; -$button-primary-disabled-fg-color: #ffffff; -$button-primary-disabled-bg-color: #bce4d0; -$button-danger-fg-color: #ffffff; -$button-danger-bg-color: #f56679; -$button-danger-disabled-fg-color: #ffffff; -$button-danger-disabled-bg-color: #f5b6bb; // TODO: Verify color - -// Toggle switch -$togglesw-off-color: #c1c9d6; -$togglesw-on-color: #7ac9a1; -$togglesw-ball-color: #fff; - -// unused? -$progressbar-color: #000; - -$room-warning-bg-color: #fff8e3; - -$memberstatus-placeholder-color: $roomtile-name-color; - -$authpage-bg-color: #2e3649; -$authpage-modal-bg-color: rgba(255, 255, 255, 0.59); -$authpage-body-bg-color: #ffffff; -$authpage-lang-color: #4e5054; -$authpage-body-color: #61708b; - -// ***** Mixins! ***** - -@define-mixin mx_DialogButton { - /* align images in buttons (eg spinners) */ - vertical-align: middle; - border: 0px; - border-radius: 36px; - font-family: $font-family; - font-size: 14px; - color: $accent-fg-color; - background-color: $accent-color; - width: auto; - padding: 7px; - padding-left: 1.5em; - padding-right: 1.5em; - cursor: pointer; - display: inline-block; - outline: none; -} - -@define-mixin mx_DialogButton_danger { - background-color: $warning-color; -} - -@define-mixin mx_DialogButton_hover { -} - -@define-mixin mx_DialogButton_small { - @mixin mx_DialogButton; - font-size: 15px; - padding: 0px 1.5em 0px 1.5em; -} - -@define-mixin mx_DialogButton_secondary { - // flip colours for the secondary ones - font-weight: 600; - border: 1px solid $accent-color ! important; - color: $accent-color; - background-color: $accent-fg-color; -} diff --git a/res/themes/light/css/_fonts.scss b/res/themes/light/css/_fonts.scss index c080663acf..ac15847e44 100644 --- a/res/themes/light/css/_fonts.scss +++ b/res/themes/light/css/_fonts.scss @@ -1,50 +1,36 @@ /* - * Open Sans - * Includes extended Latin, Greek, Cyrillic and Vietnamese character sets + * Nunito. + * Includes extended Latin and Vietnamese character sets + * Current URLs are taken from + * https://github.com/alexeiva/NunitoFont/releases/tag/v3.500 + * ...in order to include cyrillic. + * + * Previously, they were + * https://fonts.googleapis.com/css?family=Nunito:400,400i,600,600i,700,700i&subset=latin-ext,vietnamese + * + * We explicitly do not include Nunito's italic variants, as they are not italic enough + * and it's better to rely on the browser's built-in obliquing behaviour. */ /* the 'src' links are relative to the bundle.css, which is in a subdirectory. */ @font-face { - font-family: 'Open Sans'; - src: url('$(res)/fonts/Open_Sans/OpenSans-Regular.ttf') format('truetype'); - font-weight: 400; - font-style: normal; + font-family: 'Nunito'; + font-style: normal; + font-weight: 400; + src: url('$(res)/fonts/Nunito/Nunito-Regular.ttf') format('truetype'); } - @font-face { - font-family: 'Open Sans'; - src: url('$(res)/fonts/Open_Sans/OpenSans-Italic.ttf') format('truetype'); - font-weight: 400; - font-style: italic; + font-family: 'Nunito'; + font-style: normal; + font-weight: 600; + src: url('$(res)/fonts/Nunito/Nunito-SemiBold.ttf') format('truetype'); } - @font-face { - font-family: 'Open Sans'; - src: url('$(res)/fonts/Open_Sans/OpenSans-Semibold.ttf') format('truetype'); - font-weight: 600; - font-style: normal; -} - -@font-face { - font-family: 'Open Sans'; - src: url('$(res)/fonts/Open_Sans/OpenSans-SemiboldItalic.ttf') format('truetype'); - font-weight: 600; - font-style: italic; -} - -@font-face { - font-family: 'Open Sans'; - src: url('$(res)/fonts/Open_Sans/OpenSans-Bold.ttf') format('truetype'); - font-weight: 700; - font-style: normal; -} - -@font-face { - font-family: 'Open Sans'; - src: url('$(res)/fonts/Open_Sans/OpenSans-BoldItalic.ttf') format('truetype'); - font-weight: 700; - font-style: italic; + font-family: 'Nunito'; + font-style: normal; + font-weight: 700; + src: url('$(res)/fonts/Nunito/Nunito-Bold.ttf') format('truetype'); } /* diff --git a/res/themes/dharma/css/_dharma.scss b/res/themes/light/css/_light.scss similarity index 87% rename from res/themes/dharma/css/_dharma.scss rename to res/themes/light/css/_light.scss index e389cc944c..7bd84d6191 100644 --- a/res/themes/dharma/css/_dharma.scss +++ b/res/themes/light/css/_light.scss @@ -6,6 +6,13 @@ Arial here. */ $font-family: 'Nunito', Arial, Helvetica, Sans-Serif; +// unified palette +// try to use these colors when possible +$accent-color: #03b381; +$notice-primary-color: #ff4b55; +$notice-secondary-color: #61708b; +$header-panel-bg-color: #f2f5f8; + // typical text (dark-on-white in light skin) $primary-fg-color: #454545; $primary-bg-color: #ffffff; @@ -18,7 +25,6 @@ $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; @@ -27,7 +33,7 @@ $selection-fg-color: $primary-bg-color; $focus-brightness: 105%; // red warning colour -$warning-color: #f56679; +$warning-color: $notice-primary-color; // background colour for warnings $warning-bg-color: #DF2A8B; $info-bg-color: #2A9EDF; @@ -35,8 +41,8 @@ $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; +$pinned-unread-color: $notice-primary-color; +$pinned-color: $notice-secondary-color; // informational plinth $info-plinth-bg-color: #f7f7f7; @@ -72,11 +78,11 @@ $input-darker-fg-color: #9fa9ba; $input-lighter-bg-color: #f2f5f8; $input-lighter-fg-color: $input-darker-fg-color; $input-focused-border-color: #238cf5; -$input-valid-border-color: #7ac9a1; +$input-valid-border-color: $accent-color; $field-focused-label-bg-color: #ffffff; -$button-bg-color: #7ac9a1; +$button-bg-color: $accent-color; $button-fg-color: white; // apart from login forms, which have stronger border @@ -91,6 +97,7 @@ $scrollbar-track-color: transparent; // context menus $menu-border-color: #ebedf8; $menu-bg-color: #fff; +$menu-box-shadow-color: rgba(118, 131, 156, 0.6); $menu-selected-color: #f5f8fa; $avatar-initial-color: #ffffff; @@ -139,10 +146,16 @@ $rte-group-pill-color: #aaa; $topleftmenu-color: #212121; $roomheader-color: #45474a; $roomheader-addroom-color: #91A1C0; +$tagpanel-button-color: #91A1C0; +$roomheader-button-color: #91A1C0; +$groupheader-button-color: #91A1C0; +$rightpanel-button-color: #91A1C0; +$composer-button-color: #91A1C0; $roomtopic-color: #9fa9ba; $eventtile-meta-color: $roomtopic-color; $composer-e2e-icon-color: #c9ced6; +$header-divider-color: #91A1C0; // ******************** @@ -152,14 +165,14 @@ $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; +$username-variant1-color: #368bd6; +$username-variant2-color: #ac3ba8; +$username-variant3-color: #03b381; +$username-variant4-color: #e64f7a; +$username-variant5-color: #ff812d; +$username-variant6-color: #2dc2c5; +$username-variant7-color: #5c56f5; +$username-variant8-color: #74d12c; $roomtile-transparent-focused-color: rgba(0, 0, 0, 0.1); @@ -205,26 +218,24 @@ $lightbox-border-color: #ffffff; $tab-label-fg-color: #45474a; $tab-label-active-fg-color: #ffffff; $tab-label-bg-color: transparent; -$tab-label-active-bg-color: #7ac9a1; +$tab-label-active-bg-color: $accent-color; $tab-label-icon-bg-color: #454545; $tab-label-active-icon-bg-color: #ffffff; // Buttons $button-primary-fg-color: #ffffff; -$button-primary-bg-color: #7ac9a1; -$button-primary-disabled-fg-color: #ffffff; -$button-primary-disabled-bg-color: #bce4d0; +$button-primary-bg-color: $accent-color; +$button-secondary-bg-color: $accent-fg-color; $button-danger-fg-color: #ffffff; -$button-danger-bg-color: #f56679; +$button-danger-bg-color: $notice-primary-color; $button-danger-disabled-fg-color: #ffffff; $button-danger-disabled-bg-color: #f5b6bb; // TODO: Verify color // Toggle switch $togglesw-off-color: #c1c9d6; -$togglesw-on-color: #7ac9a1; +$togglesw-on-color: $accent-color; $togglesw-ball-color: #fff; -// unused? $progressbar-color: #000; $room-warning-bg-color: #fff8e3; @@ -235,7 +246,10 @@ $authpage-bg-color: #2e3649; $authpage-modal-bg-color: rgba(255, 255, 255, 0.59); $authpage-body-bg-color: #ffffff; $authpage-lang-color: #4e5054; -$authpage-body-color: #61708b; +$authpage-primary-color: #454545; +$authpage-secondary-color: #61708b; + +$panel-gradient: rgba(242, 245, 248, 0), rgba(242, 245, 248, 1); /*** form elements ***/ @@ -270,23 +284,13 @@ $authpage-body-color: #61708b; border: none; flex: 1; color: $primary-fg-color; - }, + } input::placeholder { - color: $roomsublist-label-fg-color; + 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; @@ -319,7 +323,6 @@ input[type=search].mx_textinput_icon { 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 { @@ -332,7 +335,7 @@ 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; + display: none; } .input[type=text]::-webkit-input-placeholder, @@ -386,5 +389,5 @@ textarea::placeholder { font-weight: 600; border: 1px solid $accent-color ! important; color: $accent-color; - background-color: $accent-fg-color; + background-color: $button-secondary-bg-color; } diff --git a/res/themes/light/css/light.scss b/res/themes/light/css/light.scss index 6ac8d0feba..6acb2d9d94 100644 --- a/res/themes/light/css/light.scss +++ b/res/themes/light/css/light.scss @@ -1,4 +1,4 @@ @import "_paths.scss"; @import "_fonts.scss"; -@import "_base.scss"; +@import "_light.scss"; @import "../../../../res/css/_components.scss"; diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index f283eb84a5..e36034c69d 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -177,7 +177,7 @@ class MatrixClientPeg { userId: creds.userId, deviceId: creds.deviceId, timelineSupport: true, - forceTURN: !SettingsStore.getValue('webRtcForcePeerToPeer', false), + forceTURN: !SettingsStore.getValue('webRtcAllowPeerToPeer', false), verificationMethods: [verificationMethods.SAS] }; diff --git a/src/components/structures/AutoHideScrollbar.js b/src/components/structures/AutoHideScrollbar.js index a385df0401..0f93f20407 100644 --- a/src/components/structures/AutoHideScrollbar.js +++ b/src/components/structures/AutoHideScrollbar.js @@ -114,10 +114,15 @@ export default class AutoHideScrollbar extends React.Component { } } + getScrollTop() { + return this.containerRef.scrollTop; + } + render() { return (
{ this.props.children } diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index 530a200a18..89fce9c718 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -1157,7 +1157,6 @@ export default React.createClass({ render: function() { const GroupAvatar = sdk.getComponent("avatars.GroupAvatar"); const Spinner = sdk.getComponent("elements.Spinner"); - const TintableSvg = sdk.getComponent("elements.TintableSvg"); const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); if (this.state.summaryLoading && this.state.error === null || this.state.saving) { @@ -1248,13 +1247,17 @@ export default React.createClass({ if (this.state.editing) { rightButtons.push( { _t('Save') } , ); rightButtons.push( - + {_t("Cancel")} , @@ -1262,16 +1265,20 @@ export default React.createClass({ } else { if (summary.user && summary.user.membership === 'join') { rightButtons.push( - - , ); } rightButtons.push( - - + , ); } diff --git a/src/components/structures/IndicatorScrollbar.js b/src/components/structures/IndicatorScrollbar.js index c3e54ee900..e1516d1f64 100644 --- a/src/components/structures/IndicatorScrollbar.js +++ b/src/components/structures/IndicatorScrollbar.js @@ -59,6 +59,10 @@ export default class IndicatorScrollbar extends React.Component { } } + getScrollTop() { + return this._autoHideScrollbar.getScrollTop(); + } + componentWillUnmount() { if (this._scrollElement) { this._scrollElement.removeEventListener("scroll", this.checkOverflow); diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 4bb4e34033..e534ced577 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -654,11 +654,9 @@ export default React.createClass({ }); break; } - // case 'set_theme': - // disable changing the theme for now - // as other themes are not compatible with dharma - // this._onSetTheme(payload.value); - // break; + case 'set_theme': + this._onSetTheme(payload.value); + break; case 'on_logging_in': // We are now logging in, so set the state to reflect that // NB. This does not touch 'ready' since if our dispatches diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index ca2be85b35..f7f74da728 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -27,7 +27,8 @@ import IndicatorScrollbar from './IndicatorScrollbar'; import { KeyCode } from '../../Keyboard'; import { Group } from 'matrix-js-sdk'; import PropTypes from 'prop-types'; - +import RoomTile from "../views/rooms/RoomTile"; +import LazyRenderList from "../views/elements/LazyRenderList"; // turn this on for drop & drag console debugging galore const debug = false; @@ -60,6 +61,9 @@ const RoomSubList = React.createClass({ getInitialState: function() { return { hidden: this.props.startAsHidden || false, + // some values to get LazyRenderList starting + scrollerHeight: 800, + scrollTop: 0, }; }, @@ -134,24 +138,21 @@ const RoomSubList = React.createClass({ this.setState(this.state); }, - makeRoomTiles: function() { - const RoomTile = sdk.getComponent("rooms.RoomTile"); - return this.props.list.map((room, index) => { - return 0 || this.props.isInvite} - notificationCount={room.getUnreadNotificationCount()} - isInvite={this.props.isInvite} - refreshSubList={this._updateSubListCount} - incomingCall={null} - onClick={this.onRoomTileClick} - />; - }); + makeRoomTile: function(room) { + return 0 || this.props.isInvite} + notificationCount={room.getUnreadNotificationCount()} + isInvite={this.props.isInvite} + refreshSubList={this._updateSubListCount} + incomingCall={null} + onClick={this.onRoomTileClick} + />; }, _onNotifBadgeClick: function(e) { @@ -270,6 +271,29 @@ const RoomSubList = React.createClass({ if (this.refs.subList) { this.refs.subList.style.height = `${height}px`; } + this._updateLazyRenderHeight(height); + }, + + _updateLazyRenderHeight: function(height) { + this.setState({scrollerHeight: height}); + }, + + _onScroll: function() { + this.setState({scrollTop: this.refs.scroller.getScrollTop()}); + }, + + _getRenderItems: function() { + // try our best to not create a new array + // because LazyRenderList rerender when the items prop + // is not the same object as the previous value + const {list, extraTiles} = this.props; + if (!extraTiles || !extraTiles.length) { + return list; + } + if (!list || list.length) { + return extraTiles; + } + return list.concat(extraTiles); }, render: function() { @@ -287,12 +311,15 @@ const RoomSubList = React.createClass({ {this._getHeaderJsx(isCollapsed)}
; } else { - const tiles = this.makeRoomTiles(); - tiles.push(...this.props.extraTiles); return
{this._getHeaderJsx(isCollapsed)} - - { tiles } + +
; } diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js index 2f777c1163..10628ccd13 100644 --- a/src/components/structures/SearchBox.js +++ b/src/components/structures/SearchBox.js @@ -21,7 +21,7 @@ import { _t } from '../../languageHandler'; import { KeyCode } from '../../Keyboard'; import sdk from '../../index'; import dis from '../../dispatcher'; -import { debounce } from 'lodash'; +import { throttle } from 'lodash'; import AccessibleButton from '../../components/views/elements/AccessibleButton'; module.exports = React.createClass({ @@ -67,9 +67,9 @@ module.exports = React.createClass({ this.onSearch(); }, - onSearch: debounce(function() { + onSearch: throttle(function() { this.props.onSearch(this.refs.search.value); - }, 200, {trailing: true}), + }, 200, {trailing: true, leading: true}), _onKeyDown: function(ev) { switch (ev.keyCode) { diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js index 69abd8b88b..6b578f0f68 100644 --- a/src/components/structures/auth/Registration.js +++ b/src/components/structures/auth/Registration.js @@ -64,6 +64,17 @@ module.exports = React.createClass({ getInitialState: function() { const customURLsAllowed = !SdkConfig.get()['disable_custom_urls']; + let initialPhase = PHASE_SERVER_DETAILS; + if ( + // if we have these two, skip to the good bit + // (they could come in from the URL params in a + // registration email link) + (this.props.clientSecret && this.props.sessionId) || + // or if custom URLs aren't allowed, skip them + !customURLsAllowed + ) { + initialPhase = PHASE_REGISTRATION; + } return { busy: false, @@ -87,7 +98,7 @@ module.exports = React.createClass({ hsUrl: this.props.customHsUrl, isUrl: this.props.customIsUrl, // Phase of the overall registration dialog. - phase: customURLsAllowed ? PHASE_SERVER_DETAILS : PHASE_REGISTRATION, + phase: initialPhase, flows: null, }; }, @@ -111,7 +122,7 @@ module.exports = React.createClass({ }); }, - onServerTypeChange(type) { + onServerTypeChange(type, initial) { this.setState({ serverType: type, }); @@ -137,9 +148,15 @@ module.exports = React.createClass({ hsUrl: this.props.defaultHsUrl, isUrl: this.props.defaultIsUrl, }); - this.setState({ - phase: PHASE_SERVER_DETAILS, - }); + // if this is the initial value from the control and we're + // already in the registration phase, don't go back to the + // server details phase (but do if it's actually a change resulting + // from user interaction). + if (!initial || !this.state.phase === PHASE_REGISTRATION) { + this.setState({ + phase: PHASE_SERVER_DETAILS, + }); + } break; } }, @@ -372,9 +389,12 @@ module.exports = React.createClass({ // If we're on a different phase, we only show the server type selector, // which is always shown if we allow custom URLs at all. if (PHASES_ENABLED && this.state.phase !== PHASE_SERVER_DETAILS) { + // if we've been given a custom HS URL we should actually pass that, so + // that the appropriate section is selected at the start to match the + // homeserver URL we're using return
; diff --git a/src/components/views/auth/ServerTypeSelector.js b/src/components/views/auth/ServerTypeSelector.js index de76e6acf9..7a28eec0ed 100644 --- a/src/components/views/auth/ServerTypeSelector.js +++ b/src/components/views/auth/ServerTypeSelector.js @@ -90,7 +90,11 @@ export default class ServerTypeSelector extends React.PureComponent { selected: type, }; if (onChange) { - onChange(type); + // FIXME: Supply a second 'initial' param here to flag that this is + // initialising the value rather than from user interaction + // (which sometimes we'll want to ignore). Must be a better way + // to do this. + onChange(type, true); } } diff --git a/src/components/views/context_menus/TopLeftMenu.js b/src/components/views/context_menus/TopLeftMenu.js index 1d58db3c49..8583f631f2 100644 --- a/src/components/views/context_menus/TopLeftMenu.js +++ b/src/components/views/context_menus/TopLeftMenu.js @@ -20,11 +20,15 @@ import { _t } from '../../../languageHandler'; import LogoutDialog from "../dialogs/LogoutDialog"; import Modal from "../../../Modal"; import SdkConfig from '../../../SdkConfig'; +import MatrixClientPeg from '../../../MatrixClientPeg'; export class TopLeftMenu extends React.Component { constructor() { super(); + this.viewHomePage = this.viewHomePage.bind(this); + this.viewWelcomePage = this.viewWelcomePage.bind(this); this.openSettings = this.openSettings.bind(this); + this.signIn = this.signIn.bind(this); this.signOut = this.signOut.bind(this); } @@ -41,6 +45,8 @@ export class TopLeftMenu extends React.Component { } render() { + const isGuest = MatrixClientPeg.get().isGuest(); + let homePageSection = null; if (this.hasHomePage()) { homePageSection =
    @@ -48,14 +54,26 @@ export class TopLeftMenu extends React.Component {
; } + let signInOutSection; + if (isGuest) { + signInOutSection =
    +
  • {_t("Sign in")}
  • +
; + } else { + signInOutSection =
    +
  • {_t("Sign out")}
  • +
; + } + return
{homePageSection}
    -
  • {_t("Settings")}
  • +
  • {_t("Welcome")}
    -
  • {_t("Sign out")}
  • +
  • {_t("Settings")}
+ {signInOutSection}
; } @@ -64,11 +82,21 @@ export class TopLeftMenu extends React.Component { this.closeMenu(); } + viewWelcomePage() { + dis.dispatch({action: 'view_welcome_page'}); + this.closeMenu(); + } + openSettings() { dis.dispatch({action: 'view_user_settings'}); this.closeMenu(); } + signIn() { + dis.dispatch({action: 'start_login'}); + this.closeMenu(); + } + signOut() { Modal.createTrackedDialog('Logout E2E Export', '', LogoutDialog); this.closeMenu(); diff --git a/src/components/views/elements/LazyRenderList.js b/src/components/views/elements/LazyRenderList.js new file mode 100644 index 0000000000..1c1cc127d6 --- /dev/null +++ b/src/components/views/elements/LazyRenderList.js @@ -0,0 +1,97 @@ +/* +Copyright 2019 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"; + +const OVERFLOW_ITEMS = 20; +const OVERFLOW_MARGIN = 5; + +class ItemRange { + constructor(topCount, renderCount, bottomCount) { + this.topCount = topCount; + this.renderCount = renderCount; + this.bottomCount = bottomCount; + } + + contains(range) { + return range.topCount >= this.topCount && + (range.topCount + range.renderCount) <= (this.topCount + this.renderCount); + } + + expand(amount) { + const topGrow = Math.min(amount, this.topCount); + const bottomGrow = Math.min(amount, this.bottomCount); + return new ItemRange( + this.topCount - topGrow, + this.renderCount + topGrow + bottomGrow, + this.bottomCount - bottomGrow, + ); + } +} + +export default class LazyRenderList extends React.Component { + constructor(props) { + super(props); + const renderRange = LazyRenderList.getVisibleRangeFromProps(props).expand(OVERFLOW_ITEMS); + this.state = {renderRange}; + } + + static getVisibleRangeFromProps(props) { + const {items, itemHeight, scrollTop, height} = props; + const length = items ? items.length : 0; + const topCount = Math.max(0, Math.floor(scrollTop / itemHeight)); + const itemsAfterTop = length - topCount; + const renderCount = Math.min(Math.ceil(height / itemHeight), itemsAfterTop); + const bottomCount = itemsAfterTop - renderCount; + return new ItemRange(topCount, renderCount, bottomCount); + } + + componentWillReceiveProps(props) { + const state = this.state; + const range = LazyRenderList.getVisibleRangeFromProps(props); + const intersectRange = range.expand(OVERFLOW_MARGIN); + + const prevSize = this.props.items ? this.props.items.length : 0; + const listHasChangedSize = props.items.length !== prevSize; + // only update renderRange if the list has shrunk/grown and we need to adjust padding or + // if the new range isn't contained by the old anymore + if (listHasChangedSize || !state.renderRange || !state.renderRange.contains(intersectRange)) { + this.setState({renderRange: range.expand(OVERFLOW_ITEMS)}); + } + } + + shouldComponentUpdate(nextProps, nextState) { + const itemsChanged = nextProps.items !== this.props.items; + const rangeChanged = nextState.renderRange !== this.state.renderRange; + return itemsChanged || rangeChanged; + } + + render() { + const {itemHeight, items, renderItem} = this.props; + + const {renderRange} = this.state; + const paddingTop = renderRange.topCount * itemHeight; + const paddingBottom = renderRange.bottomCount * itemHeight; + const renderedItems = (items || []).slice( + renderRange.topCount, + renderRange.topCount + renderRange.renderCount, + ); + + return (
+ { renderedItems.map(renderItem) } +
); + } +} diff --git a/src/components/views/elements/ManageIntegsButton.js b/src/components/views/elements/ManageIntegsButton.js index e5cc21d85e..3240050b6a 100644 --- a/src/components/views/elements/ManageIntegsButton.js +++ b/src/components/views/elements/ManageIntegsButton.js @@ -24,7 +24,6 @@ import ScalarMessaging from '../../../ScalarMessaging'; import Modal from "../../../Modal"; import { _t } from '../../../languageHandler'; import AccessibleButton from './AccessibleButton'; -import TintableSvg from './TintableSvg'; export default class ManageIntegsButton extends React.Component { constructor(props) { @@ -76,6 +75,7 @@ export default class ManageIntegsButton extends React.Component { if (this.scalarClient !== null) { const integrationsButtonClasses = classNames({ mx_RoomHeader_button: true, + mx_RoomHeader_manageIntegsButton: true, mx_ManageIntegsButton_error: !!this.state.scalarError, }); @@ -94,8 +94,10 @@ export default class ManageIntegsButton extends React.Component { } integrationsButton = ( - - + { integrationsWarningTriangle } { integrationsErrorPopup } diff --git a/src/components/views/right_panel/GroupHeaderButtons.js b/src/components/views/right_panel/GroupHeaderButtons.js index 6867b0bb9d..13379d49e3 100644 --- a/src/components/views/right_panel/GroupHeaderButtons.js +++ b/src/components/views/right_panel/GroupHeaderButtons.js @@ -65,12 +65,14 @@ export default class GroupHeaderButtons extends HeaderButtons { ]; return [ - , - - - ; + onClick={this.onClick}> + ; } } @@ -62,14 +61,14 @@ HeaderButton.propTypes = { isHighlighted: PropTypes.bool.isRequired, // The phase to swap to when the button is clicked clickPhase: PropTypes.string.isRequired, - // The source file of the icon to display - iconSrc: PropTypes.string.isRequired, // The badge to display above the icon badge: PropTypes.node, // The parameters to track the click event analytics: PropTypes.arrayOf(PropTypes.string).isRequired, + // Button name + name: PropTypes.string.isRequired, // Button title title: PropTypes.string.isRequired, }; diff --git a/src/components/views/right_panel/HeaderButtons.js b/src/components/views/right_panel/HeaderButtons.js index 3f5f58121d..b7155b922f 100644 --- a/src/components/views/right_panel/HeaderButtons.js +++ b/src/components/views/right_panel/HeaderButtons.js @@ -88,7 +88,7 @@ export default class HeaderButtons extends React.Component { render() { // inline style as this will be swapped around in future commits - return
+ return
{ this.renderButtons() }
; } diff --git a/src/components/views/right_panel/RoomHeaderButtons.js b/src/components/views/right_panel/RoomHeaderButtons.js index 1985909f4a..8d10094637 100644 --- a/src/components/views/right_panel/RoomHeaderButtons.js +++ b/src/components/views/right_panel/RoomHeaderButtons.js @@ -52,17 +52,20 @@ export default class RoomHeaderButtons extends HeaderButtons { ]; return [ - , - , - - {_t('Hangup')} + ; } else { callButton = - - + ; videoCallButton = - - + ; } @@ -385,9 +393,11 @@ export default class MessageComposer extends React.Component { // check separately for whether we can call, but this is slightly // complex because of conference calls. const uploadButton = ( - - + - + ; } @@ -245,7 +246,6 @@ module.exports = React.createClass({ { pinsIndicator } - ; } @@ -260,24 +260,30 @@ module.exports = React.createClass({ let forgetButton; if (this.props.onForgetClick) { forgetButton = - - + ; } let searchButton; if (this.props.onSearchClick && this.props.inRoom) { searchButton = - - + ; } let shareRoomButton; if (this.props.inRoom) { shareRoomButton = - - + ; } diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 188b42622a..c9f3195b08 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -322,7 +322,6 @@ export default class Stickerpicker extends React.Component { } render() { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); const ContextualMenu = sdk.getComponent('structures.ContextualMenu'); const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu'); let stickersButton; @@ -348,11 +347,11 @@ export default class Stickerpicker extends React.Component { - + title={_t("Hide Stickers")} + > ; } else { // Show show-stickers button @@ -360,10 +359,10 @@ export default class Stickerpicker extends React.Component { - + title={_t("Show Stickers")} + > ; } return
diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js index 3976196b57..cc1b3fd017 100644 --- a/src/components/views/settings/KeyBackupPanel.js +++ b/src/components/views/settings/KeyBackupPanel.js @@ -42,7 +42,7 @@ export default class KeyBackupPanel extends React.PureComponent { } componentWillMount() { - this._loadBackupStatus(); + this._checkKeyBackupStatus(); MatrixClientPeg.get().on('crypto.keyBackupStatus', this._onKeyBackupStatus); MatrixClientPeg.get().on( @@ -70,9 +70,32 @@ export default class KeyBackupPanel extends React.PureComponent { } _onKeyBackupStatus() { + // This just loads the current backup status rather than forcing + // a re-check otherwise we risk causing infinite loops this._loadBackupStatus(); } + async _checkKeyBackupStatus() { + try { + const {backupInfo, trustInfo} = await MatrixClientPeg.get().checkKeyBackup(); + this.setState({ + backupInfo, + backupSigStatus: trustInfo, + error: null, + loading: false, + }); + } catch (e) { + console.log("Unable to fetch check backup status", e); + if (this._unmounted) return; + this.setState({ + error: e, + backupInfo: null, + backupSigStatus: null, + loading: false, + }); + } + } + async _loadBackupStatus() { this.setState({loading: true}); try { @@ -80,6 +103,7 @@ export default class KeyBackupPanel extends React.PureComponent { const backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo); if (this._unmounted) return; this.setState({ + error: null, backupInfo, backupSigStatus, loading: false, @@ -89,9 +113,10 @@ export default class KeyBackupPanel extends React.PureComponent { if (this._unmounted) return; this.setState({ error: e, + backupInfo: null, + backupSigStatus: null, loading: false, }); - return; } } diff --git a/src/components/views/settings/tabs/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/GeneralUserSettingsTab.js index bfcc7b945c..2364475239 100644 --- a/src/components/views/settings/tabs/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/GeneralUserSettingsTab.js @@ -54,6 +54,7 @@ export default class GeneralUserSettingsTab extends React.Component { if (this.state.theme === newTheme) return; SettingsStore.setValue("theme", null, SettingLevel.ACCOUNT, newTheme); + this.setState({theme: newTheme}); dis.dispatch({action: 'set_theme', value: newTheme}); }; @@ -138,17 +139,14 @@ export default class GeneralUserSettingsTab extends React.Component { } _renderThemeSection() { - // TODO: Re-enable theme selection once the themes actually work const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag"); return (
{_t("Theme")} - - + - -
@@ -164,7 +162,7 @@ export default class GeneralUserSettingsTab extends React.Component { {_t("Deactivating your account is a permanent action - be careful!")} - {_t("Close Account")} + {_t("Deactivate Account")}
); diff --git a/src/components/views/settings/tabs/VoiceSettingsTab.js b/src/components/views/settings/tabs/VoiceSettingsTab.js index 65f38c7841..aefb114dd3 100644 --- a/src/components/views/settings/tabs/VoiceSettingsTab.js +++ b/src/components/views/settings/tabs/VoiceSettingsTab.js @@ -174,7 +174,7 @@ export default class VoiceSettingsTab extends React.Component { {microphoneDropdown} {webcamDropdown} - +
); diff --git a/src/i18n/strings/bg.json b/src/i18n/strings/bg.json index 31b8d5b209..e92648a0d2 100644 --- a/src/i18n/strings/bg.json +++ b/src/i18n/strings/bg.json @@ -1515,7 +1515,7 @@ "2018 theme": "Тема 2018", "Account management": "Управление на акаунта", "Deactivating your account is a permanent action - be careful!": "Деактивирането на акаунта е необратимо действие - внимавайте!", - "Close Account": "Затвори акаунта", + "Deactivate Account": "Затвори акаунта", "For help with using Riot, click here.": "За помощ при използването на Riot, кликнете тук.", "For help with using Riot, click here or start a chat with our bot using the button below.": "За помощ при използването на Riot, кликнете тук или започнете чат с бота ни използвайки бутона по-долу.", "Chat with Riot Bot": "Чати с Riot Bot", diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index d5ae97ee3b..8c85581e10 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1516,7 +1516,7 @@ "Theme": "Design", "2018 theme": "2018 Design", "Account management": "Benutzerkontenverwaltung", - "Close Account": "Benutzerkonto schließen", + "Deactivate Account": "Benutzerkonto schließen", "For help with using Riot, click here.": "Um Hilfe zur Benutzung von Riot zu erhalten, klicke hier.", "For help with using Riot, click here or start a chat with our bot using the button below.": "Um Hilfe zur Benutzung von Riot zu erhalten, klicke hier oder beginne einen Chat mit unserem Bot, indem du den unteren Button klickst.", "Chat with Riot Bot": "Chatte mit dem Riot Bot", diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 7376b35fe5..fe41beb7ae 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -292,7 +292,7 @@ "Automatically replace plain text Emoji": "Automatically replace plain text Emoji", "Mirror local video feed": "Mirror local video feed", "Enable Community Filter Panel": "Enable Community Filter Panel", - "Disable Peer-to-Peer for 1:1 calls": "Disable Peer-to-Peer for 1:1 calls", + "Allow Peer-to-Peer for 1:1 calls": "Allow Peer-to-Peer for 1:1 calls", "Send analytics data": "Send analytics data", "Never send encrypted messages to unverified devices from this device": "Never send encrypted messages to unverified devices from this device", "Never send encrypted messages to unverified devices in this room from this device": "Never send encrypted messages to unverified devices in this room from this device", @@ -522,13 +522,11 @@ "Phone numbers": "Phone numbers", "Language and region": "Language and region", "Theme": "Theme", - "Light theme": "Light theme", + "Default theme": "Default theme", "Dark theme": "Dark theme", - "2018 theme": "2018 theme", - "Status.im theme": "Status.im theme", "Account management": "Account management", "Deactivating your account is a permanent action - be careful!": "Deactivating your account is a permanent action - be careful!", - "Close Account": "Close Account", + "Deactivate Account": "Deactivate Account", "Legal": "Legal", "For help with using Riot, click here.": "For help with using Riot, click here.", "For help with using Riot, click here or start a chat with our bot using the button below.": "For help with using Riot, click here or start a chat with our bot using the button below.", @@ -1053,7 +1051,6 @@ "Continue With Encryption Disabled": "Continue With Encryption Disabled", "Unknown error": "Unknown error", "Incorrect password": "Incorrect password", - "Deactivate Account": "Deactivate Account", "This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. This action is irreversible.": "This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. This action is irreversible.", "Deactivating your account does not by default cause us to forget messages you have sent. If you would like us to forget your messages, please tick the box below.": "Deactivating your account does not by default cause us to forget messages you have sent. If you would like us to forget your messages, please tick the box below.", "Message visibility in Matrix is similar to email. Our forgetting your messages means that messages you have sent will not be shared with any new or unregistered users, but registered users who already have access to these messages will still have access to their copy.": "Message visibility in Matrix is similar to email. Our forgetting your messages means that messages you have sent will not be shared with any new or unregistered users, but registered users who already have access to these messages will still have access to their copy.", @@ -1205,6 +1202,7 @@ "Quote": "Quote", "Source URL": "Source URL", "Collapse Reply Thread": "Collapse Reply Thread", + "End-to-end encryption information": "End-to-end encryption information", "Failed to set Direct Message status of room": "Failed to set Direct Message status of room", "unknown error code": "unknown error code", "Failed to forget room %(errCode)s": "Failed to forget room %(errCode)s", @@ -1222,6 +1220,8 @@ "Set a new status...": "Set a new status...", "View Community": "View Community", "Hide": "Hide", + "Sign in": "Sign in", + "Welcome": "Welcome", "Login": "Login", "powered by Matrix": "powered by Matrix", "Robot check is currently unavailable on desktop - please use a web browser": "Robot check is currently unavailable on desktop - please use a web browser", @@ -1252,7 +1252,6 @@ "Username": "Username", "Mobile phone number": "Mobile phone number", "Not sure of your password? Set a new one": "Not sure of your password? Set a new one", - "Sign in": "Sign in", "Sign in to %(serverName)s": "Sign in to %(serverName)s", "Change": "Change", "Sign in with": "Sign in with", @@ -1475,7 +1474,6 @@ "unencrypted": "unencrypted", "Decryption error": "Decryption error", "Session ID": "Session ID", - "End-to-end encryption information": "End-to-end encryption information", "Event information": "Event information", "Sender device information": "Sender device information", "Passphrases must match": "Passphrases must match", @@ -1536,7 +1534,6 @@ "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.", "This device is encrypting history using the new recovery method.": "This device is encrypting history using the new recovery method.", "Go to Settings": "Go to Settings", - "Setting up Secure Messages on this device will re-encrypt this device's message history with the new recovery method.": "Setting up Secure Messages on this device will re-encrypt this device's message history with the new recovery method.", "Set up Secure Messages": "Set up Secure Messages", "Recovery Method Removed": "Recovery Method Removed", "This device has detected that your recovery passphrase and key for Secure Messages have been removed.": "This device has detected that your recovery passphrase and key for Secure Messages have been removed.", diff --git a/src/i18n/strings/eu.json b/src/i18n/strings/eu.json index 4851e3c8fb..a53b4e2f24 100644 --- a/src/i18n/strings/eu.json +++ b/src/i18n/strings/eu.json @@ -1586,7 +1586,7 @@ "2018 theme": "2018ko itxura", "Account management": "Kontuen kudeaketa", "Deactivating your account is a permanent action - be careful!": "Kontua desgaitzea behin betiko ekintza bat da, kontuz ibili!", - "Close Account": "Itxi kontua", + "Deactivate Account": "Itxi kontua", "For help with using Riot, click here.": "Riot erabiltzeko laguntza behar baduzu, egin klik hemen.", "For help with using Riot, click here or start a chat with our bot using the button below.": "Riot erabiltzeko laguntza behar baduzu, egin klik hemen edo hasi txat bat gure botarekin beheko botoia sakatuz.", "Chat with Riot Bot": "Txateatu Riot botarekin", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index d20810ca52..1940a7999b 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -1526,7 +1526,7 @@ "2018 theme": "Thème 2018", "Account management": "Gestion du compte", "Deactivating your account is a permanent action - be careful!": "La désactivation du compte est une action permanente. Soyez prudent !", - "Close Account": "Fermer le compte", + "Deactivate Account": "Fermer le compte", "For help with using Riot, click here.": "Pour obtenir de l'aide sur l'utilisation de Riot, cliquez ici.", "For help with using Riot, click here or start a chat with our bot using the button below.": "Pour obtenir de l'aide sur l'utilisation de Riot, cliquez ici ou commencez une discussion avec notre bot en utilisant le bouton ci-dessous.", "Start a chat with Riot Bot": "Commencer une discussion avec le bot Riot", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index bee5a778fb..56e9aaa4a3 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -1525,7 +1525,7 @@ "2018 theme": "2018-as téma", "Account management": "Fiók menedzsment", "Deactivating your account is a permanent action - be careful!": "A fiók felfüggesztése végleges - légy óvatos!", - "Close Account": "Fiók bezárása", + "Deactivate Account": "Fiók bezárása", "For help with using Riot, click here.": "A Riot használatában való segítséghez kattints ide.", "For help with using Riot, click here or start a chat with our bot using the button below.": "A Riot használatában való segítségér kattints ide vagy kezdj beszélgetni a botunkkal az alábbi gombra kattintva.", "Start a chat with Riot Bot": "Csevegés kezdése a Riot Bottal", diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index b1ed91e9ab..2f04e39104 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -300,10 +300,10 @@ "Add rooms to the community": "コミュニティに部屋を追加します", "Room name or alias": "部屋名またはエイリアス", "Add to community": "コミュニティに追加", - "Failed to invite the following users to %(groupId)s:": "次のユーザーを %(groupId)s に招待できませんでした:", + "Failed to invite the following users to %(groupId)s:": "次のユーザーを %(groupId)s に招待できませんでした:", "Failed to invite users to community": "ユーザーをコミュニティに招待できませんでした", "Failed to invite users to %(groupId)s": "ユーザーを %(groupId)s に招待できませんでした", - "Failed to add the following rooms to %(groupId)s:": "次の部屋を %(groupId)s に追加できませんでした:", + "Failed to add the following rooms to %(groupId)s:": "次の部屋を %(groupId)s に追加できませんでした:", "Riot does not have permission to send you notifications - please check your browser settings": "Riotに通知を送信する権限がありません - ブラウザの設定を確認してください", "Riot was not given permission to send notifications - please try again": "Riotに通知を送信する権限がありませんでした。もう一度お試しください", "Unable to enable Notifications": "通知を有効にできません", @@ -323,7 +323,7 @@ "Send Invites": "招待状を送る", "Failed to invite user": "ユーザーを招待できませんでした", "Failed to invite": "招待できませんでした", - "Failed to invite the following users to the %(roomName)s room:": "次のユーザーを %(roomName)s の部屋に招待できませんでした:", + "Failed to invite the following users to the %(roomName)s room:": "次のユーザーを %(roomName)s の部屋に招待できませんでした:", "You need to be logged in.": "ログインする必要があります。", "You need to be able to invite users to do that.": "それをするためにユーザーを招待できる必要があります。", "Unable to create widget.": "ウィジェットを作成できません。", @@ -363,9 +363,9 @@ "Unknown (user, device) pair:": "不明な(ユーザー、端末) ペア:", "Device already verified!": "端末はすでに確認済みです!", "WARNING: Device already verified, but keys do NOT MATCH!": "警告:端末はすでに検証済みですが、キーは一致しません!", - "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "警告: キー確認が失敗しました! %(userId)s と端末 %(deviceId)s の署名鍵は、提供された鍵 \"%(fingerprint)s\" と一致しない \"%(fprint)s\" です。 通信が傍受されている可能性があります!", + "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "警告: キー確認が失敗しました! %(userId)s と端末 %(deviceId)s の署名鍵は、提供された鍵 \"%(fingerprint)s\" と一致しない \"%(fprint)s\" です。 通信が傍受されている可能性があります!", "Verified key": "確認済みのキー", - "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "指定した署名鍵は、%(userId)s の端末%(deviceId)s から受け取った署名鍵と一致します。端末を検証済みとしてマークしました。", + "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "指定した署名鍵は、%(userId)s の端末%(deviceId)s から受け取った署名鍵と一致します。端末を検証済みとしてマークしました。", "Displays action": "アクションを表示", "Forces the current outbound group session in an encrypted room to be discarded": "暗号化されたルーム内の現在のアウトバウンドグループセッションを強制的に破棄します", "Unrecognised command:": "認識できないコマンド:", @@ -609,7 +609,7 @@ "Replying": "返信中", "Failed to set avatar.": "アバターを設定できませんでした。", "Save": "保存", - "(~%(count)s results)|other": "(~%(count)s 結果)", + "(~%(count)s results)|other": "(~%(count)s 結果)", "(~%(count)s results)|one": "(~%(count)s 結果)", "Join Room": "部屋に入る", "Remove avatar": "アバターを削除", @@ -641,7 +641,7 @@ "Rejoin": "再参加", "You have been kicked from %(roomName)s by %(userName)s.": "あなたは %(userName)s により %(roomName)s から追放されました。", "You have been kicked from this room by %(userName)s.": "あなたは %(userName)s によりこの部屋から追放されました。", - "You have been banned from %(roomName)s by %(userName)s.": "あなたは %(userName)s により %(roomName)s からブロックされました。", + "You have been banned from %(roomName)s by %(userName)s.": "あなたは %(userName)s により %(roomName)s からブロックされました。", "You have been banned from this room by %(userName)s.": "あなたは %(userName)s によってこの部屋からブロックされました。", "This room": "この部屋", "%(roomName)s does not exist.": "%(roomName)s は存在しません。", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index c24af068ed..9f766b9bf1 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -1393,7 +1393,7 @@ "Developer options": "Параметры разработчика", "General": "Основной", "Set a new account password...": "Установить новый пароль учетной записи...", - "Close Account": "Закрыть аккаунт", + "Deactivate Account": "Закрыть аккаунт", "Legal": "Правовой", "At this time it is not possible to reply with an emote.": "В настоящее время невозможно ответить с помощью эмоции.", "Room avatar": "Аватар комнаты", diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index 1299656c1c..2bf2f13420 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -1490,7 +1490,7 @@ "2018 theme": "Temë e 2018-s", "Account management": "Administrim llogarish", "Deactivating your account is a permanent action - be careful!": "Çaktivizimi i llogarisë tuaj është një veprim i pakthyeshëm - hapni sytë!", - "Close Account": "Mbylleni Llogarinë", + "Deactivate Account": "Mbylleni Llogarinë", "For help with using Riot, click here.": "Për ndihmë rreth përdorimit të Riot-it, klikoni këtu.", "For help with using Riot, click here or start a chat with our bot using the button below.": "Për ndihmë rreth përdorimit të Riot-it, klikoni këtu, ose nisni një fjalosje me robotin tonë duke përdorur butonin më poshtë.", "Help & About": "Ndihmë & Rreth", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 96485d3f28..6a95c64ce3 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -1524,7 +1524,7 @@ "Account management": "帳號管理", "2018 theme": "2018 主題", "Deactivating your account is a permanent action - be careful!": "停用您的帳號是永久動作,請小心!", - "Close Account": "關閉帳號", + "Deactivate Account": "關閉帳號", "For help with using Riot, click here.": "對於使用 Riot 的說明,點選這裡。", "For help with using Riot, click here or start a chat with our bot using the button below.": "對於使用 Riot 的說明,點選這裡或是使用下面的按鈕開始與我們的機器人聊天。", "Chat with Riot Bot": "與 Riot 機器人聊天", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 671f46b366..4108848033 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -22,6 +22,7 @@ import { NotificationsEnabledController, } from "./controllers/NotificationControllers"; import CustomStatusController from "./controllers/CustomStatusController"; +import ThemeController from './controllers/ThemeController'; // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times const LEVELS_ROOM_SETTINGS = ['device', 'room-device', 'room-account', 'account', 'config']; @@ -231,12 +232,13 @@ export const SETTINGS = { invertedSettingName: 'TagPanel.disableTagPanel', }, "theme": { - supportedLevels: ['config'], - default: "dharma", + supportedLevels: LEVELS_ACCOUNT_SETTINGS, + default: "light", + controller: new ThemeController(), }, - "webRtcForcePeerToPeer": { + "webRtcAllowPeerToPeer": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - displayName: _td('Disable Peer-to-Peer for 1:1 calls'), + displayName: _td('Allow Peer-to-Peer for 1:1 calls'), default: true, invertedSettingName: 'webRtcForceTURN', }, diff --git a/src/settings/controllers/ThemeController.js b/src/settings/controllers/ThemeController.js new file mode 100644 index 0000000000..615fc4c192 --- /dev/null +++ b/src/settings/controllers/ThemeController.js @@ -0,0 +1,33 @@ +/* +Copyright 2019 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 SettingController from "./SettingController"; + +const SUPPORTED_THEMES = [ + "light", + "dark", +]; + +export default class ThemeController extends SettingController { + getValueOverride(level, roomId, calculatedValue, calculatedAtLevel) { + // Override in case some no longer supported theme is stored here + if (!SUPPORTED_THEMES.includes(calculatedValue)) { + return "light"; + } + + return null; // no override + } +} diff --git a/src/settings/handlers/ConfigSettingsHandler.js b/src/settings/handlers/ConfigSettingsHandler.js index 67fff51e5b..a54ad1cef6 100644 --- a/src/settings/handlers/ConfigSettingsHandler.js +++ b/src/settings/handlers/ConfigSettingsHandler.js @@ -1,5 +1,6 @@ /* Copyright 2017 Travis Ralston +Copyright 2019 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. @@ -27,7 +28,7 @@ export default class ConfigSettingsHandler extends SettingsHandler { // Special case themes if (settingName === "theme") { - return "dharma"; // config["default_theme"]; + return config["default_theme"]; } const settingsConfig = config["settingDefaults"];