diff --git a/res/css/_components.scss b/res/css/_components.scss index 5cbcd32e9e6..3a6a3257a33 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -115,6 +115,7 @@ @import "./views/elements/_RichText.scss"; @import "./views/elements/_RoleButton.scss"; @import "./views/elements/_RoomAliasField.scss"; +@import "./views/elements/_Slider.scss"; @import "./views/elements/_Spinner.scss"; @import "./views/elements/_SyntaxHighlight.scss"; @import "./views/elements/_TextWithTooltip.scss"; @@ -206,6 +207,7 @@ @import "./views/settings/tabs/room/_GeneralRoomSettingsTab.scss"; @import "./views/settings/tabs/room/_RolesRoomSettingsTab.scss"; @import "./views/settings/tabs/room/_SecurityRoomSettingsTab.scss"; +@import "./views/settings/tabs/user/_AppearanceUserSettingsTab.scss"; @import "./views/settings/tabs/user/_GeneralUserSettingsTab.scss"; @import "./views/settings/tabs/user/_HelpUserSettingsTab.scss"; @import "./views/settings/tabs/user/_MjolnirUserSettingsTab.scss"; diff --git a/res/css/structures/_TagPanel.scss b/res/css/structures/_TagPanel.scss index 4a78c8df925..1f8443e3951 100644 --- a/res/css/structures/_TagPanel.scss +++ b/res/css/structures/_TagPanel.scss @@ -69,7 +69,7 @@ limitations under the License. height: 100%; } .mx_TagPanel .mx_TagPanel_tagTileContainer > div { - height: $font-40px; + height: 40px; padding: 10px 0 9px 0; } @@ -116,7 +116,7 @@ limitations under the License. position: absolute; left: -15px; border-radius: 0 3px 3px 0; - top: -8px; // (16px / 2) + top: -8px; // (16px from height / 2) } .mx_TagPanel .mx_TagTile.mx_AccessibleButton:focus { diff --git a/res/css/structures/_TopLeftMenuButton.scss b/res/css/structures/_TopLeftMenuButton.scss index 53d44e7c249..8d2e36bcd6f 100644 --- a/res/css/structures/_TopLeftMenuButton.scss +++ b/res/css/structures/_TopLeftMenuButton.scss @@ -43,7 +43,7 @@ limitations under the License. margin: 0 7px; mask: url('$(res)/img/feather-customised/dropdown-arrow.svg'); mask-repeat: no-repeat; - width: 10px; + width: $font-22px; height: 6px; background-color: $roomsublist-label-fg-color; } diff --git a/res/css/views/dialogs/_UserSettingsDialog.scss b/res/css/views/dialogs/_UserSettingsDialog.scss index 4d831d7858f..7adcc58c4ec 100644 --- a/res/css/views/dialogs/_UserSettingsDialog.scss +++ b/res/css/views/dialogs/_UserSettingsDialog.scss @@ -21,6 +21,10 @@ limitations under the License. mask-image: url('$(res)/img/feather-customised/settings.svg'); } +.mx_UserSettingsDialog_appearanceIcon::before { + mask-image: url('$(res)/img/feather-customised/brush.svg'); +} + .mx_UserSettingsDialog_voiceIcon::before { mask-image: url('$(res)/img/feather-customised/phone.svg'); } diff --git a/res/css/views/elements/_Slider.scss b/res/css/views/elements/_Slider.scss new file mode 100644 index 00000000000..58ba2813b4d --- /dev/null +++ b/res/css/views/elements/_Slider.scss @@ -0,0 +1,99 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +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_Slider { + position: relative; + margin: 0px; + flex-grow: 1; +} + +.mx_Slider_dotContainer { + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.mx_Slider_bar { + display: flex; + box-sizing: border-box; + position: absolute; + height: 1em; + width: 100%; + padding: 0 0.5em; // half the width of a dot. + align-items: center; +} + +.mx_Slider_bar > hr { + width: 100%; + height: 0.4em; + background-color: $slider-background-color; + border: 0; +} + +.mx_Slider_selection { + display: flex; + align-items: center; + width: calc(100% - 1em); // 2 * half the width of a dot + height: 1em; + position: absolute; + pointer-events: none; +} + +.mx_Slider_selectionDot { + position: absolute; + width: 1.1em; + height: 1.1em; + background-color: $slider-selection-color; + border-radius: 50%; + box-shadow: 0 0 6px lightgrey; + z-index: 10; +} + +.mx_Slider_selection > hr { + margin: 0; + border: 0.2em solid $slider-selection-color; +} + +.mx_Slider_dot { + height: 1em; + width: 1em; + border-radius: 50%; + background-color: $slider-background-color; + z-index: 0; +} + +.mx_Slider_dotActive { + background-color: $slider-selection-color; +} + +.mx_Slider_dotValue { + display: flex; + flex-direction: column; + align-items: center; + color: $slider-background-color; +} + +// The following is a hack to center the labels without adding +// any width to the slider's dots. +.mx_Slider_labelContainer { + width: 1em; +} + +.mx_Slider_label { + position: relative; + width: fit-content; + left: -50%; +} diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index 5bc7d5624d4..759dce5afa4 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -20,7 +20,7 @@ limitations under the License. flex-direction: row; align-items: center; cursor: pointer; - height: $font-34px; + height: 32px; margin: 0; padding: 0 8px 0 10px; position: relative; @@ -81,6 +81,7 @@ limitations under the License. .mx_RoomTile_avatar_container { position: relative; + display: flex; } .mx_RoomTile_avatar { diff --git a/res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss b/res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss new file mode 100644 index 00000000000..e82ae3c5757 --- /dev/null +++ b/res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss @@ -0,0 +1,45 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +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_AppearanceUserSettingsTab_fontSlider, +.mx_AppearanceUserSettingsTab_themeSection .mx_Field, +.mx_AppearanceUserSettingsTab_fontScaling .mx_Field { + @mixin mx_Settings_fullWidthField; +} + +.mx_AppearanceUserSettingsTab_fontSlider { + display: flex; + flex-direction: row; + align-items: center; + padding: 15px; + background: $font-slider-bg-color; + border-radius: 10px; + font-size: 10px; + margin-top: 24px; + margin-bottom: 24px; +} + +.mx_AppearanceUserSettingsTab_fontSlider_smallText { + font-size: 15px; + padding-right: 20px; + padding-left: 5px; +} + +.mx_AppearanceUserSettingsTab_fontSlider_largeText { + font-size: 18px; + padding-left: 20px; + padding-right: 5px; +} diff --git a/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss b/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss index 95a46b51ee9..6c9b89cf5a5 100644 --- a/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_GeneralUserSettingsTab.scss @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_GeneralUserSettingsTab_changePassword .mx_Field, -.mx_GeneralUserSettingsTab_themeSection .mx_Field { +.mx_GeneralUserSettingsTab_changePassword .mx_Field { @mixin mx_Settings_fullWidthField; } diff --git a/res/img/feather-customised/brush.svg b/res/img/feather-customised/brush.svg new file mode 100644 index 00000000000..d7f2738629a --- /dev/null +++ b/res/img/feather-customised/brush.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 6224c0820fe..9fb36ef1a3e 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -180,6 +180,9 @@ $breadcrumb-placeholder-bg-color: #272c35; $user-tile-hover-bg-color: $header-panel-bg-color; +// FontSlider colors +$font-slider-bg-color: $room-highlight-color; + // ***** Mixins! ***** @define-mixin mx_DialogButton { diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index f5f30133540..78fe2a74c53 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -262,6 +262,10 @@ $togglesw-off-color: #c1c9d6; $togglesw-on-color: $accent-color; $togglesw-ball-color: #fff; +// Slider +$slider-selection-color: $accent-color; +$slider-background-color: #c1c9d6; + $progressbar-color: #000; $room-warning-bg-color: $yellow-background; @@ -302,6 +306,9 @@ $breadcrumb-placeholder-bg-color: #e8eef5; $user-tile-hover-bg-color: $header-panel-bg-color; +// FontSlider colors +$font-slider-bg-color: rgba($input-darker-bg-color, 0.2); + // ***** Mixins! ***** @define-mixin mx_DialogButton { diff --git a/src/FontWatcher.js b/src/FontWatcher.js new file mode 100644 index 00000000000..006df202ad1 --- /dev/null +++ b/src/FontWatcher.js @@ -0,0 +1,51 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +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 dis from './dispatcher/dispatcher'; +import SettingsStore, {SettingLevel} from './settings/SettingsStore'; + +export class FontWatcher { + static MIN_SIZE = 13; + static MAX_SIZE = 20; + + constructor() { + this._dispatcherRef = null; + } + + start() { + this._setRootFontSize(SettingsStore.getValue("fontSize")); + this._dispatcherRef = dis.register(this._onAction); + } + + stop() { + dis.unregister(this._dispatcherRef); + } + + _onAction = (payload) => { + if (payload.action === 'update-font-size') { + this._setRootFontSize(payload.size); + } + }; + + _setRootFontSize = (size) => { + const fontSize = Math.max(Math.min(FontWatcher.MAX_SIZE, size), FontWatcher.MIN_SIZE); + + if (fontSize != size) { + SettingsStore.setValue("fontSize", null, SettingLevel.Device, fontSize); + } + document.querySelector(":root").style.fontSize = fontSize + "px"; + }; +} diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 670a017934b..48dc72f4fa0 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -60,6 +60,7 @@ import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../utils/AutoDisco import DMRoomMap from '../../utils/DMRoomMap'; import { countRoomsWithNotif } from '../../RoomNotifs'; import { ThemeWatcher } from "../../theme"; +import { FontWatcher } from '../../FontWatcher'; import { storeRoomAliasInCache } from '../../RoomAliasCache'; import { defer, IDeferred } from "../../utils/promise"; import ToastStore from "../../stores/ToastStore"; @@ -216,6 +217,7 @@ export default class MatrixChat extends React.PureComponent { private readonly loggedInView: React.RefObject; private readonly dispatcherRef: any; private readonly themeWatcher: ThemeWatcher; + private readonly fontWatcher: FontWatcher; constructor(props, context) { super(props, context); @@ -283,8 +285,11 @@ export default class MatrixChat extends React.PureComponent { this.accountPasswordTimer = null; this.dispatcherRef = dis.register(this.onAction); + this.themeWatcher = new ThemeWatcher(); + this.fontWatcher = new FontWatcher(); this.themeWatcher.start(); + this.fontWatcher.start(); this.focusComposer = false; @@ -367,6 +372,7 @@ export default class MatrixChat extends React.PureComponent { Lifecycle.stopMatrixClient(); dis.unregister(this.dispatcherRef); this.themeWatcher.stop(); + this.fontWatcher.stop(); window.removeEventListener('resize', this.handleResize); this.state.resizeNotifier.removeListener("middlePanelResized", this.dispatchTimelineResize); diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index d1abacd2d8f..090f3de22a4 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -32,7 +32,7 @@ import RoomTile from "../views/rooms/RoomTile"; import LazyRenderList from "../views/elements/LazyRenderList"; import {_t} from "../../languageHandler"; import {RovingTabIndexWrapper} from "../../accessibility/RovingTabIndex"; -import toRem from "../../utils/rem"; +import {toPx} from "../../utils/units"; // turn this on for drop & drag console debugging galore const debug = false; @@ -420,7 +420,7 @@ export default class RoomSubList extends React.PureComponent { setHeight = (height) => { if (this._subList.current) { - this._subList.current.style.height = toRem(height); + this._subList.current.style.height = toPx(height); } this._updateLazyRenderHeight(height); }; diff --git a/src/components/views/avatars/BaseAvatar.js b/src/components/views/avatars/BaseAvatar.js index 81fbc08c0ff..704e6438c87 100644 --- a/src/components/views/avatars/BaseAvatar.js +++ b/src/components/views/avatars/BaseAvatar.js @@ -24,7 +24,7 @@ import * as AvatarLogic from '../../../Avatar'; import SettingsStore from "../../../settings/SettingsStore"; import AccessibleButton from '../elements/AccessibleButton'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import toRem from "../../../utils/rem"; +import {toPx} from "../../../utils/units"; export default createReactClass({ displayName: 'BaseAvatar', @@ -166,9 +166,9 @@ export default createReactClass({ const textNode = (