From 5a3daab446f7a4da9855b6a7bb0469c8cc0476a6 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 14 Mar 2018 15:45:26 +0100 Subject: Fix issue with systemMute handler triggering too many IPC calls --- src/stores/AppStore.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/stores') diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 162422017..d07576569 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -244,7 +244,7 @@ export default class AppStore extends Store { } @action _muteApp({ isMuted, overrideSystemMute = true }) { - this.isSystemMuteOverriden = overrideSystemMute; + this.isSystemMuteOverridden = overrideSystemMute; this.actions.settings.update({ settings: { @@ -368,7 +368,7 @@ export default class AppStore extends Store { _systemDND() { const dnd = getDoNotDisturb(); - if (dnd === this.stores.settings.all.isAppMuted || !this.isSystemMuteOverriden) { + if (dnd !== this.stores.settings.all.isAppMuted && !this.isSystemMuteOverridden) { this.actions.app.muteApp({ isMuted: dnd, overrideSystemMute: false, -- cgit v1.2.3-70-g09d2 From 47885bb51ee1888b3ac851097d2d3bef54c15a0a Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 14 Mar 2018 16:21:08 +0100 Subject: feat(Mac): Add dock bounce when new update is available --- src/stores/AppStore.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/stores') diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index d07576569..76c0222c9 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -98,6 +98,10 @@ export default class AppStore extends Store { ipcRenderer.on('autoUpdate', (event, data) => { if (data.available) { this.updateStatus = this.updateStatusTypes.AVAILABLE; + + if (isMac) { + app.dock.bounce(); + } } if (data.available !== undefined && !data.available) { -- cgit v1.2.3-70-g09d2 From 9b97d1332a1b0f9447ddb560d5ba12d965611f6d Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 14 Mar 2018 16:27:30 +0100 Subject: get test build [skip appveyor] --- src/stores/AppStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stores') diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 76c0222c9..2d0a617a5 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -366,7 +366,7 @@ export default class AppStore extends Store { setTimeout(() => this._reactivateServices(retryCount + 1), 5000); } else { console.debug('reactivateServices: reload Franz'); - window.location.reload(); + // window.location.reload(); } } -- cgit v1.2.3-70-g09d2 From 82e832c09b2e013d3643e02a8a366cd4f3900b63 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 14 Mar 2018 20:37:31 +0100 Subject: feat(Services): Improve performance when reordering services --- src/containers/layout/AppLayoutContainer.js | 2 +- src/stores/ServicesStore.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/stores') diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index e4a9d60c3..075bd5e34 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js @@ -94,7 +94,7 @@ export default class AppLayoutContainer extends Component { const servicesContainer = ( service.isEnabled); + } + @computed get filtered() { return this.all.filter(service => service.name.toLowerCase().includes(this.filterNeedle.toLowerCase())); } -- cgit v1.2.3-70-g09d2 From 88faef416eadc891537f03926160e35245125c72 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Sun, 18 Mar 2018 16:37:21 +0100 Subject: Replace console logs with debugger --- package.json | 1 + src/api/server/LocalApi.js | 8 +++--- src/api/server/ServerApi.js | 60 +++++++++++++++++++++++---------------------- src/lib/analytics.js | 6 +++-- src/stores/RecipesStore.js | 8 +++--- src/stores/RequestStore.js | 4 ++- src/stores/ServicesStore.js | 10 +++++--- yarn.lock | 12 +++++++++ 8 files changed, 66 insertions(+), 43 deletions(-) (limited to 'src/stores') diff --git a/package.json b/package.json index f35da9880..31013baad 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "babel-polyfill": "^6.23.0", "babel-runtime": "^6.23.0", "classnames": "^2.2.5", + "debug-electron": "^0.0.4", "du": "^0.1.0", "electron-fetch": "^1.1.0", "electron-react-titlebar": "^0.7.1", diff --git a/src/api/server/LocalApi.js b/src/api/server/LocalApi.js index aa3a7d655..4d2497c61 100644 --- a/src/api/server/LocalApi.js +++ b/src/api/server/LocalApi.js @@ -3,6 +3,8 @@ import du from 'du'; import { getServicePartitionsDirectory } from '../../helpers/service-helpers.js'; +const debug = require('debug')('LocalApi'); + const { session } = remote; export default class LocalApi { @@ -13,7 +15,7 @@ export default class LocalApi { du(partitionsDir, (err, size) => { if (err) reject(err); - console.debug('LocalApi::getAppCacheSize resolves', size); + debug('LocalApi::getAppCacheSize resolves', size); resolve(size); }); }); @@ -22,14 +24,14 @@ export default class LocalApi { async clearCache(serviceId) { const s = session.fromPartition(`persist:service-${serviceId}`); - console.debug('LocalApi::clearCache resolves', serviceId); + debug('LocalApi::clearCache resolves', serviceId); return new Promise(resolve => s.clearCache(resolve)); } async clearAppCache() { const s = session.defaultSession; - console.debug('LocalApi::clearCache clearAppCache'); + debug('LocalApi::clearCache clearAppCache'); return new Promise(resolve => s.clearCache(resolve)); } } diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js index 8f3297d13..353faa7f4 100644 --- a/src/api/server/ServerApi.js +++ b/src/api/server/ServerApi.js @@ -27,6 +27,8 @@ import { removeServicePartitionDirectory, } from '../../helpers/service-helpers.js'; +const debug = require('debug')('ServerApi'); + module.paths.unshift( getDevRecipeDirectory(), getRecipeDirectory(), @@ -55,7 +57,7 @@ export default class ServerApi { } const u = await request.json(); - console.debug('ServerApi::login resolves', u); + debug('ServerApi::login resolves', u); return u.token; } @@ -69,7 +71,7 @@ export default class ServerApi { } const u = await request.json(); - console.debug('ServerApi::signup resolves', u); + debug('ServerApi::signup resolves', u); return u.token; } @@ -82,7 +84,7 @@ export default class ServerApi { throw request; } - console.debug('ServerApi::inviteUser'); + debug('ServerApi::inviteUser'); return true; } @@ -98,7 +100,7 @@ export default class ServerApi { } const r = await request.json(); - console.debug('ServerApi::retrievePassword'); + debug('ServerApi::retrievePassword'); return r; } @@ -112,7 +114,7 @@ export default class ServerApi { const data = await request.json(); const user = new UserModel(data); - console.debug('ServerApi::userInfo resolves', user); + debug('ServerApi::userInfo resolves', user); return user; } @@ -128,7 +130,7 @@ export default class ServerApi { const updatedData = await request.json(); const user = Object.assign(updatedData, { data: new UserModel(updatedData.data) }); - console.debug('ServerApi::updateUserInfo resolves', user); + debug('ServerApi::updateUserInfo resolves', user); return user; } @@ -141,7 +143,7 @@ export default class ServerApi { } const data = await request.json(); - console.debug('ServerApi::deleteAccount resolves', data); + debug('ServerApi::deleteAccount resolves', data); return data; } @@ -157,7 +159,7 @@ export default class ServerApi { let services = await this._mapServiceModels(data); services = services.filter(service => service !== null); - console.debug('ServerApi::getServices resolves', services); + debug('ServerApi::getServices resolves', services); return services; } @@ -181,7 +183,7 @@ export default class ServerApi { const service = Object.assign(serviceData, { data: await this._prepareServiceModel(serviceData.data) }); - console.debug('ServerApi::createService resolves', service); + debug('ServerApi::createService resolves', service); return service; } @@ -205,7 +207,7 @@ export default class ServerApi { const service = Object.assign(serviceData, { data: await this._prepareServiceModel(serviceData.data) }); - console.debug('ServerApi::updateService resolves', service); + debug('ServerApi::updateService resolves', service); return service; } @@ -240,7 +242,7 @@ export default class ServerApi { throw request; } const serviceData = await request.json(); - console.debug('ServerApi::reorderService resolves', serviceData); + debug('ServerApi::reorderService resolves', serviceData); return serviceData; } @@ -255,7 +257,7 @@ export default class ServerApi { removeServicePartitionDirectory(id, true); - console.debug('ServerApi::deleteService resolves', data); + debug('ServerApi::deleteService resolves', data); return data; } @@ -277,7 +279,7 @@ export default class ServerApi { this.recipes = this.recipes.concat(this._getDevRecipes()); - console.debug('StubServerApi::getInstalledRecipes resolves', this.recipes); + debug('StubServerApi::getInstalledRecipes resolves', this.recipes); return this.recipes; } @@ -290,7 +292,7 @@ export default class ServerApi { throw request; } const recipes = await request.json(); - console.debug('ServerApi::getRecipeUpdates resolves', recipes); + debug('ServerApi::getRecipeUpdates resolves', recipes); return recipes; } @@ -305,7 +307,7 @@ export default class ServerApi { const data = await request.json(); const recipePreviews = this._mapRecipePreviewModel(data); - console.debug('ServerApi::getRecipes resolves', recipePreviews); + debug('ServerApi::getRecipes resolves', recipePreviews); return recipePreviews; } @@ -322,7 +324,7 @@ export default class ServerApi { // data = this._addLocalRecipesToPreviews(data); const recipePreviews = this._mapRecipePreviewModel(data); - console.debug('ServerApi::getFeaturedRecipes resolves', recipePreviews); + debug('ServerApi::getFeaturedRecipes resolves', recipePreviews); return recipePreviews; } @@ -336,7 +338,7 @@ export default class ServerApi { const data = await request.json(); const recipePreviews = this._mapRecipePreviewModel(data); - console.debug('ServerApi::searchRecipePreviews resolves', recipePreviews); + debug('ServerApi::searchRecipePreviews resolves', recipePreviews); return recipePreviews; } @@ -350,7 +352,7 @@ export default class ServerApi { fs.ensureDirSync(recipeTempDirectory); const res = await fetch(packageUrl); - console.debug('Recipe downloaded', recipeId); + debug('Recipe downloaded', recipeId); const buffer = await res.buffer(); fs.writeFileSync(archivePath, buffer); @@ -392,7 +394,7 @@ export default class ServerApi { const data = await request.json(); const plan = new PlanModel(data); - console.debug('ServerApi::getPlans resolves', plan); + debug('ServerApi::getPlans resolves', plan); return plan; } @@ -408,7 +410,7 @@ export default class ServerApi { } const data = await request.json(); - console.debug('ServerApi::getHostedPage resolves', data); + debug('ServerApi::getHostedPage resolves', data); return data; } @@ -421,7 +423,7 @@ export default class ServerApi { } const data = await request.json(); - console.debug('ServerApi::getPaymentDashboardUrl resolves', data); + debug('ServerApi::getPaymentDashboardUrl resolves', data); return data; } @@ -434,7 +436,7 @@ export default class ServerApi { } const data = await request.json(); const orders = this._mapOrderModels(data); - console.debug('ServerApi::getSubscriptionOrders resolves', orders); + debug('ServerApi::getSubscriptionOrders resolves', orders); return orders; } @@ -451,7 +453,7 @@ export default class ServerApi { } const data = await request.json(); const news = this._mapNewsModels(data); - console.debug('ServerApi::getLatestNews resolves', news); + debug('ServerApi::getLatestNews resolves', news); return news; } @@ -465,7 +467,7 @@ export default class ServerApi { throw request; } - console.debug('ServerApi::hideNews resolves', id); + debug('ServerApi::hideNews resolves', id); } // Health Check @@ -476,7 +478,7 @@ export default class ServerApi { if (!request.ok) { throw request; } - console.debug('ServerApi::healthCheck resolves'); + debug('ServerApi::healthCheck resolves'); } async getLegacyServices() { @@ -502,7 +504,7 @@ export default class ServerApi { return service; })); - console.debug('ServerApi::getLegacyServices resolves', services); + debug('ServerApi::getLegacyServices resolves', services); return services; } } catch (err) { @@ -535,7 +537,7 @@ export default class ServerApi { return new ServiceModel(service, recipe); } catch (e) { - console.debug(e); + debug(e); return null; } } @@ -553,7 +555,7 @@ export default class ServerApi { await this.getRecipePackage(recipeId); - console.debug('Rerun ServerAPI::getInstalledRecipes'); + debug('Rerun ServerAPI::getInstalledRecipes'); await this.getInstalledRecipes(); recipe = this.recipes.find(r => r.id === recipeId); @@ -653,7 +655,7 @@ export default class ServerApi { return recipes; } catch (err) { - console.debug('Could not load dev recipes'); + debug('Could not load dev recipes'); return false; } } diff --git a/src/lib/analytics.js b/src/lib/analytics.js index b13bf8faa..585cbcdba 100644 --- a/src/lib/analytics.js +++ b/src/lib/analytics.js @@ -2,6 +2,8 @@ import { remote } from 'electron'; import { GA_ID } from '../config'; // import { isDevMode } from '../environment'; +const debug = require('debug')('Analytics'); + const { app } = remote; /* eslint-disable */ @@ -28,13 +30,13 @@ ga('send', 'App'); export function gaPage(page) { ga('send', 'pageview', page); - console.debug('GA track page', page); + debug('GA track page', page); } export function gaEvent(category, action, label) { ga('send', 'event', category, action, label); - console.debug('GA track page', category, action); + debug('GA track page', category, action); } setTimeout(() => { diff --git a/src/stores/RecipesStore.js b/src/stores/RecipesStore.js index 67fee1d50..a24308f6a 100644 --- a/src/stores/RecipesStore.js +++ b/src/stores/RecipesStore.js @@ -5,6 +5,8 @@ import CachedRequest from './lib/CachedRequest'; import Request from './lib/Request'; import { matchRoute } from '../helpers/routing-helpers'; +const debug = require('debug')('RecipeStore'); + export default class RecipesStore extends Store { @observable allRecipesRequest = new CachedRequest(this.api.recipes, 'all'); @observable installRecipeRequest = new Request(this.api.recipes, 'install'); @@ -34,7 +36,7 @@ export default class RecipesStore extends Store { return activeRecipe; } - console.warn('Recipe not installed'); + debug(`Recipe ${match.id} not installed`); } return null; @@ -54,10 +56,8 @@ export default class RecipesStore extends Store { // Actions @action async _install({ recipeId }) { - // console.log(this.installRecipeRequest._promise); const recipe = await this.installRecipeRequest.execute(recipeId)._promise; await this.allRecipesRequest.invalidate({ immediately: true })._promise; - // console.log(this.installRecipeRequest._promise); return recipe; } @@ -67,7 +67,7 @@ export default class RecipesStore extends Store { const recipes = {}; // Hackfix, reference this.all to fetch services - console.debug(`Check Recipe updates for ${this.all.map(recipe => recipe.id)}`); + debug(`Check Recipe updates for ${this.all.map(recipe => recipe.id)}`); recipeIds.forEach((r) => { const recipe = this.one(r); diff --git a/src/stores/RequestStore.js b/src/stores/RequestStore.js index 4140ca362..595852583 100644 --- a/src/stores/RequestStore.js +++ b/src/stores/RequestStore.js @@ -2,6 +2,8 @@ import { action, computed, observable } from 'mobx'; import Store from './lib/Store'; +const debug = require('debug')('RequestsStore'); + export default class RequestStore extends Store { @observable userInfoRequest; @observable servicesRequest; @@ -52,7 +54,7 @@ export default class RequestStore extends Store { } this._autoRetry(); - console.debug(`Retry required requests delayed in ${(delay) / 1000}s`); + debug(`Retry required requests delayed in ${(delay) / 1000}s`); }, delay); } } diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index c38d0d9ee..0d9ff7f9b 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -10,6 +10,8 @@ import CachedRequest from './lib/CachedRequest'; import { matchRoute } from '../helpers/routing-helpers'; import { gaEvent } from '../lib/analytics'; +const debug = require('debug')('ServiceStore'); + export default class ServicesStore extends Store { @observable allServicesRequest = new CachedRequest(this.api.services, 'all'); @observable createServiceRequest = new Request(this.api.services, 'create'); @@ -103,7 +105,7 @@ export default class ServicesStore extends Store { return activeService; } - console.warn('Service not available'); + debug('Service not available'); } return null; @@ -117,10 +119,10 @@ export default class ServicesStore extends Store { const recipesStore = this.stores.recipes; if (recipesStore.isInstalled(recipeId)) { - console.debug('Recipe is installed'); + debug(`Recipe ${recipeId} is installed`); this._redirectToAddServiceRoute(recipeId); } else { - console.warn('Recipe is not installed'); + debug(`Recipe ${recipeId} is not installed`); // We access the RecipeStore action directly // returns Promise instead of action await this.stores.recipes._install({ recipeId }); @@ -487,7 +489,7 @@ export default class ServicesStore extends Store { if (service) { service.webview.openDevTools(); } else { - console.warn('No service is active'); + debug('No service is active'); } } diff --git a/yarn.lock b/yarn.lock index 317f7b220..540c4f8c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1643,6 +1643,12 @@ dateformat@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.0.0.tgz#2743e3abb5c3fc2462e527dca445e04e9f4dee17" +debug-electron@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/debug-electron/-/debug-electron-0.0.4.tgz#9b035349ac8107b4e43da200d2339c4fd5b169e7" + dependencies: + debug "^2.4.1" + debug@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/debug/-/debug-1.0.4.tgz#5b9c256bd54b6ec02283176fa8a0ede6d154cbf8" @@ -1667,6 +1673,12 @@ debug@^2.1.3, debug@^2.2.0, debug@^2.5.1, debug@^2.6.1, debug@^2.6.3, debug@^2.6 dependencies: ms "2.0.0" +debug@^2.4.1: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + debug@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/debug/-/debug-3.0.1.tgz#0564c612b521dc92d9f2988f0549e34f9c98db64" -- cgit v1.2.3-70-g09d2 From 768fa9a284fa1802b0a4f021bbb7b7dff72a622f Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Sun, 18 Mar 2018 21:03:59 +0100 Subject: Remove reload code --- src/stores/AppStore.js | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'src/stores') diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 2d0a617a5..4ac8325d4 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -128,19 +128,6 @@ export default class AppStore extends Store { this.stores.router.push(data.url); }); - // Reload all services after a healthy nap - // Alternative solution for powerMonitor as the resume event is not fired - // More information: https://github.com/electron/electron/issues/1615 - const TIMEOUT = 5000; - let lastTime = (new Date()).getTime(); - setInterval(() => { - const currentTime = (new Date()).getTime(); - if (currentTime > (lastTime + TIMEOUT + 2000)) { - this._reactivateServices(); - } - lastTime = currentTime; - }, TIMEOUT); - // Set active the next service key( '⌘+pagedown, ctrl+pagedown, ⌘+alt+right, ctrl+tab', () => { @@ -360,16 +347,6 @@ export default class AppStore extends Store { return autoLauncher.isEnabled() || false; } - _reactivateServices(retryCount = 0) { - if (!this.isOnline) { - console.debug('reactivateServices: computer is offline, trying again in 5s, retries:', retryCount); - setTimeout(() => this._reactivateServices(retryCount + 1), 5000); - } else { - console.debug('reactivateServices: reload Franz'); - // window.location.reload(); - } - } - _systemDND() { const dnd = getDoNotDisturb(); if (dnd !== this.stores.settings.all.isAppMuted && !this.isSystemMuteOverridden) { -- cgit v1.2.3-70-g09d2 From 63d4281300ef86cbec6869bad3cbbb976c219c7d Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Tue, 27 Mar 2018 15:19:44 +0200 Subject: Move "locale" to user data --- src/containers/settings/EditSettingsScreen.js | 10 +--------- src/models/User.js | 2 ++ src/stores/AppStore.js | 6 +++++- src/stores/UserStore.js | 20 ++++++++++++++++++++ 4 files changed, 28 insertions(+), 10 deletions(-) (limited to 'src/stores') diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js index 1fa7ce8bc..e67c2964b 100644 --- a/src/containers/settings/EditSettingsScreen.js +++ b/src/containers/settings/EditSettingsScreen.js @@ -91,15 +91,13 @@ export default class EditSettingsScreen extends Component { showDisabledServices: settingsData.showDisabledServices, showMessageBadgeWhenMuted: settingsData.showMessageBadgeWhenMuted, enableSpellchecking: settingsData.enableSpellchecking, - // spellcheckingLanguage: settingsData.spellcheckingLanguage, - locale: settingsData.locale, - beta: settingsData.beta, }, }); user.update({ userData: { beta: settingsData.beta, + locale: settingsData.locale, }, }); } @@ -169,12 +167,6 @@ export default class EditSettingsScreen extends Component { value: settings.all.enableSpellchecking, default: DEFAULT_APP_SETTINGS.enableSpellchecking, }, - // spellcheckingLanguage: { - // label: intl.formatMessage(messages.spellcheckingLanguage), - // value: settings.all.spellcheckingLanguage, - // options: spellcheckerLocales, - // default: DEFAULT_APP_SETTINGS.spellcheckingLanguage, - // }, locale: { label: intl.formatMessage(messages.language), value: app.locale, diff --git a/src/models/User.js b/src/models/User.js index 2e5df4795..3e4aa187d 100644 --- a/src/models/User.js +++ b/src/models/User.js @@ -15,6 +15,7 @@ export default class User { @observable donor = {}; @observable isDonor = false; @observable isMiner = false; + @observable locale = false; constructor(data) { if (!data.id) { @@ -33,5 +34,6 @@ export default class User { this.isDonor = data.isDonor || this.isDonor; this.isSubscriptionOwner = data.isSubscriptionOwner || this.isSubscriptionOwner; this.isMiner = data.isMiner || this.isMiner; + this.locale = data.locale || this.locale; } } diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 4ac8325d4..94ed308f3 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -15,6 +15,8 @@ import { gaEvent } from '../lib/analytics'; import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js'; +const debug = require('debug')('AppStore'); + const { app } = remote; const defaultLocale = DEFAULT_APP_SETTINGS.locale; @@ -279,13 +281,15 @@ export default class AppStore extends Store { } _setLocale() { - const locale = this.stores.settings.all.locale; + const { locale } = this.stores.user.data; if (locale && Object.prototype.hasOwnProperty.call(locales, locale) && locale !== this.locale) { this.locale = locale; } else if (!locale) { this.locale = this._getDefaultLocale(); } + + debug(`Set locale to "${this.locale}"`); } _getDefaultLocale() { diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index 7dbbd955b..c151f6d59 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js @@ -9,6 +9,8 @@ import Request from './lib/Request'; import CachedRequest from './lib/CachedRequest'; import { gaEvent } from '../lib/analytics'; +const debug = require('debug')('UserStore'); + // TODO: split stores into UserStore and AuthStore export default class UserStore extends Store { BASE_ROUTE = '/auth'; @@ -69,6 +71,11 @@ export default class UserStore extends Store { ]); } + setup() { + // Data migration + this._migrateUserLocale(); + } + // Routes get loginRoute() { return this.LOGIN_ROUTE; @@ -292,4 +299,17 @@ export default class UserStore extends Store { this.id = null; } } + + async _migrateUserLocale() { + await this.getUserInfoRequest._promise; + + if (!this.data.locale) { + debug('Migrate "locale" to user data'); + this.actions.user.update({ + userData: { + locale: this.stores.app.locale, + }, + }); + } + } } -- cgit v1.2.3-70-g09d2 From 8aab8699e02ed9ec736bb6dfab0edd3fe9156c8d Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Tue, 27 Mar 2018 21:25:56 +0200 Subject: Split settings into multiple stores; app specific settings are now stored in config file --- src/actions/settings.js | 4 ++- src/api/LocalApi.js | 8 +++++ src/api/server/LocalApi.js | 19 +++++++++++- src/config.js | 8 ++++- src/containers/layout/AppLayoutContainer.js | 6 ++-- src/containers/settings/EditSettingsScreen.js | 32 +++++++------------- src/electron/Settings.js | 34 ++++++++++++++++++--- src/electron/ipc-api/settings.js | 8 +++++ src/models/Settings.js | 43 +++++++++++++++++++-------- src/stores/AppStore.js | 17 ++++++----- src/stores/ServicesStore.js | 15 +++++----- src/stores/SettingsStore.js | 41 ++++++++++++++++--------- src/stores/UIStore.js | 2 +- 13 files changed, 164 insertions(+), 73 deletions(-) (limited to 'src/stores') diff --git a/src/actions/settings.js b/src/actions/settings.js index 3d53cd674..fd29b798b 100644 --- a/src/actions/settings.js +++ b/src/actions/settings.js @@ -2,9 +2,11 @@ import PropTypes from 'prop-types'; export default { update: { - settings: PropTypes.object.isRequired, + type: PropTypes.string.isRequired, + data: PropTypes.object.isRequired, }, remove: { + type: PropTypes.string.isRequired, key: PropTypes.string.isRequired, }, }; diff --git a/src/api/LocalApi.js b/src/api/LocalApi.js index 59d7d8fa2..741917104 100644 --- a/src/api/LocalApi.js +++ b/src/api/LocalApi.js @@ -4,6 +4,14 @@ export default class LocalApi { this.local = local; } + getAppSettings() { + return this.local.getAppSettings(); + } + + updateAppSettings(data) { + return this.local.updateAppSettings(data); + } + getAppCacheSize() { return this.local.getAppCacheSize(); } diff --git a/src/api/server/LocalApi.js b/src/api/server/LocalApi.js index 4d2497c61..78deb7aa5 100644 --- a/src/api/server/LocalApi.js +++ b/src/api/server/LocalApi.js @@ -1,4 +1,4 @@ -import { remote } from 'electron'; +import { ipcRenderer, remote } from 'electron'; import du from 'du'; import { getServicePartitionsDirectory } from '../../helpers/service-helpers.js'; @@ -8,6 +8,23 @@ const debug = require('debug')('LocalApi'); const { session } = remote; export default class LocalApi { + // Settings + getAppSettings() { + return new Promise((resolve) => { + ipcRenderer.once('appSettings', (event, data) => { + debug('LocalApi::getAppSettings resolves', data); + resolve(data); + }); + + ipcRenderer.send('getAppSettings'); + }); + } + + async updateAppSettings(data) { + debug('LocalApi::updateAppSettings resolves', data); + ipcRenderer.send('updateAppSettings', data); + } + // Services async getAppCacheSize() { const partitionsDir = getServicePartitionsDirectory(); diff --git a/src/config.js b/src/config.js index e66594c59..366231f79 100644 --- a/src/config.js +++ b/src/config.js @@ -1,3 +1,8 @@ +import electron from 'electron'; +import path from 'path'; + +const app = process.type === 'renderer' ? electron.remote.app : electron.app; + export const CHECK_INTERVAL = 1000 * 3600; // How often should we perform checks export const LOCAL_API = 'http://localhost:3000'; export const DEV_API = 'https://dev.franzinfra.com'; @@ -13,7 +18,6 @@ export const DEFAULT_APP_SETTINGS = { showDisabledServices: true, showMessageBadgeWhenMuted: true, enableSpellchecking: true, - // spellcheckingLanguage: 'auto', locale: '', fallbackLocale: 'en-US', beta: false, @@ -22,3 +26,5 @@ export const DEFAULT_APP_SETTINGS = { export const FRANZ_SERVICE_REQUEST = 'http://bit.ly/franz-service-request'; export const FRANZ_TRANSLATION = 'http://bit.ly/franz-translate'; + +export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config', 'settings.json'); diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 075bd5e34..0931738fd 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js @@ -77,7 +77,7 @@ export default class AppLayoutContainer extends Component { ); @@ -99,7 +99,7 @@ export default class AppLayoutContainer extends Component { setWebviewReference={setWebviewReference} openWindow={openWindow} reload={reload} - isAppMuted={settings.all.isAppMuted} + isAppMuted={settings.all.app.isAppMuted} update={updateService} /> ); diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js index e67c2964b..1bd147099 100644 --- a/src/containers/settings/EditSettingsScreen.js +++ b/src/containers/settings/EditSettingsScreen.js @@ -55,10 +55,6 @@ const messages = defineMessages({ id: 'settings.app.form.spellcheckingLanguage', defaultMessage: '!!!Language for spell checking', }, - // spellcheckingAutomaticDetection: { - // id: 'settings.app.form.spellcheckingAutomaticDetection', - // defaultMessage: '!!!Detect language automatically', - // }, beta: { id: 'settings.app.form.beta', defaultMessage: '!!!Include beta versions', @@ -84,13 +80,16 @@ export default class EditSettingsScreen extends Component { }); settings.update({ - settings: { + type: 'app', + data: { runInBackground: settingsData.runInBackground, enableSystemTray: settingsData.enableSystemTray, minimizeToSystemTray: settingsData.minimizeToSystemTray, showDisabledServices: settingsData.showDisabledServices, showMessageBadgeWhenMuted: settingsData.showMessageBadgeWhenMuted, enableSpellchecking: settingsData.enableSpellchecking, + beta: settingsData.beta, // we need this info in the main process as well + locale: settingsData.locale, // we need this info in the main process as well }, }); @@ -114,17 +113,6 @@ export default class EditSettingsScreen extends Component { }); }); - // const spellcheckerLocales = [{ - // value: 'auto', - // label: intl.formatMessage(messages.spellcheckingAutomaticDetection), - // }]; - // Object.keys(SPELLCHECKER_LOCALES).forEach((key) => { - // spellcheckerLocales.push({ - // value: key, - // label: SPELLCHECKER_LOCALES[key], - // }); - // }); - const config = { fields: { autoLaunchOnStart: { @@ -139,32 +127,32 @@ export default class EditSettingsScreen extends Component { }, runInBackground: { label: intl.formatMessage(messages.runInBackground), - value: settings.all.runInBackground, + value: settings.all.app.runInBackground, default: DEFAULT_APP_SETTINGS.runInBackground, }, enableSystemTray: { label: intl.formatMessage(messages.enableSystemTray), - value: settings.all.enableSystemTray, + value: settings.all.app.enableSystemTray, default: DEFAULT_APP_SETTINGS.enableSystemTray, }, minimizeToSystemTray: { label: intl.formatMessage(messages.minimizeToSystemTray), - value: settings.all.minimizeToSystemTray, + value: settings.all.app.minimizeToSystemTray, default: DEFAULT_APP_SETTINGS.minimizeToSystemTray, }, showDisabledServices: { label: intl.formatMessage(messages.showDisabledServices), - value: settings.all.showDisabledServices, + value: settings.all.app.showDisabledServices, default: DEFAULT_APP_SETTINGS.showDisabledServices, }, showMessageBadgeWhenMuted: { label: intl.formatMessage(messages.showMessageBadgeWhenMuted), - value: settings.all.showMessageBadgeWhenMuted, + value: settings.all.app.showMessageBadgeWhenMuted, default: DEFAULT_APP_SETTINGS.showMessageBadgeWhenMuted, }, enableSpellchecking: { label: intl.formatMessage(messages.enableSpellchecking), - value: settings.all.enableSpellchecking, + value: settings.all.app.enableSpellchecking, default: DEFAULT_APP_SETTINGS.enableSpellchecking, }, locale: { diff --git a/src/electron/Settings.js b/src/electron/Settings.js index 824b4c20c..e24aefdbb 100644 --- a/src/electron/Settings.js +++ b/src/electron/Settings.js @@ -1,27 +1,53 @@ -import { observable } from 'mobx'; +import { observable, toJS } from 'mobx'; +import { pathExistsSync, outputJsonSync, readJsonSync } from 'fs-extra'; -import { DEFAULT_APP_SETTINGS } from '../config'; +import { SETTINGS_PATH, DEFAULT_APP_SETTINGS } from '../config'; + +const debug = require('debug')('Settings'); export default class Settings { @observable store = { - autoLaunchOnStart: DEFAULT_APP_SETTINGS.autoLaunchOnStart, autoLaunchInBackground: DEFAULT_APP_SETTINGS.autoLaunchInBackground, runInBackground: DEFAULT_APP_SETTINGS.runInBackground, enableSystemTray: DEFAULT_APP_SETTINGS.enableSystemTray, minimizeToSystemTray: DEFAULT_APP_SETTINGS.minimizeToSystemTray, locale: DEFAULT_APP_SETTINGS.locale, beta: DEFAULT_APP_SETTINGS.beta, + isAppMuted: DEFAULT_APP_SETTINGS.isAppMuted, + showMessageBadgeWhenMuted: DEFAULT_APP_SETTINGS.showMessageBadgeWhenMuted, + showDisabledServices: DEFAULT_APP_SETTINGS.showDisabledServices, + enableSpellchecking: DEFAULT_APP_SETTINGS.enableSpellchecking, }; + constructor() { + if (!pathExistsSync(SETTINGS_PATH)) { + this._writeFile(); + } else { + this._hydrate(); + } + } + set(settings) { this.store = Object.assign(this.store, settings); + + this._writeFile(); } - all() { + get all() { return this.store; } get(key) { return this.store[key]; } + + _hydrate() { + this.store = readJsonSync(SETTINGS_PATH); + debug('Hydrate store', toJS(this.store)); + } + + _writeFile() { + outputJsonSync(SETTINGS_PATH, this.store); + debug('Write settings file', toJS(this.store)); + } } diff --git a/src/electron/ipc-api/settings.js b/src/electron/ipc-api/settings.js index 995b28fbd..00bdc0113 100644 --- a/src/electron/ipc-api/settings.js +++ b/src/electron/ipc-api/settings.js @@ -4,4 +4,12 @@ export default (params) => { ipcMain.on('settings', (event, args) => { params.settings.set(args); }); + + ipcMain.on('getAppSettings', () => { + params.mainWindow.webContents.send('appSettings', params.settings.all); + }); + + ipcMain.on('updateAppSettings', (event, args) => { + params.settings.set(args); + }); }; diff --git a/src/models/Settings.js b/src/models/Settings.js index e39b63087..f58c05b38 100644 --- a/src/models/Settings.js +++ b/src/models/Settings.js @@ -2,19 +2,38 @@ import { observable, extendObservable } from 'mobx'; import { DEFAULT_APP_SETTINGS } from '../config'; export default class Settings { - @observable autoLaunchInBackground = DEFAULT_APP_SETTINGS.autoLaunchInBackground; - @observable runInBackground = DEFAULT_APP_SETTINGS.runInBackground; - @observable enableSystemTray = DEFAULT_APP_SETTINGS.enableSystemTray; - @observable minimizeToSystemTray = DEFAULT_APP_SETTINGS.minimizeToSystemTray; - @observable showDisabledServices = DEFAULT_APP_SETTINGS.showDisabledServices; - @observable showMessageBadgeWhenMuted = DEFAULT_APP_SETTINGS.showMessageBadgeWhenMuted; - @observable enableSpellchecking = DEFAULT_APP_SETTINGS.enableSpellchecking; - @observable locale = DEFAULT_APP_SETTINGS.locale; - @observable beta = DEFAULT_APP_SETTINGS.beta; - @observable isAppMuted = DEFAULT_APP_SETTINGS.isAppMuted; + @observable app = { + autoLaunchInBackground: DEFAULT_APP_SETTINGS.autoLaunchInBackground, + runInBackground: DEFAULT_APP_SETTINGS.runInBackground, + enableSystemTray: DEFAULT_APP_SETTINGS.enableSystemTray, + minimizeToSystemTray: DEFAULT_APP_SETTINGS.minimizeToSystemTray, + isAppMuted: DEFAULT_APP_SETTINGS.isAppMuted, + showMessageBadgeWhenMuted: DEFAULT_APP_SETTINGS.showMessageBadgeWhenMuted, + showDisabledServices: DEFAULT_APP_SETTINGS.showDisabledServices, + enableSpellchecking: DEFAULT_APP_SETTINGS.enableSpellchecking, + locale: DEFAULT_APP_SETTINGS.locale, + beta: DEFAULT_APP_SETTINGS.beta, - constructor(data) { - Object.assign(this, data); + } + + @observable service = { + activeService: DEFAULT_APP_SETTINGS.autoLaunchInBackground, + } + + @observable group = { + collapsed: [], + disabled: [], + } + + @observable stats = { + appStarts: 0, + } + + constructor({ app, service, group, stats }) { + Object.assign(this.app, app); + Object.assign(this.service, service); + Object.assign(this.group, group); + Object.assign(this.stats, stats); } update(data) { diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 94ed308f3..3c6c24b59 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -159,7 +159,7 @@ export default class AppStore extends Store { // Actions @action _notify({ title, options, notificationId, serviceId = null }) { - if (this.stores.settings.all.isAppMuted) return; + if (this.stores.settings.all.app.isAppMuted) return; const notification = new window.Notification(title, options); notification.onclick = (e) => { @@ -240,14 +240,15 @@ export default class AppStore extends Store { this.isSystemMuteOverridden = overrideSystemMute; this.actions.settings.update({ - settings: { + type: 'app', + data: { isAppMuted: isMuted, }, }); } @action _toggleMuteApp() { - this._muteApp({ isMuted: !this.stores.settings.all.isAppMuted }); + this._muteApp({ isMuted: !this.stores.settings.all.app.isAppMuted }); } @action async _clearAllCache() { @@ -331,8 +332,9 @@ export default class AppStore extends Store { // Helpers _appStartsCounter() { this.actions.settings.update({ - settings: { - appStarts: (this.stores.settings.all.appStarts || 0) + 1, + type: 'stats', + data: { + appStarts: (this.stores.settings.all.stats.appStarts || 0) + 1, }, }); } @@ -340,7 +342,8 @@ export default class AppStore extends Store { async _autoStart() { this.autoLaunchOnStart = await this._checkAutoStart(); - if (this.stores.settings.all.appStarts === 1) { + if (this.stores.settings.all.stats.appStarts === 1) { + debug('Set app to launch on start'); this.actions.app.launchOnStartup({ enable: true, }); @@ -353,7 +356,7 @@ export default class AppStore extends Store { _systemDND() { const dnd = getDoNotDisturb(); - if (dnd !== this.stores.settings.all.isAppMuted && !this.isSystemMuteOverridden) { + if (dnd !== this.stores.settings.all.app.isAppMuted && !this.isSystemMuteOverridden) { this.actions.app.muteApp({ isMuted: dnd, overrideSystemMute: false, diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index f7d92b1ff..b96bc506b 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -86,13 +86,13 @@ export default class ServicesStore extends Store { } @computed get allDisplayed() { - return this.stores.settings.all.showDisabledServices ? this.all : this.enabled; + return this.stores.settings.all.service.showDisabledServices ? this.all : this.enabled; } // This is just used to avoid unnecessary rerendering of resource-heavy webviews @computed get allDisplayedUnordered() { const services = this.allServicesRequest.execute().result || []; - return this.stores.settings.all.showDisabledServices ? services : services.filter(service => service.isEnabled); + return this.stores.settings.all.service.showDisabledServices ? services : services.filter(service => service.isEnabled); } @computed get filtered() { @@ -334,7 +334,7 @@ export default class ServicesStore extends Store { }); } else if (channel === 'notification') { const options = args[0].options; - if (service.recipe.hasNotificationSound || service.isMuted || this.stores.settings.all.isAppMuted) { + if (service.recipe.hasNotificationSound || service.isMuted || this.stores.settings.all.app.isAppMuted) { Object.assign(options, { silent: true, }); @@ -434,7 +434,7 @@ export default class ServicesStore extends Store { } @action _reorder({ oldIndex, newIndex }) { - const showDisabledServices = this.stores.settings.all.showDisabledServices; + const showDisabledServices = this.stores.settings.all.service.showDisabledServices; const oldEnabledSortIndex = showDisabledServices ? oldIndex : this.all.indexOf(this.enabled[oldIndex]); const newEnabledSortIndex = showDisabledServices ? newIndex : this.all.indexOf(this.enabled[newIndex]); @@ -512,7 +512,8 @@ export default class ServicesStore extends Store { if (service) { this.actions.settings.update({ - settings: { + type: 'service', + data: { activeService: service.id, }, }); @@ -520,7 +521,7 @@ export default class ServicesStore extends Store { } _mapActiveServiceToServiceModelReaction() { - const { activeService } = this.stores.settings.all; + const { activeService } = this.stores.settings.all.service; if (this.allDisplayed.length) { this.allDisplayed.map(service => Object.assign(service, { isActive: activeService ? activeService === service.id : this.allDisplayed[0].id === service.id, @@ -529,7 +530,7 @@ export default class ServicesStore extends Store { } _getUnreadMessageCountReaction() { - const showMessageBadgeWhenMuted = this.stores.settings.all.showMessageBadgeWhenMuted; + const showMessageBadgeWhenMuted = this.stores.settings.all.app.showMessageBadgeWhenMuted; const showMessageBadgesEvenWhenMuted = this.stores.ui.showMessageBadgesEvenWhenMuted; const unreadDirectMessageCount = this.allDisplayed diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index b7d803398..b3f5d3eaf 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -1,12 +1,18 @@ import { ipcRenderer } from 'electron'; -import { action, computed } from 'mobx'; +import { action, computed, observable } from 'mobx'; import localStorage from 'mobx-localstorage'; import Store from './lib/Store'; -import { gaEvent } from '../lib/analytics'; import SettingsModel from '../models/Settings'; +import Request from './lib/Request'; +import CachedRequest from './lib/CachedRequest'; + +const debug = require('debug')('SettingsStore'); export default class SettingsStore extends Store { + @observable appSettingsRequest = new CachedRequest(this.api.local, 'getAppSettings'); + @observable updateAppSettingsRequest = new Request(this.api.local, 'updateAppSettings'); + constructor(...args) { super(...args); @@ -15,22 +21,29 @@ export default class SettingsStore extends Store { this.actions.settings.remove.listen(this._remove.bind(this)); } - setup() { - this._shareSettingsWithMainProcess(); - } - @computed get all() { - return new SettingsModel(localStorage.getItem('app') || {}); + return new SettingsModel({ + app: this.appSettingsRequest.execute().result || {}, + service: localStorage.getItem('service') || {}, + group: localStorage.getItem('group') || {}, + stats: localStorage.getItem('stats') || {}, + }); } - @action async _update({ settings }) { + @action async _update({ type, data }) { + debug('Update settings', type, data, this.all); const appSettings = this.all; - localStorage.setItem('app', Object.assign(appSettings, settings)); - - // We need a little hack to wait until everything is patched - setTimeout(() => this._shareSettingsWithMainProcess(), 0); - - gaEvent('Settings', 'update'); + if (type !== 'app') { + localStorage.setItem(type, Object.assign(appSettings[type], data)); + } else { + debug('Store app settings on file system', type, data); + this.updateAppSettingsRequest.execute(data); + + this.appSettingsRequest.patch((result) => { + if (!result) return; + Object.assign(result, data); + }); + } } @action async _remove({ key }) { diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js index 5e9cc9ba7..b391bdcae 100644 --- a/src/stores/UIStore.js +++ b/src/stores/UIStore.js @@ -17,7 +17,7 @@ export default class UIStore extends Store { @computed get showMessageBadgesEvenWhenMuted() { const settings = this.stores.settings.all; - return (settings.isAppMuted && settings.showMessageBadgeWhenMuted) || !settings.isAppMuted; + return (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || !settings.isAppMuted; } // Actions -- cgit v1.2.3-70-g09d2 From ca66ab1a3b53ec677e0eba69e9feea3ad777c3bf Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 28 Mar 2018 10:03:34 +0200 Subject: Add settings migration --- src/models/Settings.js | 5 +++- src/stores/SettingsStore.js | 65 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 8 deletions(-) (limited to 'src/stores') diff --git a/src/models/Settings.js b/src/models/Settings.js index f58c05b38..6b41b5d95 100644 --- a/src/models/Settings.js +++ b/src/models/Settings.js @@ -29,11 +29,14 @@ export default class Settings { appStarts: 0, } - constructor({ app, service, group, stats }) { + @observable migration = {} + + constructor({ app, service, group, stats, migration }) { Object.assign(this.app, app); Object.assign(this.service, service); Object.assign(this.group, group); Object.assign(this.stats, stats); + Object.assign(this.migration, migration); } update(data) { diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index b3f5d3eaf..075cb6482 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -21,22 +21,27 @@ export default class SettingsStore extends Store { this.actions.settings.remove.listen(this._remove.bind(this)); } + setup() { + this._migrate(); + } + @computed get all() { return new SettingsModel({ app: this.appSettingsRequest.execute().result || {}, service: localStorage.getItem('service') || {}, group: localStorage.getItem('group') || {}, stats: localStorage.getItem('stats') || {}, + migration: localStorage.getItem('migration') || {}, }); } @action async _update({ type, data }) { - debug('Update settings', type, data, this.all); const appSettings = this.all; if (type !== 'app') { + debug('Update settings', type, data, this.all); localStorage.setItem(type, Object.assign(appSettings[type], data)); } else { - debug('Store app settings on file system', type, data); + debug('Update settings on file system', type, data); this.updateAppSettingsRequest.execute(data); this.appSettingsRequest.patch((result) => { @@ -46,18 +51,64 @@ export default class SettingsStore extends Store { } } - @action async _remove({ key }) { - const appSettings = this.all; + @action async _remove({ type, key }) { + if (type === 'app') return; // app keys can't be deleted + + const appSettings = this.all[type]; if (Object.hasOwnProperty.call(appSettings, key)) { delete appSettings[key]; - localStorage.setItem('app', appSettings); - } - this._shareSettingsWithMainProcess(); + this.actions.settings.update({ + type, + data: appSettings, + }); + } } // Reactions _shareSettingsWithMainProcess() { ipcRenderer.send('settings', this.all); } + + // Helper + _migrate() { + const legacySettings = localStorage.getItem('app'); + + if (!this.all.migration['5.0.0-beta.17-settings']) { + this.actions.settings.update({ + type: 'app', + data: { + autoLaunchInBackground: legacySettings.autoLaunchInBackground, + runInBackground: legacySettings.runInBackground, + enableSystemTray: legacySettings.enableSystemTray, + minimizeToSystemTray: legacySettings.minimizeToSystemTray, + isAppMuted: legacySettings.isAppMuted, + enableGPUAcceleration: legacySettings.enableGPUAcceleration, + showMessageBadgeWhenMuted: legacySettings.showMessageBadgeWhenMuted, + showDisabledServices: legacySettings.showDisabledServices, + enableSpellchecking: legacySettings.enableSpellchecking, + locale: legacySettings.locale, + beta: legacySettings.beta, + }, + }); + + this.actions.settings.update({ + type: 'service', + data: { + activeService: legacySettings.activeService, + }, + }); + + this.actions.settings.update({ + type: 'migration', + data: { + '5.0.0-beta.17-settings': true, + }, + }); + + localStorage.removeItem('app'); + + debug('Migrated settings to split stores'); + } + } } -- cgit v1.2.3-70-g09d2 From b3cfa16fb079ddbc339316fc09324cb7ebe7abf0 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 28 Mar 2018 10:05:00 +0200 Subject: Add beta and locale settings to app config as well --- src/stores/UserStore.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/stores') diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index c151f6d59..574616925 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js @@ -263,8 +263,10 @@ export default class UserStore extends Store { // We need to set the beta flag for the SettingsStore this.actions.settings.update({ - settings: { + type: 'app', + data: { beta: data.beta, + locale: data.locale, }, }); } -- cgit v1.2.3-70-g09d2 From 04145fb473d929c6b80fcb9a66c635a6af7382a8 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 28 Mar 2018 10:07:31 +0200 Subject: Fix issue with endless data fetching loop when user logs out --- src/stores/AppStore.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/stores') diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 3c6c24b59..ea1e71bdc 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -282,7 +282,11 @@ export default class AppStore extends Store { } _setLocale() { - const { locale } = this.stores.user.data; + let locale; + if (this.stores.user.isLoggedIn) { + locale = this.stores.user.data.locale; + } + if (locale && Object.prototype.hasOwnProperty.call(locales, locale) && locale !== this.locale) { this.locale = locale; -- cgit v1.2.3-70-g09d2 From 2de13b5161c82e5857edb13d4a971a31b7628f0b Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 28 Mar 2018 10:11:12 +0200 Subject: Set correct keys for new settings store --- src/stores/ServicesStore.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/stores') diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index b96bc506b..6dfc114f5 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -86,13 +86,13 @@ export default class ServicesStore extends Store { } @computed get allDisplayed() { - return this.stores.settings.all.service.showDisabledServices ? this.all : this.enabled; + return this.stores.settings.all.app.showDisabledServices ? this.all : this.enabled; } // This is just used to avoid unnecessary rerendering of resource-heavy webviews @computed get allDisplayedUnordered() { const services = this.allServicesRequest.execute().result || []; - return this.stores.settings.all.service.showDisabledServices ? services : services.filter(service => service.isEnabled); + return this.stores.settings.all.app.showDisabledServices ? services : services.filter(service => service.isEnabled); } @computed get filtered() { @@ -434,7 +434,7 @@ export default class ServicesStore extends Store { } @action _reorder({ oldIndex, newIndex }) { - const showDisabledServices = this.stores.settings.all.service.showDisabledServices; + const showDisabledServices = this.stores.settings.all.app.showDisabledServices; const oldEnabledSortIndex = showDisabledServices ? oldIndex : this.all.indexOf(this.enabled[oldIndex]); const newEnabledSortIndex = showDisabledServices ? newIndex : this.all.indexOf(this.enabled[newIndex]); @@ -554,7 +554,10 @@ export default class ServicesStore extends Store { _logoutReaction() { if (!this.stores.user.isLoggedIn) { - this.actions.settings.remove({ key: 'activeService' }); + this.actions.settings.remove({ + type: 'service', + key: 'activeService', + }); this.allServicesRequest.invalidate().reset(); } } @@ -562,7 +565,7 @@ export default class ServicesStore extends Store { _shareSettingsWithServiceProcess() { this.actions.service.sendIPCMessageToAllServices({ channel: 'settings-update', - args: this.stores.settings.all, + args: this.stores.settings.all.app, }); } -- cgit v1.2.3-70-g09d2 From 5398846e58d87f5ef54ccc19f4ccb318166ef621 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 28 Mar 2018 10:12:03 +0200 Subject: Replace share settings with webviews autorun with single key reaction --- src/stores/ServicesStore.js | 14 +++++++++----- src/webview/plugin.js | 6 +++++- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src/stores') diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 6dfc114f5..ccb85421a 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -1,8 +1,5 @@ -// import { remote } from 'electron'; -import { action, computed, observable } from 'mobx'; +import { action, reaction, computed, observable } from 'mobx'; import { debounce, remove } from 'lodash'; -// import path from 'path'; -// import fs from 'fs-extra'; import Store from './lib/Store'; import Request from './lib/Request'; @@ -63,13 +60,20 @@ export default class ServicesStore extends Store { this._mapActiveServiceToServiceModelReaction.bind(this), this._saveActiveService.bind(this), this._logoutReaction.bind(this), - this._shareSettingsWithServiceProcess.bind(this), ]); // Just bind this this._initializeServiceRecipeInWebview.bind(this); } + setup() { + // Single key reactions + reaction( + () => this.stores.settings.all.app.enableSpellchecking, + () => this._shareSettingsWithServiceProcess(), + ); + } + @computed get all() { if (this.stores.user.isLoggedIn) { const services = this.allServicesRequest.execute().result; diff --git a/src/webview/plugin.js b/src/webview/plugin.js index 52b19b3fd..c6530fef6 100644 --- a/src/webview/plugin.js +++ b/src/webview/plugin.js @@ -8,6 +8,8 @@ import RecipeWebview from './lib/RecipeWebview'; import Spellchecker from './spellchecker'; import './notifications'; +const debug = require('debug')('Plugin'); + ipcRenderer.on('initializeRecipe', (e, data) => { const modulePath = path.join(data.recipe.path, 'webview.js'); // Delete module from cache @@ -15,8 +17,9 @@ ipcRenderer.on('initializeRecipe', (e, data) => { try { // eslint-disable-next-line require(modulePath)(new RecipeWebview(), data); + debug('Initialize Recipe'); } catch (err) { - console.error(err); + debug('Recipe initialization failed', err); } }); @@ -31,6 +34,7 @@ new ContextMenuListener((info) => { // eslint-disable-line ipcRenderer.on('settings-update', (e, data) => { spellchecker.toggleSpellchecker(data.enableSpellchecking); + debug('Settings update received', data); }); // initSpellche -- cgit v1.2.3-70-g09d2 From a01ec7fe971ef863caae4c4a70df2d015f1dd62e Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 28 Mar 2018 11:06:02 +0200 Subject: minor cleanup --- src/electron/ipc-api/settings.js | 4 ---- src/stores/SettingsStore.js | 5 ----- 2 files changed, 9 deletions(-) (limited to 'src/stores') diff --git a/src/electron/ipc-api/settings.js b/src/electron/ipc-api/settings.js index 00bdc0113..3eab68a91 100644 --- a/src/electron/ipc-api/settings.js +++ b/src/electron/ipc-api/settings.js @@ -1,10 +1,6 @@ import { ipcMain } from 'electron'; export default (params) => { - ipcMain.on('settings', (event, args) => { - params.settings.set(args); - }); - ipcMain.on('getAppSettings', () => { params.mainWindow.webContents.send('appSettings', params.settings.all); }); diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 075cb6482..fe0ce2be9 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -65,11 +65,6 @@ export default class SettingsStore extends Store { } } - // Reactions - _shareSettingsWithMainProcess() { - ipcRenderer.send('settings', this.all); - } - // Helper _migrate() { const legacySettings = localStorage.getItem('app'); -- cgit v1.2.3-70-g09d2 From 655a6ed192bb1942b641f073b8f0db10c8692374 Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 28 Mar 2018 14:55:51 +0200 Subject: fix(Windows): Hide title bar when in fullscreen --- src/components/layout/AppLayout.js | 4 +++- src/containers/layout/AppLayoutContainer.js | 1 + src/stores/AppStore.js | 10 ++++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/stores') diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index 66aef1730..746775a7f 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js @@ -43,6 +43,7 @@ const messages = defineMessages({ @observer export default class AppLayout extends Component { static propTypes = { + isFullScreen: PropTypes.bool.isRequired, sidebar: PropTypes.element.isRequired, services: PropTypes.element.isRequired, children: PropTypes.element, @@ -69,6 +70,7 @@ export default class AppLayout extends Component { render() { const { + isFullScreen, sidebar, services, children, @@ -90,7 +92,7 @@ export default class AppLayout extends Component { return (
- {isWindows && } + {isWindows && !isFullScreen && }
{sidebar}
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 075bd5e34..222ffdc1a 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js @@ -106,6 +106,7 @@ export default class AppLayoutContainer extends Component { return ( { this.isOnline = true; }); window.addEventListener('offline', () => { this.isOnline = false; }); + mainWindow.on('enter-full-screen', () => { this.isFullScreen = true; }); + mainWindow.on('leave-full-screen', () => { this.isFullScreen = false; }); + + this.isOnline = navigator.onLine; // Check if Franz should launch on start @@ -170,8 +178,6 @@ export default class AppStore extends Store { this.actions.service.setActive({ serviceId }); - const mainWindow = remote.getCurrentWindow(); - if (isWindows) { mainWindow.restore(); } else if (isLinux) { -- cgit v1.2.3-70-g09d2 From dd62880081e91e906c9b57b68b529fecd68251c6 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 28 Mar 2018 15:13:31 +0200 Subject: fix linting issue --- src/stores/SettingsStore.js | 1 - 1 file changed, 1 deletion(-) (limited to 'src/stores') diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index fe0ce2be9..82fc2a279 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -1,4 +1,3 @@ -import { ipcRenderer } from 'electron'; import { action, computed, observable } from 'mobx'; import localStorage from 'mobx-localstorage'; -- cgit v1.2.3-70-g09d2 From cb546fb8d5f341a1cad0ff3f29540b4480eb27bd Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Tue, 3 Apr 2018 19:46:10 +0200 Subject: Fix reintroduced mobx issue with non-existing keys --- src/stores/SettingsStore.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/stores') diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 82fc2a279..d1327899c 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -20,7 +20,9 @@ export default class SettingsStore extends Store { this.actions.settings.remove.listen(this._remove.bind(this)); } - setup() { + async setup() { + // We need to wait until `appSettingsRequest` has been executed once, otherwise we can't patch the result. If we don't wait we'd run into an issue with mobx not reacting to changes of previously not existing keys + await this.appSettingsRequest._promise; this._migrate(); } -- cgit v1.2.3-70-g09d2 From 4dae1ca3c8498306e6013f97aebc8f39d855ed7c Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Tue, 3 Apr 2018 19:55:12 +0200 Subject: We don't need to migrate this information as it will be set anyway --- src/stores/SettingsStore.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/stores') diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index d1327899c..d8519c609 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -83,8 +83,6 @@ export default class SettingsStore extends Store { showMessageBadgeWhenMuted: legacySettings.showMessageBadgeWhenMuted, showDisabledServices: legacySettings.showDisabledServices, enableSpellchecking: legacySettings.enableSpellchecking, - locale: legacySettings.locale, - beta: legacySettings.beta, }, }); -- cgit v1.2.3-70-g09d2 From 7d8a47876569c0a80195f9ddea570e967e972b57 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 15 Nov 2018 12:18:44 +0100 Subject: Remove flow types --- src/models/News.js | 8 ++++---- src/models/Plan.js | 4 ++-- src/models/RecipePreview.js | 8 ++++---- src/models/Service.js | 2 +- src/stores/UIStore.js | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/stores') diff --git a/src/models/News.js b/src/models/News.js index a96e6550f..caf1d70e5 100644 --- a/src/models/News.js +++ b/src/models/News.js @@ -1,10 +1,10 @@ // @flow export default class News { - id: string = ''; - message: string = ''; - type: string = 'primary'; - sticky: bool = false; + id = ''; + message = ''; + type = 'primary'; + sticky = false; constructor(data) { if (!data.id) { diff --git a/src/models/Plan.js b/src/models/Plan.js index e77353824..c7b4a0962 100644 --- a/src/models/Plan.js +++ b/src/models/Plan.js @@ -1,11 +1,11 @@ // @flow export default class Plan { - month: { + month = { id: '', price: 0, } - year: { + year = { id: '', price: 0, } diff --git a/src/models/RecipePreview.js b/src/models/RecipePreview.js index 525a5c4b5..7470d757a 100644 --- a/src/models/RecipePreview.js +++ b/src/models/RecipePreview.js @@ -1,10 +1,10 @@ // @flow export default class RecipePreview { - id: string = ''; - name: string = ''; - icon: string = ''; // TODO: check if this isn't replaced by `icons` - featured: bool = false; + id = ''; + name = ''; + icon = ''; // TODO: check if this isn't replaced by `icons` + featured = false; constructor(data) { if (!data.id) { diff --git a/src/models/Service.js b/src/models/Service.js index bafb3f564..4f8767dbe 100644 --- a/src/models/Service.js +++ b/src/models/Service.js @@ -7,7 +7,7 @@ export default class Service { recipe = ''; webview = null; timer = null; - events: {}; + events = {}; isAttached = false; diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js index b391bdcae..bee6c8bcf 100644 --- a/src/stores/UIStore.js +++ b/src/stores/UIStore.js @@ -26,7 +26,7 @@ export default class UIStore extends Store { this.stores.router.push(settingsPath); } - @action _closeSettings(): void { + @action _closeSettings() { this.stores.router.push('/'); } -- cgit v1.2.3-70-g09d2 From 8f5de18c754230540f731dbd12828ad8b850d1f2 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 15 Nov 2018 12:21:28 +0100 Subject: Fix minor issues due to babel upgrade --- src/api/server/ServerApi.js | 2 +- src/index.js | 5 +++++ src/stores/SettingsStore.js | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src/stores') diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js index 353faa7f4..2e80e520b 100644 --- a/src/api/server/ServerApi.js +++ b/src/api/server/ServerApi.js @@ -35,7 +35,7 @@ module.paths.unshift( ); const { app } = remote; -const fetch = remote.require('electron-fetch'); +const { default: fetch } = remote.require('electron-fetch'); const SERVER_URL = API; const API_VERSION = 'v1'; diff --git a/src/index.js b/src/index.js index 5ba901b89..5fbe3bc4f 100644 --- a/src/index.js +++ b/src/index.js @@ -19,6 +19,11 @@ const debug = require('debug')('App'); let mainWindow; let willQuitApp = false; +// DEV MODE: Save user data into FranzDev +if (isDevMode) { + app.setPath('userData', path.join(app.getPath('appData'), 'FranzDev')); +} + // Ensure that the recipe directory exists fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp')); fs.ensureFileSync(path.join(app.getPath('userData'), 'window-state.json')); diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index d8519c609..9270a6481 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -68,7 +68,7 @@ export default class SettingsStore extends Store { // Helper _migrate() { - const legacySettings = localStorage.getItem('app'); + const legacySettings = localStorage.getItem('app') || {}; if (!this.all.migration['5.0.0-beta.17-settings']) { this.actions.settings.update({ -- cgit v1.2.3-70-g09d2 From 1483b63d34aa9b0eadcebe6e068efc3ce1aa7460 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 15 Nov 2018 21:26:45 +0100 Subject: Add migration task to initially set darkMode --- src/stores/SettingsStore.js | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'src/stores') diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 9270a6481..019ec12bb 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -1,5 +1,6 @@ import { action, computed, observable } from 'mobx'; import localStorage from 'mobx-localstorage'; +import isDarkMode from '@adlk/mojave-isdarkmode'; import Store from './lib/Store'; import SettingsModel from '../models/Settings'; @@ -23,7 +24,7 @@ export default class SettingsStore extends Store { async setup() { // We need to wait until `appSettingsRequest` has been executed once, otherwise we can't patch the result. If we don't wait we'd run into an issue with mobx not reacting to changes of previously not existing keys await this.appSettingsRequest._promise; - this._migrate(); + await this._migrate(); } @computed get all() { @@ -67,7 +68,7 @@ export default class SettingsStore extends Store { } // Helper - _migrate() { + async _migrate() { const legacySettings = localStorage.getItem('app') || {}; if (!this.all.migration['5.0.0-beta.17-settings']) { @@ -104,5 +105,26 @@ export default class SettingsStore extends Store { debug('Migrated settings to split stores'); } + + // Enable dark mode once + if (!this.all.migration['5.0.0-beta.19-settings']) { + this.actions.settings.update({ + type: 'app', + data: { + darkMode: await isDarkMode(), + }, + }); + + this.actions.settings.update({ + type: 'migration', + data: { + '5.0.0-beta.19-settings': true, + }, + }); + + localStorage.removeItem('app'); + + debug('Set up dark mode'); + } } } -- cgit v1.2.3-70-g09d2 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/I18n.js | 3 +-- src/components/auth/AuthLayout.js | 3 +-- src/components/auth/Import.js | 3 +-- src/components/auth/Invite.js | 3 +-- src/components/auth/Login.js | 3 +-- src/components/auth/Password.js | 3 +-- src/components/auth/Pricing.js | 3 +-- src/components/auth/Signup.js | 3 +-- src/components/auth/Welcome.js | 3 +-- src/components/layout/AppLayout.js | 3 +-- src/components/layout/Sidebar.js | 3 +-- src/components/services/content/ServiceDisabled.js | 3 +-- src/components/services/content/ServiceWebview.js | 3 +-- src/components/services/content/Services.js | 3 +-- src/components/services/content/WebviewCrashHandler.js | 3 +-- src/components/services/tabs/TabItem.js | 6 +++--- src/components/services/tabs/Tabbar.js | 3 +-- src/components/settings/SettingsLayout.js | 3 +-- src/components/settings/account/AccountDashboard.js | 3 +-- src/components/settings/recipes/RecipeItem.js | 3 +-- src/components/settings/recipes/RecipesDashboard.js | 3 +-- 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 +-- src/components/settings/settings/EditSettingsForm.js | 3 +-- src/components/settings/user/EditUserForm.js | 3 +-- src/components/subscription/SubscriptionForm.js | 3 +-- src/components/subscription/SubscriptionPopup.js | 3 +-- src/components/ui/Button.js | 3 +-- src/components/ui/ImageUpload.js | 4 +--- src/components/ui/InfoBar.js | 3 +-- src/components/ui/Infobox.js | 3 +-- src/components/ui/Input.js | 3 +-- src/components/ui/Link.js | 4 +--- src/components/ui/Radio.js | 3 +-- src/components/ui/SearchInput.js | 3 +-- src/components/ui/Select.js | 3 +-- src/components/ui/StatusBarTargetUrl.js | 3 +-- src/components/ui/Tabs/Tabs.js | 3 +-- src/components/ui/Toggle.js | 3 +-- src/containers/auth/AuthLayoutContainer.js | 3 +-- src/containers/auth/ImportScreen.js | 3 +-- src/containers/auth/InviteScreen.js | 3 +-- src/containers/auth/LoginScreen.js | 3 +-- src/containers/auth/PasswordScreen.js | 3 +-- src/containers/auth/PricingScreen.js | 3 +-- src/containers/auth/SignupScreen.js | 3 +-- src/containers/auth/WelcomeScreen.js | 3 +-- src/containers/layout/AppLayoutContainer.js | 3 +-- src/containers/settings/AccountScreen.js | 3 +-- src/containers/settings/EditServiceScreen.js | 3 +-- src/containers/settings/EditSettingsScreen.js | 3 +-- src/containers/settings/EditUserScreen.js | 3 +-- src/containers/settings/InviteScreen.js | 3 +-- src/containers/settings/RecipesScreen.js | 3 +-- src/containers/settings/ServicesScreen.js | 3 +-- src/containers/settings/SettingsWindow.js | 3 +-- src/containers/subscription/SubscriptionFormScreen.js | 3 +-- src/containers/subscription/SubscriptionPopupScreen.js | 3 +-- src/stores/ServicesStore.js | 2 +- src/webview/plugin.js | 2 +- 62 files changed, 64 insertions(+), 125 deletions(-) (limited to 'src/stores') diff --git a/src/I18n.js b/src/I18n.js index 4ee34157c..e33141576 100644 --- a/src/I18n.js +++ b/src/I18n.js @@ -7,8 +7,7 @@ import { oneOrManyChildElements } from './prop-types'; import translations from './i18n/translations'; import UserStore from './stores/UserStore'; -@inject('stores') @observer -export default class I18N extends Component { +export default @inject('stores') @observer class I18N extends Component { componentDidUpdate() { window.franz.menu.rebuild(); } diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.js index 2741b8a15..4c991797c 100644 --- a/src/components/auth/AuthLayout.js +++ b/src/components/auth/AuthLayout.js @@ -10,8 +10,7 @@ import InfoBar from '../ui/InfoBar'; import { oneOrManyChildElements, globalError as globalErrorPropType } from '../../prop-types'; import globalMessages from '../../i18n/globalMessages'; -@observer -export default class AuthLayout extends Component { +export default @observer class AuthLayout extends Component { static propTypes = { children: oneOrManyChildElements.isRequired, pathname: PropTypes.string.isRequired, diff --git a/src/components/auth/Import.js b/src/components/auth/Import.js index 9ba14e768..0d5feb274 100644 --- a/src/components/auth/Import.js +++ b/src/components/auth/Import.js @@ -28,8 +28,7 @@ const messages = defineMessages({ }, }); -@observer -export default class Import extends Component { +export default @observer class Import extends Component { static propTypes = { services: MobxPropTypes.arrayOrObservableArray.isRequired, onSubmit: PropTypes.func.isRequired, diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js index f1c16986b..96821a61a 100644 --- a/src/components/auth/Invite.js +++ b/src/components/auth/Invite.js @@ -43,8 +43,7 @@ const messages = defineMessages({ }, }); -@observer -export default class Invite extends Component { +export default @observer class Invite extends Component { static propTypes = { onSubmit: PropTypes.func.isRequired, embed: PropTypes.bool, diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js index 4a3cd6776..f465b35a5 100644 --- a/src/components/auth/Login.js +++ b/src/components/auth/Login.js @@ -55,8 +55,7 @@ const messages = defineMessages({ }, }); -@observer -export default class Login extends Component { +export default @observer class Login extends Component { static propTypes = { onSubmit: PropTypes.func.isRequired, isSubmitting: PropTypes.bool.isRequired, diff --git a/src/components/auth/Password.js b/src/components/auth/Password.js index 5bcc80b6e..ad34e39af 100644 --- a/src/components/auth/Password.js +++ b/src/components/auth/Password.js @@ -41,8 +41,7 @@ const messages = defineMessages({ }, }); -@observer -export default class Password extends Component { +export default @observer class Password extends Component { static propTypes = { onSubmit: PropTypes.func.isRequired, isSubmitting: PropTypes.bool.isRequired, diff --git a/src/components/auth/Pricing.js b/src/components/auth/Pricing.js index 3cc8d5f6b..f08129568 100644 --- a/src/components/auth/Pricing.js +++ b/src/components/auth/Pricing.js @@ -28,8 +28,7 @@ const messages = defineMessages({ }, }); -@observer -export default class Signup extends Component { +export default @observer class Signup extends Component { static propTypes = { donor: MobxPropTypes.objectOrObservableObject.isRequired, isLoading: PropTypes.bool.isRequired, diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js index 923aa456d..bbcad8b67 100644 --- a/src/components/auth/Signup.js +++ b/src/components/auth/Signup.js @@ -65,8 +65,7 @@ const messages = defineMessages({ }, }); -@observer -export default class Signup extends Component { +export default @observer class Signup extends Component { static propTypes = { onSubmit: PropTypes.func.isRequired, isSubmitting: PropTypes.bool.isRequired, diff --git a/src/components/auth/Welcome.js b/src/components/auth/Welcome.js index 9e1c762a5..f6d77f70f 100644 --- a/src/components/auth/Welcome.js +++ b/src/components/auth/Welcome.js @@ -16,8 +16,7 @@ const messages = defineMessages({ }, }); -@observer -export default class Login extends Component { +export default @observer class Login extends Component { static propTypes = { loginRoute: PropTypes.string.isRequired, signupRoute: PropTypes.string.isRequired, diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index 746775a7f..c2e811f3e 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js @@ -40,8 +40,7 @@ const messages = defineMessages({ }, }); -@observer -export default class AppLayout extends Component { +export default @observer class AppLayout extends Component { static propTypes = { isFullScreen: PropTypes.bool.isRequired, sidebar: PropTypes.element.isRequired, diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js index fa269f216..6ea95bf88 100644 --- a/src/components/layout/Sidebar.js +++ b/src/components/layout/Sidebar.js @@ -26,8 +26,7 @@ const messages = defineMessages({ }, }); -@observer -export default class Sidebar extends Component { +export default @observer class Sidebar extends Component { static propTypes = { openSettings: PropTypes.func.isRequired, toggleMuteApp: PropTypes.func.isRequired, diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.js index b5af3743d..58fb38d8c 100644 --- a/src/components/services/content/ServiceDisabled.js +++ b/src/components/services/content/ServiceDisabled.js @@ -16,8 +16,7 @@ const messages = defineMessages({ }, }); -@observer -export default class ServiceDisabled extends Component { +export default @observer class ServiceDisabled extends Component { static propTypes = { name: PropTypes.string.isRequired, enable: PropTypes.func.isRequired, diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js index c146abf4e..7163209ee 100644 --- a/src/components/services/content/ServiceWebview.js +++ b/src/components/services/content/ServiceWebview.js @@ -10,8 +10,7 @@ import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl'; import WebviewCrashHandler from './WebviewCrashHandler'; import ServiceDisabled from './ServiceDisabled'; -@observer -export default class ServiceWebview extends Component { +export default @observer class ServiceWebview extends Component { static propTypes = { service: PropTypes.instanceOf(ServiceModel).isRequired, setWebviewReference: PropTypes.func.isRequired, diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js index b1322afc2..4cbd51043 100644 --- a/src/components/services/content/Services.js +++ b/src/components/services/content/Services.js @@ -18,8 +18,7 @@ const messages = defineMessages({ }, }); -@observer -export default class Services extends Component { +export default @observer class Services extends Component { static propTypes = { services: MobxPropTypes.arrayOrObservableArray.isRequired, setWebviewReference: PropTypes.func.isRequired, diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js index d3e6951f3..3be1fccf4 100644 --- a/src/components/services/content/WebviewCrashHandler.js +++ b/src/components/services/content/WebviewCrashHandler.js @@ -24,8 +24,7 @@ const messages = defineMessages({ }, }); -@observer -export default class WebviewCrashHandler extends Component { +export default @observer class WebviewCrashHandler extends Component { static propTypes = { name: PropTypes.string.isRequired, reload: PropTypes.func.isRequired, diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js index 638262f7f..8de7dc438 100644 --- a/src/components/services/tabs/TabItem.js +++ b/src/components/services/tabs/TabItem.js @@ -141,10 +141,10 @@ class TabItem extends Component { {service.unreadIndirectMessageCount > 0 && service.unreadDirectMessageCount === 0 && service.isIndirectMessageBadgeEnabled && ( - + • - - )} + + )} ); } diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js index ceb88c51c..dd5c2140f 100644 --- a/src/components/services/tabs/Tabbar.js +++ b/src/components/services/tabs/Tabbar.js @@ -4,8 +4,7 @@ import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; import TabBarSortableList from './TabBarSortableList'; -@observer -export default class TabBar extends Component { +export default @observer class TabBar extends Component { static propTypes = { services: MobxPropTypes.arrayOrObservableArray.isRequired, setActive: PropTypes.func.isRequired, diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.js index d5392ddba..3cb08feb1 100644 --- a/src/components/settings/SettingsLayout.js +++ b/src/components/settings/SettingsLayout.js @@ -5,8 +5,7 @@ import { observer } from 'mobx-react'; import { oneOrManyChildElements } from '../../prop-types'; import Appear from '../ui/effects/Appear'; -@observer -export default class SettingsLayout extends Component { +export default @observer class SettingsLayout extends Component { static propTypes = { navigation: PropTypes.element.isRequired, children: oneOrManyChildElements.isRequired, diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js index 4992f0913..2fcfdfc9a 100644 --- a/src/components/settings/account/AccountDashboard.js +++ b/src/components/settings/account/AccountDashboard.js @@ -74,8 +74,7 @@ const messages = defineMessages({ }, }); -@observer -export default class AccountDashboard extends Component { +export default @observer class AccountDashboard extends Component { static propTypes = { user: MobxPropTypes.observableObject.isRequired, orders: MobxPropTypes.arrayOrObservableArray.isRequired, diff --git a/src/components/settings/recipes/RecipeItem.js b/src/components/settings/recipes/RecipeItem.js index 7b2f64d26..dae8891b3 100644 --- a/src/components/settings/recipes/RecipeItem.js +++ b/src/components/settings/recipes/RecipeItem.js @@ -4,8 +4,7 @@ import { observer } from 'mobx-react'; import RecipePreviewModel from '../../../models/RecipePreview'; -@observer -export default class RecipeItem extends Component { +export default @observer class RecipeItem extends Component { static propTypes = { recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired, onClick: PropTypes.func.isRequired, diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js index 4610c69a5..cd783200f 100644 --- a/src/components/settings/recipes/RecipesDashboard.js +++ b/src/components/settings/recipes/RecipesDashboard.js @@ -46,8 +46,7 @@ const messages = defineMessages({ }, }); -@observer -export default class RecipesDashboard extends Component { +export default @observer class RecipesDashboard extends Component { static propTypes = { recipes: MobxPropTypes.arrayOrObservableArray.isRequired, isLoading: PropTypes.bool.isRequired, 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, diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 97f535594..3d265ce31 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js @@ -82,8 +82,7 @@ const messages = defineMessages({ }, }); -@observer -export default class EditSettingsForm extends Component { +export default @observer class EditSettingsForm extends Component { static propTypes = { checkForUpdates: PropTypes.func.isRequired, installUpdate: PropTypes.func.isRequired, diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js index f36887fc2..6c0305089 100644 --- a/src/components/settings/user/EditUserForm.js +++ b/src/components/settings/user/EditUserForm.js @@ -39,8 +39,7 @@ const messages = defineMessages({ }, }); -@observer -export default class EditServiceForm extends Component { +export default @observer class EditServiceForm extends Component { static propTypes = { status: MobxPropTypes.observableArray.isRequired, form: PropTypes.instanceOf(Form).isRequired, diff --git a/src/components/subscription/SubscriptionForm.js b/src/components/subscription/SubscriptionForm.js index dd350479d..5992e4204 100644 --- a/src/components/subscription/SubscriptionForm.js +++ b/src/components/subscription/SubscriptionForm.js @@ -71,8 +71,7 @@ const messages = defineMessages({ }, }); -@observer -export default class SubscriptionForm extends Component { +export default @observer class SubscriptionForm extends Component { static propTypes = { plan: MobxPropTypes.objectOrObservableObject.isRequired, isLoading: PropTypes.bool.isRequired, diff --git a/src/components/subscription/SubscriptionPopup.js b/src/components/subscription/SubscriptionPopup.js index 528d02907..f3c63e7ee 100644 --- a/src/components/subscription/SubscriptionPopup.js +++ b/src/components/subscription/SubscriptionPopup.js @@ -17,8 +17,7 @@ const messages = defineMessages({ }, }); -@observer -export default class SubscriptionPopup extends Component { +export default @observer class SubscriptionPopup extends Component { static propTypes = { url: PropTypes.string.isRequired, closeWindow: PropTypes.func.isRequired, diff --git a/src/components/ui/Button.js b/src/components/ui/Button.js index 554206cb7..309e05bb4 100644 --- a/src/components/ui/Button.js +++ b/src/components/ui/Button.js @@ -4,8 +4,7 @@ import { observer } from 'mobx-react'; import Loader from 'react-loader'; import classnames from 'classnames'; -@observer -export default class Button extends Component { +export default @observer class Button extends Component { static propTypes = { className: PropTypes.string, label: PropTypes.string.isRequired, diff --git a/src/components/ui/ImageUpload.js b/src/components/ui/ImageUpload.js index 81c3b8da6..76f77d631 100644 --- a/src/components/ui/ImageUpload.js +++ b/src/components/ui/ImageUpload.js @@ -2,12 +2,10 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { observer } from 'mobx-react'; import { Field } from 'mobx-react-form'; -// import Loader from 'react-loader'; import classnames from 'classnames'; import Dropzone from 'react-dropzone'; -@observer -export default class ImageUpload extends Component { +export default @observer class ImageUpload extends Component { static propTypes = { field: PropTypes.instanceOf(Field).isRequired, className: PropTypes.string, diff --git a/src/components/ui/InfoBar.js b/src/components/ui/InfoBar.js index 84a5f1446..94a1ddf76 100644 --- a/src/components/ui/InfoBar.js +++ b/src/components/ui/InfoBar.js @@ -7,8 +7,7 @@ import Loader from 'react-loader'; // import { oneOrManyChildElements } from '../../prop-types'; import Appear from '../ui/effects/Appear'; -@observer -export default class InfoBar extends Component { +export default @observer class InfoBar extends Component { static propTypes = { // eslint-disable-next-line children: PropTypes.any.isRequired, diff --git a/src/components/ui/Infobox.js b/src/components/ui/Infobox.js index 2d063c7ef..77051f567 100644 --- a/src/components/ui/Infobox.js +++ b/src/components/ui/Infobox.js @@ -4,8 +4,7 @@ import { observer } from 'mobx-react'; import classnames from 'classnames'; import Loader from 'react-loader'; -@observer -export default class Infobox extends Component { +export default @observer class Infobox extends Component { static propTypes = { children: PropTypes.any.isRequired, // eslint-disable-line icon: PropTypes.string, diff --git a/src/components/ui/Input.js b/src/components/ui/Input.js index 0bb9f23bf..7fc5b69b0 100644 --- a/src/components/ui/Input.js +++ b/src/components/ui/Input.js @@ -6,8 +6,7 @@ import classnames from 'classnames'; import { scorePassword as scorePasswordFunc } from '../../helpers/password-helpers'; -@observer -export default class Input extends Component { +export default @observer class Input extends Component { static propTypes = { field: PropTypes.instanceOf(Field).isRequired, className: PropTypes.string, diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js index f5da921fa..0602290f1 100644 --- a/src/components/ui/Link.js +++ b/src/components/ui/Link.js @@ -9,9 +9,7 @@ import { oneOrManyChildElements } from '../../prop-types'; import { matchRoute } from '../../helpers/routing-helpers'; // TODO: create container component for this component - -@inject('stores') @observer -export default class Link extends Component { +export default @inject('stores') @observer class Link extends Component { onClick(e) { if (this.props.target === '_blank') { e.preventDefault(); diff --git a/src/components/ui/Radio.js b/src/components/ui/Radio.js index b54cfc820..63ca6f9b8 100644 --- a/src/components/ui/Radio.js +++ b/src/components/ui/Radio.js @@ -4,8 +4,7 @@ import { observer } from 'mobx-react'; import { Field } from 'mobx-react-form'; import classnames from 'classnames'; -@observer -export default class Radio extends Component { +export default @observer class Radio extends Component { static propTypes = { field: PropTypes.instanceOf(Field).isRequired, className: PropTypes.string, diff --git a/src/components/ui/SearchInput.js b/src/components/ui/SearchInput.js index a94cde201..5a9571d27 100644 --- a/src/components/ui/SearchInput.js +++ b/src/components/ui/SearchInput.js @@ -5,8 +5,7 @@ import classnames from 'classnames'; import uuidv1 from 'uuid/v1'; import { debounce } from 'lodash'; -@observer -export default class SearchInput extends Component { +export default @observer class SearchInput extends Component { static propTypes = { value: PropTypes.string, placeholder: PropTypes.string, diff --git a/src/components/ui/Select.js b/src/components/ui/Select.js index 2a877af3e..abcad417e 100644 --- a/src/components/ui/Select.js +++ b/src/components/ui/Select.js @@ -4,8 +4,7 @@ import { observer } from 'mobx-react'; import { Field } from 'mobx-react-form'; import classnames from 'classnames'; -@observer -export default class Select extends Component { +export default @observer class Select extends Component { static propTypes = { field: PropTypes.instanceOf(Field).isRequired, className: PropTypes.string, diff --git a/src/components/ui/StatusBarTargetUrl.js b/src/components/ui/StatusBarTargetUrl.js index b7b198f42..4285a343c 100644 --- a/src/components/ui/StatusBarTargetUrl.js +++ b/src/components/ui/StatusBarTargetUrl.js @@ -5,8 +5,7 @@ import classnames from 'classnames'; import Appear from '../ui/effects/Appear'; -@observer -export default class StatusBarTargetUrl extends Component { +export default @observer class StatusBarTargetUrl extends Component { static propTypes = { className: PropTypes.string, text: PropTypes.string, diff --git a/src/components/ui/Tabs/Tabs.js b/src/components/ui/Tabs/Tabs.js index 50397f9bb..12f650ffd 100644 --- a/src/components/ui/Tabs/Tabs.js +++ b/src/components/ui/Tabs/Tabs.js @@ -5,8 +5,7 @@ import classnames from 'classnames'; import { oneOrManyChildElements } from '../../../prop-types'; -@observer -export default class Tab extends Component { +export default @observer class Tab extends Component { static propTypes = { children: oneOrManyChildElements.isRequired, active: PropTypes.number, diff --git a/src/components/ui/Toggle.js b/src/components/ui/Toggle.js index 62d46393e..f7c2ec955 100644 --- a/src/components/ui/Toggle.js +++ b/src/components/ui/Toggle.js @@ -4,8 +4,7 @@ import { observer } from 'mobx-react'; import classnames from 'classnames'; import { Field } from 'mobx-react-form'; -@observer -export default class Toggle extends Component { +export default @observer class Toggle extends Component { static propTypes = { field: PropTypes.instanceOf(Field).isRequired, className: PropTypes.string, diff --git a/src/containers/auth/AuthLayoutContainer.js b/src/containers/auth/AuthLayoutContainer.js index 004054fdd..62b589d2f 100644 --- a/src/containers/auth/AuthLayoutContainer.js +++ b/src/containers/auth/AuthLayoutContainer.js @@ -8,8 +8,7 @@ import GlobalErrorStore from '../../stores/GlobalErrorStore'; import { oneOrManyChildElements } from '../../prop-types'; -@inject('stores', 'actions') @observer -export default class AuthLayoutContainer extends Component { +export default @inject('stores', 'actions') @observer class AuthLayoutContainer extends Component { static propTypes = { children: oneOrManyChildElements.isRequired, location: PropTypes.shape({ diff --git a/src/containers/auth/ImportScreen.js b/src/containers/auth/ImportScreen.js index ddd56ffb6..fc46f8b54 100644 --- a/src/containers/auth/ImportScreen.js +++ b/src/containers/auth/ImportScreen.js @@ -5,8 +5,7 @@ import Import from '../../components/auth/Import'; import UserStore from '../../stores/UserStore'; import { gaPage } from '../../lib/analytics'; -@inject('stores', 'actions') @observer -export default class ImportScreen extends Component { +export default @inject('stores', 'actions') @observer class ImportScreen extends Component { componentDidMount() { gaPage('Auth/Import'); } diff --git a/src/containers/auth/InviteScreen.js b/src/containers/auth/InviteScreen.js index 059888c99..26bf97038 100644 --- a/src/containers/auth/InviteScreen.js +++ b/src/containers/auth/InviteScreen.js @@ -4,8 +4,7 @@ import { inject, observer } from 'mobx-react'; import Invite from '../../components/auth/Invite'; import { gaPage } from '../../lib/analytics'; -@inject('stores', 'actions') @observer -export default class InviteScreen extends Component { +export default @inject('stores', 'actions') @observer class InviteScreen extends Component { componentDidMount() { gaPage('Auth/Invite'); } diff --git a/src/containers/auth/LoginScreen.js b/src/containers/auth/LoginScreen.js index 9e22c5141..865bd38f8 100644 --- a/src/containers/auth/LoginScreen.js +++ b/src/containers/auth/LoginScreen.js @@ -7,8 +7,7 @@ import { gaPage } from '../../lib/analytics'; import { globalError as globalErrorPropType } from '../../prop-types'; -@inject('stores', 'actions') @observer -export default class LoginScreen extends Component { +export default @inject('stores', 'actions') @observer class LoginScreen extends Component { static propTypes = { error: globalErrorPropType.isRequired, }; diff --git a/src/containers/auth/PasswordScreen.js b/src/containers/auth/PasswordScreen.js index d88cb08e6..236fd2031 100644 --- a/src/containers/auth/PasswordScreen.js +++ b/src/containers/auth/PasswordScreen.js @@ -5,8 +5,7 @@ import Password from '../../components/auth/Password'; import UserStore from '../../stores/UserStore'; import { gaPage } from '../../lib/analytics'; -@inject('stores', 'actions') @observer -export default class PasswordScreen extends Component { +export default @inject('stores', 'actions') @observer class PasswordScreen extends Component { componentDidMount() { gaPage('Auth/Password Retrieve'); } diff --git a/src/containers/auth/PricingScreen.js b/src/containers/auth/PricingScreen.js index 7e1586535..34b512e15 100644 --- a/src/containers/auth/PricingScreen.js +++ b/src/containers/auth/PricingScreen.js @@ -10,8 +10,7 @@ import { gaPage } from '../../lib/analytics'; import { globalError as globalErrorPropType } from '../../prop-types'; -@inject('stores', 'actions') @observer -export default class PricingScreen extends Component { +export default @inject('stores', 'actions') @observer class PricingScreen extends Component { static propTypes = { error: globalErrorPropType.isRequired, }; diff --git a/src/containers/auth/SignupScreen.js b/src/containers/auth/SignupScreen.js index 3b86ab138..caf75de90 100644 --- a/src/containers/auth/SignupScreen.js +++ b/src/containers/auth/SignupScreen.js @@ -8,8 +8,7 @@ import { gaPage } from '../../lib/analytics'; import { globalError as globalErrorPropType } from '../../prop-types'; -@inject('stores', 'actions') @observer -export default class SignupScreen extends Component { +export default @inject('stores', 'actions') @observer class SignupScreen extends Component { static propTypes = { error: globalErrorPropType.isRequired, }; diff --git a/src/containers/auth/WelcomeScreen.js b/src/containers/auth/WelcomeScreen.js index e413264a6..2c120f81c 100644 --- a/src/containers/auth/WelcomeScreen.js +++ b/src/containers/auth/WelcomeScreen.js @@ -7,8 +7,7 @@ import UserStore from '../../stores/UserStore'; import RecipePreviewsStore from '../../stores/RecipePreviewsStore'; import { gaPage } from '../../lib/analytics'; -@inject('stores', 'actions') @observer -export default class LoginScreen extends Component { +export default @inject('stores', 'actions') @observer class LoginScreen extends Component { componentDidMount() { gaPage('Auth/Welcome'); } diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 9212f809f..f63fe3717 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js @@ -17,8 +17,7 @@ import Sidebar from '../../components/layout/Sidebar'; import Services from '../../components/services/content/Services'; import AppLoader from '../../components/ui/AppLoader'; -@inject('stores', 'actions') @observer -export default class AppLayoutContainer extends Component { +export default @inject('stores', 'actions') @observer class AppLayoutContainer extends Component { static defaultProps = { children: null, }; diff --git a/src/containers/settings/AccountScreen.js b/src/containers/settings/AccountScreen.js index c5c2982b0..5818af0b1 100644 --- a/src/containers/settings/AccountScreen.js +++ b/src/containers/settings/AccountScreen.js @@ -12,8 +12,7 @@ import AccountDashboard from '../../components/settings/account/AccountDashboard const { BrowserWindow } = remote; -@inject('stores', 'actions') @observer -export default class AccountScreen extends Component { +export default @inject('stores', 'actions') @observer class AccountScreen extends Component { componentDidMount() { gaPage('Settings/Account Dashboard'); } diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js index 67c2731fc..1fc6bc85e 100644 --- a/src/containers/settings/EditServiceScreen.js +++ b/src/containers/settings/EditServiceScreen.js @@ -52,8 +52,7 @@ const messages = defineMessages({ }, }); -@inject('stores', 'actions') @observer -export default class EditServiceScreen extends Component { +export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component { static contextTypes = { intl: intlShape, }; diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js index 018ce663f..0b3ad0389 100644 --- a/src/containers/settings/EditSettingsScreen.js +++ b/src/containers/settings/EditSettingsScreen.js @@ -65,8 +65,7 @@ const messages = defineMessages({ }, }); -@inject('stores', 'actions') @observer -export default class EditSettingsScreen extends Component { +export default @inject('stores', 'actions') @observer class EditSettingsScreen extends Component { static contextTypes = { intl: intlShape, }; diff --git a/src/containers/settings/EditUserScreen.js b/src/containers/settings/EditUserScreen.js index dda8ce513..4c5a9117e 100644 --- a/src/containers/settings/EditUserScreen.js +++ b/src/containers/settings/EditUserScreen.js @@ -50,8 +50,7 @@ const messages = defineMessages({ }, }); -@inject('stores', 'actions') @observer -export default class EditUserScreen extends Component { +export default @inject('stores', 'actions') @observer class EditUserScreen extends Component { static contextTypes = { intl: intlShape, }; diff --git a/src/containers/settings/InviteScreen.js b/src/containers/settings/InviteScreen.js index 5f341b1b3..38ca6ec74 100644 --- a/src/containers/settings/InviteScreen.js +++ b/src/containers/settings/InviteScreen.js @@ -5,8 +5,7 @@ import { inject, observer } from 'mobx-react'; import Invite from '../../components/auth/Invite'; import { gaPage } from '../../lib/analytics'; -@inject('stores', 'actions') @observer -export default class InviteScreen extends Component { +export default @inject('stores', 'actions') @observer class InviteScreen extends Component { componentDidMount() { gaPage('Settings/Invite'); } diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js index 65341e9e3..4efe81505 100644 --- a/src/containers/settings/RecipesScreen.js +++ b/src/containers/settings/RecipesScreen.js @@ -11,8 +11,7 @@ import { gaPage } from '../../lib/analytics'; import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; -@inject('stores', 'actions') @observer -export default class RecipesScreen extends Component { +export default @inject('stores', 'actions') @observer class RecipesScreen extends Component { static propTypes = { params: PropTypes.shape({ filter: PropTypes.string, diff --git a/src/containers/settings/ServicesScreen.js b/src/containers/settings/ServicesScreen.js index 12db1bcd3..c1a133ef7 100644 --- a/src/containers/settings/ServicesScreen.js +++ b/src/containers/settings/ServicesScreen.js @@ -10,8 +10,7 @@ import { gaPage } from '../../lib/analytics'; import ServicesDashboard from '../../components/settings/services/ServicesDashboard'; -@inject('stores', 'actions') @observer -export default class ServicesScreen extends Component { +export default @inject('stores', 'actions') @observer class ServicesScreen extends Component { componentDidMount() { gaPage('Settings/Service Dashboard'); } diff --git a/src/containers/settings/SettingsWindow.js b/src/containers/settings/SettingsWindow.js index 13ca96f72..55589d0be 100644 --- a/src/containers/settings/SettingsWindow.js +++ b/src/containers/settings/SettingsWindow.js @@ -7,8 +7,7 @@ import ServicesStore from '../../stores/ServicesStore'; import Layout from '../../components/settings/SettingsLayout'; import Navigation from '../../components/settings/navigation/SettingsNavigation'; -@inject('stores', 'actions') @observer -export default class SettingsContainer extends Component { +export default @inject('stores', 'actions') @observer class SettingsContainer extends Component { render() { const { children, stores } = this.props; const { closeSettings } = this.props.actions.ui; diff --git a/src/containers/subscription/SubscriptionFormScreen.js b/src/containers/subscription/SubscriptionFormScreen.js index fc6e3c4be..9f7571bda 100644 --- a/src/containers/subscription/SubscriptionFormScreen.js +++ b/src/containers/subscription/SubscriptionFormScreen.js @@ -9,8 +9,7 @@ import SubscriptionForm from '../../components/subscription/SubscriptionForm'; const { BrowserWindow } = remote; -@inject('stores', 'actions') @observer -export default class SubscriptionFormScreen extends Component { +export default @inject('stores', 'actions') @observer class SubscriptionFormScreen extends Component { static propTypes = { onCloseWindow: PropTypes.func, content: PropTypes.oneOrManyChildElements, diff --git a/src/containers/subscription/SubscriptionPopupScreen.js b/src/containers/subscription/SubscriptionPopupScreen.js index bb0603170..6641f236d 100644 --- a/src/containers/subscription/SubscriptionPopupScreen.js +++ b/src/containers/subscription/SubscriptionPopupScreen.js @@ -5,8 +5,7 @@ import { inject, observer } from 'mobx-react'; import SubscriptionPopup from '../../components/subscription/SubscriptionPopup'; -@inject('stores', 'actions') @observer -export default class SubscriptionPopupScreen extends Component { +export default @inject('stores', 'actions') @observer class SubscriptionPopupScreen extends Component { state = { complete: false, }; diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index ccb85421a..4c2992c70 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -93,7 +93,7 @@ export default class ServicesStore extends Store { return this.stores.settings.all.app.showDisabledServices ? this.all : this.enabled; } - // This is just used to avoid unnecessary rerendering of resource-heavy webviews + // This is just used to avoid unnecessary rerendering of resource-heavy webviews @computed get allDisplayedUnordered() { const services = this.allServicesRequest.execute().result || []; return this.stores.settings.all.app.showDisabledServices ? services : services.filter(service => service.isEnabled); diff --git a/src/webview/plugin.js b/src/webview/plugin.js index c6530fef6..a148d4633 100644 --- a/src/webview/plugin.js +++ b/src/webview/plugin.js @@ -47,7 +47,7 @@ document.addEventListener('DOMContentLoaded', () => { const originalWindowOpen = window.open; window.open = (url, frameName, features) => { - // We need to differentiate if the link should be opened in a popup or in the systems default browser + // We need to differentiate if the link should be opened in a popup or in the systems default browser if (!frameName && !features) { return ipcRenderer.sendToHost('new-window', url); } -- cgit v1.2.3-70-g09d2 From 9d2447cfd493da423ce8a42a421fa8075c359da7 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 16 Nov 2018 20:40:11 +0100 Subject: Add isSystemDarkModeEnabled to AppStore --- src/containers/auth/AuthLayoutContainer.js | 1 + src/stores/AppStore.js | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/stores') diff --git a/src/containers/auth/AuthLayoutContainer.js b/src/containers/auth/AuthLayoutContainer.js index 62b589d2f..a0618e012 100644 --- a/src/containers/auth/AuthLayoutContainer.js +++ b/src/containers/auth/AuthLayoutContainer.js @@ -26,6 +26,7 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer isAPIHealthy={!stores.app.healthCheckRequest.isError} retryHealthCheck={actions.app.healthCheck} isHealthCheckLoading={stores.app.healthCheckRequest.isExecuting} + darkMode={stores.app.isSystemDarkModeEnabled} > {children} diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 38edff1b4..e24160b4c 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -5,6 +5,7 @@ import key from 'keymaster'; import { getDoNotDisturb } from '@meetfranz/electron-notification-state'; import AutoLaunch from 'auto-launch'; import prettyBytes from 'pretty-bytes'; +import isDarkMode from '@adlk/mojave-isdarkmode'; import Store from './lib/Store'; import Request from './lib/Request'; @@ -50,6 +51,8 @@ export default class AppStore extends Store { @observable isSystemMuteOverridden = false; + @observable isSystemDarkModeEnabled = false; + @observable isClearingAllCache = false; @observable isFullScreen = mainWindow.isFullScreen(); @@ -77,7 +80,7 @@ export default class AppStore extends Store { ]); } - setup() { + async setup() { this._appStartsCounter(); // Focus the active service window.addEventListener('focus', this.actions.service.focusActiveService); @@ -159,6 +162,8 @@ export default class AppStore extends Store { this.locale = this._getDefaultLocale(); this._healthCheck(); + + this.isSystemDarkModeEnabled = await isDarkMode(); } @computed get cacheSize() { -- cgit v1.2.3-70-g09d2 From 5c1aeaca015088272afa12ca76ebbdd78832ea60 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 16 Nov 2018 20:47:22 +0100 Subject: use native electron.systemPreferences.isDarkMode() --- package-lock.json | 23 ----------------------- package.json | 1 - src/stores/AppStore.js | 7 +++---- src/stores/SettingsStore.js | 4 ++-- 4 files changed, 5 insertions(+), 30 deletions(-) (limited to 'src/stores') diff --git a/package-lock.json b/package-lock.json index d75356409..1311b2369 100644 --- a/package-lock.json +++ b/package-lock.json @@ -82,29 +82,6 @@ } } }, - "@adlk/mojave-isdarkmode": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@adlk/mojave-isdarkmode/-/mojave-isdarkmode-1.0.1.tgz", - "integrity": "sha512-vNecc2GQfSYZ5znFBbgDTc/VJezg6Rpe/jesTtcBv2ojgAppg9HllxWSrnriWFuSlYmsNI3/WKfvD0ag2768vw==", - "requires": { - "debug": "^4.1.0" - }, - "dependencies": { - "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", diff --git a/package.json b/package.json index f12cb6001..259e42bda 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "author": "Stefan Malzner ", "license": "Apache-2.0", "dependencies": { - "@adlk/mojave-isdarkmode": "^1.0.1", "@babel/polyfill": "^7.0.0", "@babel/runtime": "^7.0.0", "@meetfranz/electron-notification-state": "^1.0.0", diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index e24160b4c..d1ed2596b 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -1,11 +1,10 @@ -import { remote, ipcRenderer, shell } from 'electron'; +import { remote, ipcRenderer, shell, systemPreferences } from 'electron'; import { action, computed, observable } from 'mobx'; import moment from 'moment'; import key from 'keymaster'; import { getDoNotDisturb } from '@meetfranz/electron-notification-state'; import AutoLaunch from 'auto-launch'; import prettyBytes from 'pretty-bytes'; -import isDarkMode from '@adlk/mojave-isdarkmode'; import Store from './lib/Store'; import Request from './lib/Request'; @@ -80,7 +79,7 @@ export default class AppStore extends Store { ]); } - async setup() { + setup() { this._appStartsCounter(); // Focus the active service window.addEventListener('focus', this.actions.service.focusActiveService); @@ -163,7 +162,7 @@ export default class AppStore extends Store { this._healthCheck(); - this.isSystemDarkModeEnabled = await isDarkMode(); + this.isSystemDarkModeEnabled = systemPreferences.isDarkMode(); } @computed get cacheSize() { diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 019ec12bb..31165053d 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -1,6 +1,6 @@ +import { systemPreferences } from 'electron'; import { action, computed, observable } from 'mobx'; import localStorage from 'mobx-localstorage'; -import isDarkMode from '@adlk/mojave-isdarkmode'; import Store from './lib/Store'; import SettingsModel from '../models/Settings'; @@ -111,7 +111,7 @@ export default class SettingsStore extends Store { this.actions.settings.update({ type: 'app', data: { - darkMode: await isDarkMode(), + darkMode: systemPreferences.isDarkMode(), }, }); -- cgit v1.2.3-70-g09d2 From 69e11a513e4e0ca43d0434f1d823b7f07ad81640 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 16 Nov 2018 20:52:10 +0100 Subject: Fix systemPreferences.isDarkMode call --- src/stores/AppStore.js | 4 ++-- src/stores/SettingsStore.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/stores') diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index d1ed2596b..76d9bfa53 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -1,4 +1,4 @@ -import { remote, ipcRenderer, shell, systemPreferences } from 'electron'; +import { remote, ipcRenderer, shell } from 'electron'; import { action, computed, observable } from 'mobx'; import moment from 'moment'; import key from 'keymaster'; @@ -17,7 +17,7 @@ import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '.. const debug = require('debug')('AppStore'); -const { app } = remote; +const { app, systemPreferences } = remote; const mainWindow = remote.getCurrentWindow(); diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 31165053d..4b5715628 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -1,4 +1,4 @@ -import { systemPreferences } from 'electron'; +import { remote } from 'electron'; import { action, computed, observable } from 'mobx'; import localStorage from 'mobx-localstorage'; @@ -7,6 +7,7 @@ import SettingsModel from '../models/Settings'; import Request from './lib/Request'; import CachedRequest from './lib/CachedRequest'; +const { systemPreferences } = remote; const debug = require('debug')('SettingsStore'); export default class SettingsStore extends Store { -- cgit v1.2.3-70-g09d2 From aef5033ef19bf51dbacc0dcdfe76ec2d90173531 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 22 Nov 2018 10:53:11 +0100 Subject: Add "Franz" to debug identifiers --- package.json | 2 +- src/api/server/LocalApi.js | 2 +- src/api/server/ServerApi.js | 2 +- src/electron/Settings.js | 2 +- src/index.js | 2 +- src/lib/analytics.js | 2 +- src/stores/AppStore.js | 2 +- src/stores/RecipesStore.js | 2 +- src/stores/RequestStore.js | 2 +- src/stores/ServicesStore.js | 2 +- src/stores/SettingsStore.js | 2 +- src/stores/UserStore.js | 2 +- src/webview/plugin.js | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/stores') diff --git a/package.json b/package.json index 6be38cd6f..ee2b12e99 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "private": true, "scripts": { "prestart": "npm run rebuild", - "start": "electron ./build", + "start": "DEBUG=Franz:* electron ./build", "start:local": "cross-env LOCAL_API=1 npm start", "start:live": "cross-env LIVE_API=1 npm start", "dev": "cross-env NODE_ENV=development gulp dev", diff --git a/src/api/server/LocalApi.js b/src/api/server/LocalApi.js index 78deb7aa5..4814bba66 100644 --- a/src/api/server/LocalApi.js +++ b/src/api/server/LocalApi.js @@ -3,7 +3,7 @@ import du from 'du'; import { getServicePartitionsDirectory } from '../../helpers/service-helpers.js'; -const debug = require('debug')('LocalApi'); +const debug = require('debug')('Franz:LocalApi'); const { session } = remote; diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js index 2e80e520b..ad1ffa59a 100644 --- a/src/api/server/ServerApi.js +++ b/src/api/server/ServerApi.js @@ -27,7 +27,7 @@ import { removeServicePartitionDirectory, } from '../../helpers/service-helpers.js'; -const debug = require('debug')('ServerApi'); +const debug = require('debug')('Franz:ServerApi'); module.paths.unshift( getDevRecipeDirectory(), diff --git a/src/electron/Settings.js b/src/electron/Settings.js index 254180b73..7b04406a2 100644 --- a/src/electron/Settings.js +++ b/src/electron/Settings.js @@ -3,7 +3,7 @@ import { pathExistsSync, outputJsonSync, readJsonSync } from 'fs-extra'; import { SETTINGS_PATH, DEFAULT_APP_SETTINGS } from '../config'; -const debug = require('debug')('Settings'); +const debug = require('debug')('Franz:Settings'); export default class Settings { @observable store = DEFAULT_APP_SETTINGS; diff --git a/src/index.js b/src/index.js index 65f18bb55..7d906ad71 100644 --- a/src/index.js +++ b/src/index.js @@ -12,7 +12,7 @@ import handleDeepLink from './electron/deepLinking'; import { appId } from './package.json'; // eslint-disable-line import/no-unresolved import './electron/exception'; -const debug = require('debug')('App'); +const debug = require('debug')('Franz:App'); // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. diff --git a/src/lib/analytics.js b/src/lib/analytics.js index 585cbcdba..8b9a44579 100644 --- a/src/lib/analytics.js +++ b/src/lib/analytics.js @@ -2,7 +2,7 @@ import { remote } from 'electron'; import { GA_ID } from '../config'; // import { isDevMode } from '../environment'; -const debug = require('debug')('Analytics'); +const debug = require('debug')('Franz:Analytics'); const { app } = remote; diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 76d9bfa53..9ad4cd531 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -15,7 +15,7 @@ import { gaEvent } from '../lib/analytics'; import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js'; -const debug = require('debug')('AppStore'); +const debug = require('debug')('Franz:AppStore'); const { app, systemPreferences } = remote; diff --git a/src/stores/RecipesStore.js b/src/stores/RecipesStore.js index a24308f6a..f2480bc8e 100644 --- a/src/stores/RecipesStore.js +++ b/src/stores/RecipesStore.js @@ -5,7 +5,7 @@ import CachedRequest from './lib/CachedRequest'; import Request from './lib/Request'; import { matchRoute } from '../helpers/routing-helpers'; -const debug = require('debug')('RecipeStore'); +const debug = require('debug')('Franz:RecipeStore'); export default class RecipesStore extends Store { @observable allRecipesRequest = new CachedRequest(this.api.recipes, 'all'); diff --git a/src/stores/RequestStore.js b/src/stores/RequestStore.js index 595852583..bbfe6f6df 100644 --- a/src/stores/RequestStore.js +++ b/src/stores/RequestStore.js @@ -2,7 +2,7 @@ import { action, computed, observable } from 'mobx'; import Store from './lib/Store'; -const debug = require('debug')('RequestsStore'); +const debug = require('debug')('Franz:RequestsStore'); export default class RequestStore extends Store { @observable userInfoRequest; diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 4c2992c70..c5822968a 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -7,7 +7,7 @@ import CachedRequest from './lib/CachedRequest'; import { matchRoute } from '../helpers/routing-helpers'; import { gaEvent } from '../lib/analytics'; -const debug = require('debug')('ServiceStore'); +const debug = require('debug')('Franz:ServiceStore'); export default class ServicesStore extends Store { @observable allServicesRequest = new CachedRequest(this.api.services, 'all'); diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 4b5715628..f1b067115 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -8,7 +8,7 @@ import Request from './lib/Request'; import CachedRequest from './lib/CachedRequest'; const { systemPreferences } = remote; -const debug = require('debug')('SettingsStore'); +const debug = require('debug')('Franz:SettingsStore'); export default class SettingsStore extends Store { @observable appSettingsRequest = new CachedRequest(this.api.local, 'getAppSettings'); diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index 574616925..9d8ac5657 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js @@ -9,7 +9,7 @@ import Request from './lib/Request'; import CachedRequest from './lib/CachedRequest'; import { gaEvent } from '../lib/analytics'; -const debug = require('debug')('UserStore'); +const debug = require('debug')('Franz:UserStore'); // TODO: split stores into UserStore and AuthStore export default class UserStore extends Store { diff --git a/src/webview/plugin.js b/src/webview/plugin.js index a148d4633..ee8cedbab 100644 --- a/src/webview/plugin.js +++ b/src/webview/plugin.js @@ -8,7 +8,7 @@ import RecipeWebview from './lib/RecipeWebview'; import Spellchecker from './spellchecker'; import './notifications'; -const debug = require('debug')('Plugin'); +const debug = require('debug')('Franz:Plugin'); ipcRenderer.on('initializeRecipe', (e, data) => { const modulePath = path.join(data.recipe.path, 'webview.js'); -- 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/stores') 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