Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/constants/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Message type for store action events from
// background to Proxy Stores
export const ACTION_TYPE = 'chromex.action';

// Message type used for dispatch events
// from the Proxy Stores to background
export const DISPATCH_TYPE = 'chromex.dispatch';
Expand Down
11 changes: 10 additions & 1 deletion src/store/Store.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import assignIn from 'lodash.assignin';

import {
ACTION_TYPE,
DISPATCH_TYPE,
STATE_TYPE,
PATCH_STATE_TYPE,
Expand Down Expand Up @@ -62,6 +63,10 @@ class Store {
// Don't use shouldDeserialize here, since no one else should be using this port
this.serializedPortListener(message => {
switch (message.type) {
case ACTION_TYPE:
this.dispatch({ ...message.payload, fromBackground: true });
break;

case STATE_TYPE:
this.replaceState(message.payload);

Expand Down Expand Up @@ -148,7 +153,11 @@ class Store {
* @param {object} data The action data to dispatch
* @return {Promise} Promise that will resolve/reject based on the action response from the background
*/
dispatch(data) {
dispatch({ fromBackground, ...data } = {}) {
if (Boolean(fromBackground)) {
// don't need to message this dispatch back to the background because it originated there
return Promise.resolve(true)
}
return new Promise((resolve, reject) => {
this.serializedMessageSender(
this.extensionId,
Expand Down
39 changes: 37 additions & 2 deletions src/wrap-store/wrapStore.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import applyMiddleware from "../store/applyMiddleware";
import {
ACTION_TYPE,
DISPATCH_TYPE,
STATE_TYPE,
PATCH_STATE_TYPE,
Expand Down Expand Up @@ -90,6 +92,21 @@ export default (store, {
}
};

let actionListeners = [];
const subscribeToActions = (fn) => {
actionListeners.push(fn);
// return unsubscribe function
return () => {
actionListeners = actionListeners.filter((f) => f !== fn);
};
};
const postActionToListeners = ({ _sender, ...action }) => {
// actions with _sender came down from remote proxy stores so don't need to send them back
if (!Boolean(_sender)) {
actionListeners.forEach((fn) => fn(action));
}
};

/**
* Setup for state updates
*/
Expand All @@ -116,11 +133,23 @@ export default (store, {
}
};

// Send event message down connected port on every redux action
const unsubscribeActionsSubscription = subscribeToActions((action) => {
serializedMessagePoster({
type: ACTION_TYPE,
payload: action,
});
});
// Send patched state down connected port on every redux store state change
const unsubscribe = store.subscribe(patchState);
const unsubscribeStoreSubscription = store.subscribe(patchState);

const unsubscribeAll = () => {
unsubscribeActionsSubscription();
unsubscribeStoreSubscription();
};

// when the port disconnects, unsubscribe the sendState listener
port.onDisconnect.addListener(unsubscribe);
port.onDisconnect.addListener(unsubscribeAll);

// Send store's initial state through port
serializedMessagePoster({
Expand Down Expand Up @@ -178,4 +207,10 @@ export default (store, {
// TODO: Find use case for this. Ommiting until then.
// browserAPI.runtime.sendMessage(null, {action: 'storeReady'});

const postActionMiddleware = (_) => (next) => (action) => {
postActionToListeners(action);
return next(action);
};

applyMiddleware(store, postActionMiddleware);
};