M app/javascript/flavours/glitch/containers/mastodon.jsx => app/javascript/flavours/glitch/containers/mastodon.jsx +13 -9
@@ 19,6 19,8 @@ import initialState, { title as siteTitle } from 'flavours/glitch/initial_state'
import { IntlProvider } from 'flavours/glitch/locales';
import { store } from 'flavours/glitch/store';
+import { ThemeComponent } from './theme_component';
+
const title = process.env.NODE_ENV === 'production' ? siteTitle : `${siteTitle} (Dev)`;
const hydrateAction = hydrateStore(initialState);
@@ 79,15 81,17 @@ export default class Mastodon extends PureComponent {
return (
<IntlProvider>
<ReduxProvider store={store}>
- <ErrorBoundary>
- <Router>
- <ScrollContext shouldUpdateScroll={this.shouldUpdateScroll}>
- <Route path='/' component={UI} />
- </ScrollContext>
- </Router>
-
- <Helmet defaultTitle={title} titleTemplate={`%s - ${title}`} />
- </ErrorBoundary>
+ <ThemeComponent>
+ <ErrorBoundary>
+ <Router>
+ <ScrollContext shouldUpdateScroll={this.shouldUpdateScroll}>
+ <Route path='/' component={UI} />
+ </ScrollContext>
+ </Router>
+
+ <Helmet defaultTitle={title} titleTemplate={`%s - ${title}`} />
+ </ErrorBoundary>
+ </ThemeComponent>
</ReduxProvider>
</IntlProvider>
);
A app/javascript/flavours/glitch/containers/theme_component.jsx => app/javascript/flavours/glitch/containers/theme_component.jsx +36 -0
@@ 0,0 1,36 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+
+import { useAppSelector } from 'flavours/glitch/store';
+
+const ThemeComponent = ({ children }) => {
+ const theme = useAppSelector(
+ (state) => state.getIn(['local_settings', 'theme']) ?? 'mastodon-light',
+ );
+
+ let href;
+ switch (true) {
+ case theme === 'mastodon':
+ href = '';
+ break;
+ case theme === 'mastodon-light':
+ href = '/packs/css/skins/glitch/mastodon-light/common.css';
+ break;
+ case theme === 'contrast':
+ href = '/packs/css/skins/glitch/contrast/common.css';
+ break;
+ }
+
+ return (
+ <>
+ {href !== '' ? <link rel='stylesheet' media='all' href={href} /> : null}
+ {children}
+ </>
+ );
+};
+
+ThemeComponent.propTypes = {
+ children: PropTypes.node,
+};
+
+export { ThemeComponent };
M app/javascript/flavours/glitch/features/local_settings/page/index.jsx => app/javascript/flavours/glitch/features/local_settings/page/index.jsx +13 -0
@@ 54,6 54,19 @@ class LocalSettingsPage extends PureComponent {
<h1><FormattedMessage id='settings.general' defaultMessage='General' /></h1>
<LocalSettingsPageItem
settings={settings}
+ item={['theme']}
+ id='mastodon-settings--theme'
+ options={[
+ { value: 'mastodon-light', message: 'Light' },
+ { value: 'mastodon', message: 'Dark' },
+ { value: 'contrast', message: 'High contrast' },
+ ]}
+ onChange={onChange}
+ >
+ <FormattedMessage id='settings.theme' defaultMessage='Theme' />
+ </LocalSettingsPageItem>
+ <LocalSettingsPageItem
+ settings={settings}
item={['show_reply_count']}
id='mastodon-settings--reply-count'
onChange={onChange}
M app/javascript/flavours/glitch/reducers/local_settings.js => app/javascript/flavours/glitch/reducers/local_settings.js +1 -0
@@ 62,6 62,7 @@ const initialState = ImmutableMap({
media: true,
visibility: true,
}),
+ theme: 'mastodon-light',
});
const hydrate = (state, localSettings) => state.mergeDeep(localSettings);