Skip to content

Commit

Permalink
feat(App): Add option to enable dark mode for supported services
Browse files Browse the repository at this point in the history
  • Loading branch information
adlk committed Nov 22, 2018
1 parent fd7df5a commit fd7954f
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/components/settings/services/EditServiceForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ export default @observer class EditServiceForm extends Component {

<div className="settings__settings-group">
<h3>{intl.formatMessage(messages.headlineGeneral)}</h3>
<Toggle field={form.$('isDarkModeEnabled')} />
<Toggle field={form.$('isEnabled')} />
</div>
</div>
Expand Down
11 changes: 11 additions & 0 deletions src/containers/settings/EditServiceScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { defineMessages, intlShape } from 'react-intl';
import UserStore from '../../stores/UserStore';
import RecipesStore from '../../stores/RecipesStore';
import ServicesStore from '../../stores/ServicesStore';
import SettingsStore from '../../stores/SettingsStore';
import Form from '../../lib/Form';
import { gaPage } from '../../lib/analytics';

Expand Down Expand Up @@ -50,6 +51,10 @@ const messages = defineMessages({
id: 'settings.service.form.icon',
defaultMessage: '!!!Custom icon',
},
enableDarkMode: {
id: 'settings.service.form.enableDarkMode',
defaultMessage: '!!!Enable Dark Mode',
},
});

export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component {
Expand Down Expand Up @@ -111,6 +116,11 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
default: null,
type: 'file',
},
isDarkModeEnabled: {
label: intl.formatMessage(messages.enableDarkMode),
value: service.isDarkModeEnabled,
default: this.props.stores.settings.all.app.darkMode,
},
},
};

Expand Down Expand Up @@ -238,6 +248,7 @@ EditServiceScreen.wrappedComponent.propTypes = {
user: PropTypes.instanceOf(UserStore).isRequired,
recipes: PropTypes.instanceOf(RecipesStore).isRequired,
services: PropTypes.instanceOf(ServicesStore).isRequired,
settings: PropTypes.instanceOf(SettingsStore).isRequired,
}).isRequired,
router: PropTypes.shape({
params: PropTypes.shape({
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
"settings.service.form.icon": "Custom icon",
"settings.service.form.iconDelete": "Delete",
"settings.service.form.iconUpload": "Drop your image, or click here",
"settings.service.form.enableDarkMode": "Enable Dark Mode",
"settings.service.error.headline": "Error",
"settings.service.error.goBack": "Back to services",
"settings.service.error.message": "Could not load service recipe.",
Expand Down
6 changes: 6 additions & 0 deletions src/models/Recipe.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import emailParser from 'address-rfc2822';
import semver from 'semver';
import fs from 'fs-extra';
import path from 'path';

export default class Recipe {
id = '';
Expand Down Expand Up @@ -73,4 +75,8 @@ export default class Recipe {

return [];
}

get hasDarkMode() {
return fs.pathExistsSync(path.join(this.path, 'darkmode.css'));
}
}
3 changes: 3 additions & 0 deletions src/models/Service.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default class Service {
@observable iconUrl = '';
@observable hasCustomUploadedIcon = false;
@observable hasCrashed = false;
@observable isDarkModeEnabled = false;
constructor(data, recipe) {
if (!data) {
Expand Down Expand Up @@ -64,6 +65,8 @@ export default class Service {
this.isMuted = data.isMuted !== undefined ? data.isMuted : this.isMuted;
this.isDarkModeEnabled = data.isDarkModeEnabled !== undefined ? data.isDarkModeEnabled : this.isDarkModeEnabled;
this.hasCustomUploadedIcon = data.hasCustomIcon !== undefined ? data.hasCustomIcon : this.hasCustomUploadedIcon;
this.recipe = recipe;
Expand Down
8 changes: 8 additions & 0 deletions src/stores/ServicesStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,14 @@ export default class ServicesStore extends Store {
await request._promise;
this.actionStatus = request.result.status;

if (service.isEnabled) {
this._sendIPCMessage({
serviceId,
channel: 'service-settings-update',
args: newData,
});
}

if (redirect) {
this.stores.router.push('/settings/services');
gaEvent('Service', 'update', service.recipe.id);
Expand Down
28 changes: 28 additions & 0 deletions src/webview/darkmode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import path from 'path';
import fs from 'fs-extra';

const ID = 'franz-theme-dark-mode';

export function injectDarkModeStyle(recipePath) {
const darkModeStyle = path.join(recipePath, 'darkmode.css');
if (fs.pathExistsSync(darkModeStyle)) {
const data = fs.readFileSync(darkModeStyle);
const styles = document.createElement('style');
styles.id = ID;
styles.innerHTML = data.toString();

document.querySelector('head').appendChild(styles);
}
}

export function removeDarkModeStyle() {
const style = document.querySelector(`#${ID}`);

if (style) {
style.remove();
}
}

export function isDarkModeStyleInjected() {
return !!document.querySelector(`#${ID}`);
}
33 changes: 30 additions & 3 deletions src/webview/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@ import { isDevMode } from '../environment';
import RecipeWebview from './lib/RecipeWebview';

import Spellchecker from './spellchecker';
import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode';
import './notifications';

const debug = require('debug')('Franz:Plugin');

window.franzSettings = {};
let serviceData;

ipcRenderer.on('initializeRecipe', (e, data) => {
const modulePath = path.join(data.recipe.path, 'webview.js');
// Delete module from cache
delete require.cache[require.resolve(modulePath)];
try {
// eslint-disable-next-line
require(modulePath)(new RecipeWebview(), data);
debug('Initialize Recipe');
debug('Initialize Recipe', data);

serviceData = data;

if (data.isDarkModeEnabled) {
injectDarkModeStyle(data.recipe.path);
debug('Add dark theme styles');
}
} catch (err) {
debug('Recipe initialization failed', err);
}
Expand All @@ -33,11 +44,27 @@ new ContextMenuListener((info) => { // eslint-disable-line
});

ipcRenderer.on('settings-update', (e, data) => {
spellchecker.toggleSpellchecker(data.enableSpellchecking);
debug('Settings update received', data);

spellchecker.toggleSpellchecker(data.enableSpellchecking);
window.franzSettings = data;
});

ipcRenderer.on('service-settings-update', (e, data) => {
debug('Service settings update received', data);

if (data.isDarkModeEnabled && !isDarkModeStyleInjected()) {
injectDarkModeStyle(serviceData.recipe.path);

debug('Enable service dark mode');
} else if (!data.isDarkModeEnabled && isDarkModeStyleInjected()) {
removeDarkModeStyle();

debug('Disable service dark mode');
}
});

// initSpellche
// initSpellchecker

document.addEventListener('DOMContentLoaded', () => {
ipcRenderer.sendToHost('hello');
Expand Down

0 comments on commit fd7954f

Please sign in to comment.