From 203172c886b326782e66bf53d8dbd8d00104ff3c Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 17 Jan 2017 14:11:01 +0000 Subject: [PATCH 1/6] typos --- src/components/structures/ContextualMenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index fecb2a1841..da419897dc 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -67,7 +67,7 @@ module.exports = { chevronOffset.top = props.chevronOffset; } - // To overide the deafult chevron colour, if it's been set + // To override the default chevron colour, if it's been set var chevronCSS = ""; if (props.menuColour) { chevronCSS = ` From a18d94099e76232454ed3feefa837cfe8da532ab Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 17 Jan 2017 14:11:15 +0000 Subject: [PATCH 2/6] switch to using for edit button --- src/components/views/rooms/EventTile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 42dbe78630..ef578d47db 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -263,7 +263,7 @@ module.exports = WithMatrixClient(React.createClass({ // The window X and Y offsets are to adjust position when zoomed in to page var x = buttonRect.right + window.pageXOffset; - var y = (buttonRect.top + (e.target.height / 2) + window.pageYOffset) - 19; + var y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19; var self = this; ContextualMenu.createMenu(MessageContextMenu, { chevronOffset: 10, @@ -465,7 +465,7 @@ module.exports = WithMatrixClient(React.createClass({ } var editButton = ( - Options + ); var e2e; From c2cdb626bdf3b8156168a6594ba1c8462d482c2f Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 17 Jan 2017 19:13:04 +0000 Subject: [PATCH 3/6] let the tinter handle 'white' highlights of SVGs too --- src/Tinter.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Tinter.js b/src/Tinter.js index 534a1d810b..c18d3068a7 100644 --- a/src/Tinter.js +++ b/src/Tinter.js @@ -42,6 +42,7 @@ var keyHex = [ "#76CFA6", // Vector Green "#EAF5F0", // Vector Light Green "#D3EFE1", // BottomLeftMenu overlay (20% Vector Green overlaid on Vector Light Green) + "#FFFFFF", // white highlights of the SVGs (for switching to dark theme) ]; // cache of our replacement colours @@ -50,6 +51,7 @@ var colors = [ keyHex[0], keyHex[1], keyHex[2], + keyHex[3], ]; var cssFixups = [ @@ -172,7 +174,7 @@ module.exports = { tintables.push(tintable); }, - tint: function(primaryColor, secondaryColor, tertiaryColor) { + tint: function(primaryColor, secondaryColor, tertiaryColor, whiteColor) { if (!cached) { calcCssFixups(); @@ -203,14 +205,19 @@ module.exports = { tertiaryColor = rgbToHex(rgb1); } + if (!whiteColor) { + whiteColor = colors[3]; + } + if (colors[0] === primaryColor && colors[1] === secondaryColor && - colors[2] === tertiaryColor) + colors[2] === tertiaryColor && + colors[3] === whiteColor) { return; } - colors = [primaryColor, secondaryColor, tertiaryColor]; + colors = [primaryColor, secondaryColor, tertiaryColor, whiteColor]; if (DEBUG) console.log("Tinter.tint"); From 8288eb730c0ddd7239dbb542031dd6b56de4eeac Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 17 Jan 2017 19:13:23 +0000 Subject: [PATCH 4/6] a rather hacky implementation of theme switching --- src/components/structures/MatrixChat.js | 42 +++++++++++++++ src/components/structures/UserSettings.js | 63 ++++++++++++++++++----- 2 files changed, 93 insertions(+), 12 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index c47109db94..79e93bb990 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -25,6 +25,7 @@ var SdkConfig = require("../../SdkConfig"); var ContextualMenu = require("./ContextualMenu"); var RoomListSorter = require("../../RoomListSorter"); var UserActivity = require("../../UserActivity"); +var UserSettingsStore = require('../../UserSettingsStore'); var Presence = require("../../Presence"); var dis = require("../../dispatcher"); @@ -456,6 +457,9 @@ module.exports = React.createClass({ middleOpacity: payload.middleOpacity, }); break; + case 'set_theme': + this._onSetTheme(payload.value); + break; case 'on_logged_in': this._onLoggedIn(); break; @@ -584,6 +588,44 @@ module.exports = React.createClass({ _onLoadCompleted: function() { this.props.onLoadCompleted(); this.setState({loading: false}); + + // set up the right theme. + // XXX: this will temporarily flicker the wrong CSS. + dis.dispatch({ + action: 'set_theme', + value: UserSettingsStore.getSyncedSetting('theme') + }); + }, + + /** + * Called whenever someone changes the theme + */ + _onSetTheme: function(theme) { + if (!theme) { + theme = 'light'; + } + + var i, a; + for (i = 0; (a = document.getElementsByTagName("link")[i]); i++) { + var href = a.getAttribute("href"); + if (href.startsWith("theme-")) { + if (href.startsWith("theme-" + theme + ".")) { + a.disabled = false; + } + else { + a.disabled = true; + } + } + } + + if (theme === 'dark') { + // abuse the tinter to change all the SVG's #fff to #2d2d2d + // XXX: obviously this shouldn't be hardcoded here. + Tinter.tint(undefined, undefined, undefined, '#2d2d2d'); + } + else { + Tinter.tint(undefined, undefined, undefined, '#ffffff'); + } }, /** diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index a41eab3a76..ebfd6dc0a7 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -363,7 +363,23 @@ module.exports = React.createClass({ */ ]; + var themes = [ + { + id: 'theme', + label: 'Light theme', + value: 'light', + }, + { + id: 'theme', + label: 'Dark theme', + value: 'dark', + } + ]; + var syncedSettings = UserSettingsStore.getSyncedSettings(); + if (!syncedSettings.theme) { + syncedSettings.theme = 'light'; + } return (
@@ -379,19 +395,42 @@ module.exports = React.createClass({ Disable inline URL previews by default
+ { settingsLabels.map( setting => { + return
+ UserSettingsStore.setSyncedSetting(setting.id, e.target.checked) } + /> + +
+ })} + { themes.map( setting => { + return
+ { + if (e.target.checked) { + UserSettingsStore.setSyncedSetting(setting.id, setting.value) + } + dis.dispatch({ + action: 'set_theme', + value: setting.value, + }); + } + } + /> + +
+ })} - { settingsLabels.forEach( setting => { -
- UserSettingsStore.setSyncedSetting(setting.id, e.target.checked) } - /> - -
- })} ); }, From 3d30553b7fa21f5884abd26c27212626f38d2ce2 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 18 Jan 2017 14:06:47 +0000 Subject: [PATCH 5/6] review fixes, plus unbreak to work with new webpack layout --- src/Tinter.js | 26 ++- src/components/structures/MatrixChat.js | 9 +- src/components/structures/UserSettings.js | 184 ++++++++++++---------- 3 files changed, 123 insertions(+), 96 deletions(-) diff --git a/src/Tinter.js b/src/Tinter.js index c18d3068a7..4a5e4e453c 100644 --- a/src/Tinter.js +++ b/src/Tinter.js @@ -174,7 +174,7 @@ module.exports = { tintables.push(tintable); }, - tint: function(primaryColor, secondaryColor, tertiaryColor, whiteColor) { + tint: function(primaryColor, secondaryColor, tertiaryColor) { if (!cached) { calcCssFixups(); @@ -205,19 +205,16 @@ module.exports = { tertiaryColor = rgbToHex(rgb1); } - if (!whiteColor) { - whiteColor = colors[3]; - } - if (colors[0] === primaryColor && colors[1] === secondaryColor && - colors[2] === tertiaryColor && - colors[3] === whiteColor) + colors[2] === tertiaryColor) { return; } - colors = [primaryColor, secondaryColor, tertiaryColor, whiteColor]; + colors[0] = primaryColor; + colors[1] = secondaryColor; + colors[2] = tertiaryColor; if (DEBUG) console.log("Tinter.tint"); @@ -231,6 +228,19 @@ module.exports = { }); }, + tintSvgWhite: function(whiteColor) { + if (!whiteColor) { + whiteColor = colors[3]; + } + if (colors[3] === whiteColor) { + return; + } + colors[3] = whiteColor; + tintables.forEach(function(tintable) { + tintable(); + }); + }, + // XXX: we could just move this all into TintableSvg, but as it's so similar // to the CSS fixup stuff in Tinter (just that the fixups are stored in TintableSvg) // keeping it here for now. diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 7d74e2ee02..8917f0535e 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -608,8 +608,9 @@ module.exports = React.createClass({ var i, a; for (i = 0; (a = document.getElementsByTagName("link")[i]); i++) { var href = a.getAttribute("href"); - if (href.startsWith("theme-")) { - if (href.startsWith("theme-" + theme + ".")) { + var match = href.match(/^bundles\/.*\/theme-(.*)\.css$/); + if (match) { + if (match[1] === theme) { a.disabled = false; } else { @@ -621,10 +622,10 @@ module.exports = React.createClass({ if (theme === 'dark') { // abuse the tinter to change all the SVG's #fff to #2d2d2d // XXX: obviously this shouldn't be hardcoded here. - Tinter.tint(undefined, undefined, undefined, '#2d2d2d'); + Tinter.tintSvgWhite('#2d2d2d'); } else { - Tinter.tint(undefined, undefined, undefined, '#ffffff'); + Tinter.tintSvgWhite('#ffffff'); } }, diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index ebfd6dc0a7..a120d365d1 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -32,6 +32,47 @@ var AddThreepid = require('../../AddThreepid'); const REACT_SDK_VERSION = 'dist' in package_json ? package_json.version : package_json.gitHead || ""; + +// Enumerate some simple 'flip a bit' UI settings (if any) +const SETTINGS_LABELS = [ +/* + { + id: 'alwaysShowTimestamps', + label: 'Always show message timestamps', + }, + { + id: 'showTwelveHourTimestamps', + label: 'Show timestamps in 12 hour format (e.g. 2:30pm)', + }, + { + id: 'useCompactLayout', + label: 'Use compact timeline layout', + }, + { + id: 'useFixedWidthFont', + label: 'Use fixed width font', + }, +*/ +]; + +// Enumerate the available themes, with a nice human text label. +// XXX: Ideally we would have a theme manifest or something and they'd be nicely +// packaged up in a single directory, and/or located at the application layer. +// But for now for expedience we just hardcode them here. +const THEMES = [ + { + id: 'theme', + label: 'Light theme', + value: 'light', + }, + { + id: 'theme', + label: 'Dark theme', + value: 'dark', + } +]; + + module.exports = React.createClass({ displayName: 'UserSettings', @@ -93,6 +134,12 @@ module.exports = React.createClass({ middleOpacity: 0.3, }); this._refreshFromServer(); + + var syncedSettings = UserSettingsStore.getSyncedSettings(); + if (!syncedSettings.theme) { + syncedSettings.theme = 'light'; + } + this._syncedSettings = syncedSettings; }, componentDidMount: function() { @@ -342,99 +389,68 @@ module.exports = React.createClass({ _renderUserInterfaceSettings: function() { var client = MatrixClientPeg.get(); - var settingsLabels = [ - /* - { - id: 'alwaysShowTimestamps', - label: 'Always show message timestamps', - }, - { - id: 'showTwelveHourTimestamps', - label: 'Show timestamps in 12 hour format (e.g. 2:30pm)', - }, - { - id: 'useCompactLayout', - label: 'Use compact timeline layout', - }, - { - id: 'useFixedWidthFont', - label: 'Use fixed width font', - }, - */ - ]; - - var themes = [ - { - id: 'theme', - label: 'Light theme', - value: 'light', - }, - { - id: 'theme', - label: 'Dark theme', - value: 'dark', - } - ]; - - var syncedSettings = UserSettingsStore.getSyncedSettings(); - if (!syncedSettings.theme) { - syncedSettings.theme = 'light'; - } - return (

