Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

MM-23853 Support dark mode and light mode syncing with OS theme setting #8804

Closed

Conversation

komik966
Copy link
Contributor

@komik966 komik966 commented Sep 8, 2021

Summary

This PR adds support for dark mode and light mode syncing with OS theme setting

Ticket Link

mattermost/mattermost#15975

Related Pull Requests

Screenshots

demo.mp4

Release Note

Added support for dark mode and light mode syncing with OS theme setting

@mattermod
Copy link
Contributor

Hello @komik966,

Thanks for your pull request! A Core Committer will review your pull request soon. For code contributions, you can learn more about the review process here.

@mattermod mattermod added 2: Dev Review Requires review by a core commiter 3: QA Review Requires review by a QA tester labels Sep 8, 2021
@komik966 komik966 marked this pull request as draft September 8, 2021 11:09
@komik966
Copy link
Contributor Author

komik966 commented Sep 8, 2021

I'm opening as draft because it requires unit tests addition and e2e tests fixing.

Right after signing in, default theme is used instead one from user preferences. It's known issue to me, I'm going to fix it.

@mattermod
Copy link
Contributor

This PR has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

/cc @jasonblais @jfrerich @emilyacook

@hmhealey
Copy link
Member

hmhealey commented Oct 5, 2021

Hi @komik966. Apologies for the delay in reviews here. I'm not sure why our integration didn't assign reviewers, so this sort of got missed out on

@komik966
Copy link
Contributor Author

komik966 commented Oct 5, 2021

@hmhealey No problem. Recently I'm busy, so I might be slow to respond.

@esethna
Copy link
Contributor

esethna commented Oct 6, 2021

@deanwhillier would appreciate your review here considering the theming work you've been doing recently

Copy link
Contributor

@larkox larkox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. A few nits here and there. Would be nice to have them solved before merge, but not blocking.

import {ThemeKey} from 'mattermost-redux/types/themes';

