From 891a7d6642f5e8c4d4f56280e29489524f0d5286 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 15 Nov 2018 22:10:02 +0100 Subject: Fix linting errors --- src/components/settings/services/EditServiceForm.js | 3 +-- src/components/settings/services/ServiceError.js | 3 +-- src/components/settings/services/ServiceItem.js | 3 +-- src/components/settings/services/ServicesDashboard.js | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) (limited to 'src/components/settings/services') diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index f6f2df2f3..29e49ada2 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js @@ -94,8 +94,7 @@ const messages = defineMessages({ }, }); -@observer -export default class EditServiceForm extends Component { +export default @observer class EditServiceForm extends Component { static propTypes = { recipe: PropTypes.instanceOf(Recipe).isRequired, service(props, propName) { diff --git a/src/components/settings/services/ServiceError.js b/src/components/settings/services/ServiceError.js index 1f1512927..3cfc080d6 100644 --- a/src/components/settings/services/ServiceError.js +++ b/src/components/settings/services/ServiceError.js @@ -25,8 +25,7 @@ const messages = defineMessages({ }, }); -@observer -export default class ServiceError extends Component { +export default @observer class ServiceError extends Component { static contextTypes = { intl: intlShape, }; diff --git a/src/components/settings/services/ServiceItem.js b/src/components/settings/services/ServiceItem.js index 9743315b0..84080519b 100644 --- a/src/components/settings/services/ServiceItem.js +++ b/src/components/settings/services/ServiceItem.js @@ -22,8 +22,7 @@ const messages = defineMessages({ }, }); -@observer -export default class ServiceItem extends Component { +export default @observer class ServiceItem extends Component { static propTypes = { service: PropTypes.instanceOf(ServiceModel).isRequired, goToServiceForm: PropTypes.func.isRequired, diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js index 20e451f01..e7dfaf106 100644 --- a/src/components/settings/services/ServicesDashboard.js +++ b/src/components/settings/services/ServicesDashboard.js @@ -49,8 +49,7 @@ const messages = defineMessages({ }, }); -@observer -export default class ServicesDashboard extends Component { +export default @observer class ServicesDashboard extends Component { static propTypes = { services: MobxPropTypes.arrayOrObservableArray.isRequired, isLoading: PropTypes.bool.isRequired, -- cgit v1.2.3-70-g09d2 From 972aded4500cc7851bc27f50e765572de903f6ed Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 21 Nov 2018 13:59:04 +0100 Subject: Disable button when form is pristine and user input is required --- src/components/settings/services/EditServiceForm.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/components/settings/services') diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index 29e49ada2..6893ef0a2 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js @@ -201,6 +201,8 @@ export default @observer class EditServiceForm extends Component { activeTabIndex = 2; } + const requiresUserInput = !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl); + return (
@@ -339,6 +341,7 @@ export default @observer class EditServiceForm extends Component { type="submit" label={intl.formatMessage(messages.saveService)} htmlForm="form" + disabled={form.isPristine && requiresUserInput} /> )}
-- cgit v1.2.3-70-g09d2 From 74ef57050b84b436f5f839749551b0b25476c898 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 21 Nov 2018 22:30:49 +0100 Subject: Fix disable save service button --- src/components/settings/services/EditServiceForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/components/settings/services') diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index 6893ef0a2..7aa632f29 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js @@ -341,7 +341,7 @@ export default @observer class EditServiceForm extends Component { type="submit" label={intl.formatMessage(messages.saveService)} htmlForm="form" - disabled={form.isPristine && requiresUserInput} + disabled={action !== 'edit' && form.isPristine && requiresUserInput} /> )}
-- cgit v1.2.3-70-g09d2 From fd7954fef99d59ca0aa9f2b468afea3463ef2202 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 22 Nov 2018 11:36:11 +0100 Subject: feat(App): Add option to enable dark mode for supported services --- .../settings/services/EditServiceForm.js | 1 + src/containers/settings/EditServiceScreen.js | 11 ++++++++ src/i18n/locales/en-US.json | 1 + src/models/Recipe.js | 6 ++++ src/models/Service.js | 3 ++ src/stores/ServicesStore.js | 8 ++++++ src/webview/darkmode.js | 28 ++++++++++++++++++ src/webview/plugin.js | 33 ++++++++++++++++++++-- 8 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 src/webview/darkmode.js (limited to 'src/components/settings/services') diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index 7aa632f29..f9afe4c8d 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js @@ -304,6 +304,7 @@ export default @observer class EditServiceForm extends Component {

{intl.formatMessage(messages.headlineGeneral)}

+
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js index 1fc6bc85e..e69c2c2a8 100644 --- a/src/containers/settings/EditServiceScreen.js +++ b/src/containers/settings/EditServiceScreen.js @@ -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'; @@ -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 { @@ -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, + }, }, }; @@ -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({ diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 8b2f763b5..66ec5af84 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -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.", diff --git a/src/models/Recipe.js b/src/models/Recipe.js index 032a9aa19..43c44514c 100644 --- a/src/models/Recipe.js +++ b/src/models/Recipe.js @@ -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 = ''; @@ -73,4 +75,8 @@ export default class Recipe { return []; } + + get hasDarkMode() { + return fs.pathExistsSync(path.join(this.path, 'darkmode.css')); + } } diff --git a/src/models/Service.js b/src/models/Service.js index 4f8767dbe..1bab8bd68 100644 --- a/src/models/Service.js +++ b/src/models/Service.js @@ -28,6 +28,7 @@ export default class Service { @observable iconUrl = ''; @observable hasCustomUploadedIcon = false; @observable hasCrashed = false; + @observable isDarkModeEnabled = false; constructor(data, recipe) { if (!data) { @@ -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; diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index c5822968a..cdb2db142 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -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); diff --git a/src/webview/darkmode.js b/src/webview/darkmode.js new file mode 100644 index 000000000..9830ef33c --- /dev/null +++ b/src/webview/darkmode.js @@ -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}`); +} diff --git a/src/webview/plugin.js b/src/webview/plugin.js index ee8cedbab..e6fdc4efd 100644 --- a/src/webview/plugin.js +++ b/src/webview/plugin.js @@ -6,10 +6,14 @@ 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 @@ -17,7 +21,14 @@ ipcRenderer.on('initializeRecipe', (e, data) => { 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); } @@ -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'); -- cgit v1.2.3-70-g09d2