User Interface

-
- UserSettingsStore.setUrlPreviewsDisabled(e.target.checked) } - /> - -
- { settingsLabels.map( setting => { - return
- UserSettingsStore.setSyncedSetting(setting.id, e.target.checked) } - /> - -
- })} - { themes.map( setting => { - return
- { - if (e.target.checked) { - UserSettingsStore.setSyncedSetting(setting.id, setting.value) - } - dis.dispatch({ - action: 'set_theme', - value: setting.value, - }); - } - } - /> - -
- })} + { this._renderUrlPreviewSelector() } + { SETTINGS_LABELS.map( this._renderSyncedSetting ) } + { THEMES.map( this._renderThemeSelector ) }
); }, + _renderUrlPreviewSelector: function() { + return
+ UserSettingsStore.setUrlPreviewsDisabled(e.target.checked) } + /> + +
+ }, + + _renderSyncedSetting: function(setting) { + return
+ UserSettingsStore.setSyncedSetting(setting.id, e.target.checked) } + /> + +
+ }, + + _renderThemeSelector: function(setting) { + return
+ { + if (e.target.checked) { + UserSettingsStore.setSyncedSetting(setting.id, setting.value) + } + dis.dispatch({ + action: 'set_theme', + value: setting.value, + }); + } + } + /> + +
+ }, + _renderCryptoInfo: function() { const client = MatrixClientPeg.get(); const deviceId = client.deviceId; From fc630672378bb292dcde1188255deb830a486596 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 18 Jan 2017 16:36:27 +0000 Subject: [PATCH 6/6] improve commentary --- src/components/structures/UserSettings.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index a120d365d1..5ce9ab1a15 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -33,7 +33,9 @@ const REACT_SDK_VERSION = 'dist' in package_json ? package_json.version : package_json.gitHead || ""; -// Enumerate some simple 'flip a bit' UI settings (if any) +// Enumerate some simple 'flip a bit' UI settings (if any). +// 'id' gives the key name in the im.vector.web.settings account data event +// 'label' is how we describe it in the UI. const SETTINGS_LABELS = [ /* { @@ -56,6 +58,10 @@ const SETTINGS_LABELS = [ ]; // Enumerate the available themes, with a nice human text label. +// 'id' gives the key name in the im.vector.web.settings account data event +// 'value' is the value for that key in the event +// 'label' is how we describe it in the UI. +// // XXX: Ideally we would have a theme manifest or something and they'd be nicely // packaged up in a single directory, and/or located at the application layer. // But for now for expedience we just hardcode them here.