export const getAllowedThemes = createSelector('getAllowedThemes', getConfig, (config) => {
const allowedThemes = (config.AllowedThemes && config.AllowedThemes.split(',')) || [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we simplify this by doing config.AllowedThemes?.split(',') || []?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. This code was moved from:

const allowedThemes = (config.AllowedThemes && config.AllowedThemes.split(',')) || [];

I think @typescript-eslint/prefer-optional-chain would be useful inside eslint config.

Comment on lines +10 to +12
const hasAllowedThemes = allowedThemes.length > 1 || (allowedThemes[0] && allowedThemes[0].trim().length > 0);
const themesKeys = Object.keys(Preferences.THEMES) as ThemeKey[];
return themesKeys.filter((key) => !hasAllowedThemes || allowedThemes.indexOf(key) >= 0).map((key) => Preferences.THEMES[key]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am struggling to grasp this logic. Do you mind explaining it to me?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently this logic sits here:

const allowedThemes = this.props.allowedThemes;
const hasAllowedThemes = allowedThemes.length > 1 || (allowedThemes[0] && allowedThemes[0].trim().length > 0);
for (const k in Preferences.THEMES) {
if (Preferences.THEMES.hasOwnProperty(k)) {
if (hasAllowedThemes && allowedThemes.indexOf(k) < 0) {
continue;
}

In my implementation filter function requires negation of hasAllowedThemes && allowedThemes.indexOf(k) < 0. I used De Morgan's law (https://en.wikipedia.org/wiki/De_Morgan%27s_laws) to change hasAllowedThemes && allowedThemes.indexOf(k) < 0 -> !hasAllowedThemes || allowedThemes.indexOf(key) >= 0.

return (
<>
<div className='theme-chooser-header'>{header}</div>
<div className='themes-grid'>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance this div may be empty? If so, is there any visual concern that we may want to address? (May be out of the scope of this PR)

>
{theme.type?.toLowerCase() === allowedTheme.type?.toLowerCase() && <span className='fa fa-check-circle themes-grid__thumbnail-active-check'/>}
<ThemeThumbnail
themeKey={allowedTheme.type as string}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here is because it may be undefined? Should we instead do something like allowedTheme.type!?


import {Preferences} from 'mattermost-redux/constants';

import {getAllowedThemes} from '../../../../../selectors/theme';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use a better route?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be able to use this:

Suggested change
import {getAllowedThemes} from '../../../../../selectors/theme';
import {getAllowedThemes} from 'selectors/theme';

Copy link
Contributor

@deanwhillier deanwhillier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks really good @komik966! A few things for your consideration. Also, I still need to go through 'components/user_settings/display/user_settings_theme/expanded/expanded.tsx', but thought I'd post what I have for now. Thanks for your work on this and apologies if the recent theme updates added more work for you!

I also have a couple questions to confirm:

  1. What happens when allowed themes only contain light or dark themes?
    • With and without custom themes enabled
  2. What happens if allowed themes are changed after an os sync’d theme pair has been selected?

@esethna, FYI for followup consideration, the theme thumbnails need to be made accessible. They were already inaccessible before, so a separate ticket/PR would be good. I also need to tweak the theme SVG thumbnail a bit based on the mobile thumbnail I did.

Comment on lines +143 to +144
case GeneralTypes.OS_COLOR_SCHEME_INIT:
case GeneralTypes.OS_COLOR_SCHEME_CHANGED:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since ‘OS_COLOR_SCHEME_INIT’ and ‘OS_COLOR_SCHEME_CHANGED’ in essence do the same thing, would it make sense to maybe combine them into one action type using something like ‘SET_OS_COLOR_SCHEME’ or ‘OS_COLOR_SCHEME_SET’ to simplify things a bit?

@@ -3353,14 +3353,14 @@
"user.settings.advance.sendTitle": "Wysyłaj wiadomość przy użyciu Ctrl+Enter",
"user.settings.advance.sendTitle.mac": "Wysyłaj wiadomość przy użyciu Ctrl+Enter",
"user.settings.advance.title": "Zaawansowane Ustawienia",
"user.settings.custom_theme.advancedThemeEditing": "Zaawansowana edycja motywu",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only i18n/en.json strings need to be provided, the rest of the language files are auto-generated by the translation build process. If you're interested, feel free to provide these translations using our translation server and get assistance over in our community translation channel.

@@ -12,6 +12,7 @@ export type ThemeType = 'Denim' | 'Sapphire' | 'Quartz' | 'Indigo' | 'Onyx';
export type Theme = {
[key: string]: string | undefined;
type?: ThemeType | 'custom';
colorScheme?: 'light' | 'dark';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use the OsColorSchemeName type from packages/mattermost-redux/src/types/general.ts here?

Comment on lines +37 to +43
type Props = {
selected: boolean;
updateSection: (section: string) => void;
setRequireConfirm: (requireConfirm?: boolean) => void;
setEnforceFocus: (enforceFocus?: boolean) => void;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I'm not sure if we have a standard for this yet or not, but I think the Props type usually lives at the top of component from what I've seen so far.


const UserSettingsTheme: React.FC<Props> = ({selected, updateSection, setRequireConfirm, setEnforceFocus}: Props) => {
return selected ? (
<Expanded
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we maybe use a slightly more descriptive component name here? Something like UserSettingsExpanded?

onClick={onCustomThemeClick}
>
{customThemeSelected && <span className='fa fa-check-circle themes-grid__thumbnail-active-check'/>}
<span className='fa fa-pencil'/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Palette icon is available in compass-icons, our new custom icon font (already available in the web app)
- the following should do the trick with an additional style update to set the font-size to 31.2px (according to the design)

https://mattermost.github.io/compass-icons/

Suggested change
<span className='fa fa-pencil'/>
<i className='icon icon-palette-outline'/>

})}
onClick={onCustomThemeClick}
>
{customThemeSelected && <span className='fa fa-check-circle themes-grid__thumbnail-active-check'/>}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use our new custom icon font for this now. :)

https://mattermost.github.io/compass-icons/

Suggested change
{customThemeSelected && <span className='fa fa-check-circle themes-grid__thumbnail-active-check'/>}
{customThemeSelected && <i className='icon icon-check-circle themes-grid__thumbnail-active-check'/>}

/>
<div className='header__icon'>
<LocalizedIcon
className='fa fa-plus'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use compass-icons icon font here.

https://mattermost.github.io/compass-icons/

title={{id: t('generic_icons.expand'), defaultMessage: 'Expand Icon'}}
/>
<LocalizedIcon
className='fa fa-minus'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use compass-icons icon font here.

https://mattermost.github.io/compass-icons/


export const getAllowedThemes = createSelector('getAllowedThemes', getConfig, (config) => {
const allowedThemes = (config.AllowedThemes && config.AllowedThemes.split(',')) || [];
const hasAllowedThemes = allowedThemes.length > 1 || (allowedThemes[0] && allowedThemes[0].trim().length > 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: ‘hasAllowedThemes’ seems to be returning undefined instead of false if allowedThemes haven't been defined, maybe switch to ‘??’ Instead of ‘||’?

@deanwhillier
Copy link
Contributor

@komik966, I was thinking we should maybe also update setThemeDefaults to add the new colorScheme value to old custom themes that don't have yet have it by defaulting to light? That function is intended to fill in missing values and transform old to new values as needed.

packages/mattermost-redux/src/utils/theme_utils.ts

@mattermod
Copy link
Contributor

This PR has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

/cc @jasonblais @jfrerich @emilyacook

@esethna
Copy link
Contributor

esethna commented Oct 26, 2021

@komik966 let us know if you have questions about Dean's feedback?

@komik966
Copy link
Contributor Author

@esethna As far no questions. I'll address all comments this weekend.

@komik966
Copy link
Contributor Author

komik966 commented Nov 1, 2021

I will continue covering the comments this week

@mattermod
Copy link
Contributor

This PR has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

/cc @jasonblais @jfrerich @emilyacook

@pat-s
Copy link

pat-s commented Dec 2, 2021

@komik966 Would love to see this PR getting merged :)

@esethna
Copy link
Contributor

esethna commented Feb 1, 2022

Hey @komik966! How's this coming? We're really excited about this feature and would love to get this in!

@komik966
Copy link
Contributor Author

komik966 commented Feb 8, 2022

Hi, @esethna! I didn't make progress here.
But the good news is that I finished some activities which prevented me to continue work on this in the last few months (months! 😮)
So please expect some new changes here till the end of this week.

@esethna
Copy link
Contributor

esethna commented Feb 8, 2022

@komik966 that's great news, looking forward to it! Thanks!

I'm going to introduce @laneycs who will be the PM that takes over this project (OS theme syncing). Laney here are the related PRs for server and mobile in addition to this one for web.

@esethna esethna closed this Feb 8, 2022
@esethna esethna reopened this Feb 8, 2022
@esethna esethna requested a review from laneycs February 8, 2022 22:35
@esethna
Copy link
Contributor

esethna commented Apr 5, 2022

@komik966 just checking how this is going and if you're still working on it? cc// @laneycs

@komik966
Copy link
Contributor Author

komik966 commented Apr 5, 2022

@komik966 komik966 closed this Apr 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
2: Dev Review Requires review by a core commiter 3: QA Review Requires review by a QA tester Hacktoberfest Lifecycle/1:stale release-note
Projects
None yet
9 participants