diff --git a/packages/cozy-flags/package.json b/packages/cozy-flags/package.json index 100a27a22a..62b6657404 100644 --- a/packages/cozy-flags/package.json +++ b/packages/cozy-flags/package.json @@ -29,6 +29,7 @@ ] }, "dependencies": { - "detect-node": "2.0.4" + "detect-node": "2.0.4", + "microee": "^0.0.6" } } diff --git a/packages/cozy-flags/src/browser/flag.js b/packages/cozy-flags/src/browser/flag.js index d9bcb1c699..7a4f67ac58 100644 --- a/packages/cozy-flags/src/browser/flag.js +++ b/packages/cozy-flags/src/browser/flag.js @@ -1,5 +1,8 @@ /* global localStorage */ +import MicroEE from 'microee' +import React from 'react' + export const prefix = 'flag__' export const getKey = name => prefix + name @@ -26,6 +29,7 @@ class FlagStore { for (let flag of flags) { const val = localStorage.getItem(getKey(flag)) this.store[flag] = val ? JSON.parse(val) : val + this.emit('change') } } @@ -45,10 +49,23 @@ class FlagStore { localStorage.setItem(getKey(name), JSON.stringify(value)) } this.store[name] = value + this.emit('change') + } + + remove(name) { + delete this.store[name] + localStorage.removeItem(getKey(name)) + this.emit('change') } } +MicroEE.mixin(FlagStore) + const store = new FlagStore() + +/** + * Public API to use flags + */ const flag = function() { if (!window.localStorage) { return @@ -67,7 +84,7 @@ export const listFlags = () => { } export const resetFlags = () => { - listFlags().forEach(name => (store[name] = null)) + listFlags().forEach(name => store.remove(name)) } flag.store = store @@ -75,3 +92,30 @@ flag.list = listFlags flag.reset = resetFlags export default flag + +/** + * Connects a component to the flags. The wrapped component + * will be refreshed when a flag changes. + */ +flag.connect = Component => { + class Wrapped extends React.Component { + constructor(props) { + super(props) + this.handleChange = this.handleChange.bind(this) + } + componentWillMount() { + store.on('change', this.handleChange) + } + componentWillUnmount() { + store.removeListener('change', this.handleChange) + } + handleChange() { + this.forceUpdate() + } + render() { + return + } + } + Wrapped.displayName = 'flag_' + Component.displayName + return Wrapped +} diff --git a/packages/cozy-flags/src/tests.js b/packages/cozy-flags/src/tests.js index d5012c56ac..b64135ecbb 100644 --- a/packages/cozy-flags/src/tests.js +++ b/packages/cozy-flags/src/tests.js @@ -15,6 +15,18 @@ export default function testFlagAPI(flag) { flag('test', true) expect(flag('test')).toBe(true) }) + + if (flag.store) { + describe('observable', () => { + beforeEach(() => { + jest.spyOn(flag.store, 'emit') + }) + it('should emit events', () => { + flag('test', true) + expect(flag.store.emit).toHaveBeenCalled() + }) + }) + } }) describe('listFlags', () => { diff --git a/yarn.lock b/yarn.lock index 92bdca5e3a..3f9739d28a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8473,6 +8473,11 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= +microee@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/microee/-/microee-0.0.6.tgz#a12bdb0103681e8b126a9b071eba4c467c78fffe" + integrity sha1-oSvbAQNoHosSapsHHrpMRnx4//4= + micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -10527,7 +10532,6 @@ pouchdb-abstract-mapreduce@6.4.3: "pouchdb-adapter-cordova-sqlite@https://github.com/SnceGroup/pouchdb-adapter-cordova-sqlite.git#f3ee23009b70209c611435d57491aa77fb88802a": version "2.0.2" - uid f3ee23009b70209c611435d57491aa77fb88802a resolved "https://github.com/SnceGroup/pouchdb-adapter-cordova-sqlite.git#f3ee23009b70209c611435d57491aa77fb88802a" dependencies: pouchdb-adapter-websql-core "^6.1.1"