Skip to content

Commit

Permalink
app: Apply IoC to store objects
Browse files Browse the repository at this point in the history
  • Loading branch information
evanpurkhiser committed Jan 12, 2021
1 parent c14781b commit 6fab96c
Show file tree
Hide file tree
Showing 34 changed files with 479 additions and 326 deletions.
4 changes: 2 additions & 2 deletions src/main/configMigrations.ts
@@ -1,13 +1,13 @@
import {set} from 'mobx';

import store from 'src/shared/store';
import {AppStore} from 'src/shared/store';

/**
* There may be some situations where we have to implement migrations of the
* users configuration as they upgrade versiosns. These migrations will live
* here.
*/
export function runConfigMigrations() {
export function runConfigMigrations(store: AppStore) {
/**
* 11-19-20
*
Expand Down
4 changes: 2 additions & 2 deletions src/main/debugEvents.ts
Expand Up @@ -10,7 +10,7 @@ import {
ProlinkNetwork,
} from 'prolink-connect';

import store from 'src/shared/store';
import {AppStore} from 'src/shared/store';

type Events =
| {
Expand Down Expand Up @@ -150,7 +150,7 @@ class DebugEventsService {
* to Sentry. The service will be activated and deactivated reactively to the
* reportDebugEvents store configuration.
*/
export function registerDebuggingEventsService(network: ProlinkNetwork) {
export function registerDebuggingEventsService(store: AppStore, network: ProlinkNetwork) {
if (!network.isConnected()) {
return;
}
Expand Down
40 changes: 22 additions & 18 deletions src/main/main.ts
@@ -1,5 +1,4 @@
import 'regenerator-runtime/runtime';
import 'main/menu';

import {app, BrowserWindow, nativeTheme, shell} from 'electron';
import isDev from 'electron-is-dev';
Expand All @@ -12,21 +11,29 @@ import * as url from 'url';
import {startOverlayServer} from 'main/overlayServer';
import {runConfigMigrations} from 'src/main/configMigrations';
import {registerDebuggingEventsService} from 'src/main/debugEvents';
import {setupMenu} from 'src/main/menu';
import {userInfo} from 'src/shared/sentry/main';
import store from 'src/shared/store';
import {AppStore, createStore} from 'src/shared/store';
import {loadMainConfig, observeStore, registerMainIpc} from 'src/shared/store/ipc';
import connectNetworkStore from 'src/shared/store/network';
import theme from 'src/theme';

const mainStore = createStore();

export const withMainStore = (cb: (store: AppStore) => void) => cb(mainStore);

// Update the store with user details ASAP
(async () => set(store, {user: await userInfo}))();
(async () => set(mainStore, {user: await userInfo}))();

// Intialize the store for the main thread immedaitely.
store.isInitalized = true;
mainStore.isInitalized = true;

// see https://www.electronjs.org/docs/api/app#appallowrendererprocessreuse
app.allowRendererProcessReuse = true;

// Setup application menu
setupMenu(mainStore);

let win: BrowserWindow | null;

const createWindow = () => {
Expand Down Expand Up @@ -70,36 +77,33 @@ const createWindow = () => {
};

app.on('ready', async () => {
await loadMainConfig();
await loadMainConfig(mainStore);
createWindow();

registerMainIpc();
runConfigMigrations();
observeStore();

// Setup some additional overlay functionality
require('src/overlay/overlays/nowPlaying/main');
registerMainIpc(mainStore);
runConfigMigrations(mainStore);
observeStore({target: mainStore});

let network: ProlinkNetwork;

// Open connections to the network
try {
network = await bringOnline();
store.networkState = network.state;
mainStore.networkState = network.state;
} catch (e) {
if (e.errno !== 'EADDRINUSE') {
throw e;
}

// Something is using the status port... Most likely rekordbox
store.networkState = NetworkState.Failed;
mainStore.networkState = NetworkState.Failed;
return;
}

// Attempt to autoconfigure from other devices on the network
await network.autoconfigFromPeers();
network.connect();
store.networkState = network.state;
mainStore.networkState = network.state;

// Start overlay http / websocket server.
//
Expand All @@ -113,10 +117,10 @@ app.on('ready', async () => {
//
// As thus THIS LINE MUST BE PLACED AFTER THE NETWORK IS BROUGHT ONLINE.
//
await startOverlayServer();
await startOverlayServer(mainStore);

connectNetworkStore(network);
registerDebuggingEventsService(network);
connectNetworkStore(mainStore, network);
registerDebuggingEventsService(mainStore, network);
});

app.on('window-all-closed', () => {
Expand All @@ -130,7 +134,7 @@ app.on('activate', () => {
});

reaction(
() => store.config.theme,
() => mainStore.config.theme,
schema => {
const bg = nativeTheme.shouldUseDarkColors
? theme.dark.background
Expand Down
158 changes: 80 additions & 78 deletions src/main/menu.ts
@@ -1,85 +1,87 @@
import {app, Menu, shell} from 'electron';

import store from 'src/shared/store';
import {AppStore} from 'src/shared/store';

const isMac = process.platform === 'darwin';
export function setupMenu(store: AppStore) {
const isMac = process.platform === 'darwin';

const template: Electron.MenuItemConstructorOptions[] = [
...((isMac
? [
const template: Electron.MenuItemConstructorOptions[] = [
...((isMac
? [
{
label: app.name,
submenu: [
{role: 'about'},
{type: 'separator'},
{role: 'services'},
{type: 'separator'},
{role: 'hide'},
{role: 'hideothers'},
{role: 'unhide'},
{type: 'separator'},
{role: 'quit'},
],
},
]
: []) as Electron.MenuItemConstructorOptions[]),
{
label: 'Edit',
submenu: [
{role: 'undo'},
{role: 'redo'},
{type: 'separator'},
{role: 'cut'},
{role: 'copy'},
{role: 'paste'},
{role: 'delete'},
{type: 'separator'},
{role: 'selectAll'},
],
},
{
label: 'View',
submenu: [
{role: 'reload'},
{role: 'forceReload'},
{role: 'togglefullscreen'},
{
label: app.name,
submenu: [
{role: 'about'},
{type: 'separator'},
{role: 'services'},
{type: 'separator'},
{role: 'hide'},
{role: 'hideothers'},
{role: 'unhide'},
{type: 'separator'},
{role: 'quit'},
],
accelerator: 'cmd + option + s',
label: 'Toggle Sidebar',
click: () => store.config.toggleSidebar(),
},
]
: []) as Electron.MenuItemConstructorOptions[]),
{
label: 'Edit',
submenu: [
{role: 'undo'},
{role: 'redo'},
{type: 'separator'},
{role: 'cut'},
{role: 'copy'},
{role: 'paste'},
{role: 'delete'},
{type: 'separator'},
{role: 'selectAll'},
],
},
{
label: 'View',
submenu: [
{role: 'reload'},
{role: 'forceReload'},
{role: 'togglefullscreen'},
{
accelerator: 'cmd + option + s',
label: 'Toggle Sidebar',
click: () => store.config.toggleSidebar(),
},
{
visible: false,
accelerator: 'cmd + l',
label: 'Toggle UI Theme',
click: () => store.config.toggleTheme(),
},
],
},
{
label: 'Window',
submenu: [
{role: 'minimize'},
{role: 'zoom'},
...((isMac
? [{type: 'separator'}, {role: 'front'}, {type: 'separator'}, {role: 'window'}]
: [{role: 'close'}]) as Electron.MenuItemConstructorOptions[]),
],
},
{
role: 'help',
submenu: [
{
label: 'Learn More',
click: () => shell.openExternal('https://prolink.tools/'),
},
{
label: 'User Manual',
click: () => shell.openExternal('https://prolink.tools/manual'),
},
],
},
];
{
visible: false,
accelerator: 'cmd + l',
label: 'Toggle UI Theme',
click: () => store.config.toggleTheme(),
},
],
},
{
label: 'Window',
submenu: [
{role: 'minimize'},
{role: 'zoom'},
...((isMac
? [{type: 'separator'}, {role: 'front'}, {type: 'separator'}, {role: 'window'}]
: [{role: 'close'}]) as Electron.MenuItemConstructorOptions[]),
],
},
{
role: 'help',
submenu: [
{
label: 'Learn More',
click: () => shell.openExternal('https://prolink.tools/'),
},
{
label: 'User Manual',
click: () => shell.openExternal('https://prolink.tools/manual'),
},
],
},
];

const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
}
5 changes: 3 additions & 2 deletions src/main/overlayServer.ts
Expand Up @@ -9,17 +9,18 @@ import http from 'http';
import * as path from 'path';

import {WEBSERVER_PORT} from 'src/shared/constants';
import {AppStore} from 'src/shared/store';
import {registerMainWebsocket} from 'src/shared/store/ipc';

const OVERLAY_ROOT = path.resolve(__dirname, 'overlay');

export async function startOverlayServer() {
export async function startOverlayServer(store: AppStore) {
const app = connect();
const httpServer = http.createServer(app);

// Setup socketio server
const wss = new Server(httpServer, {serveClient: false});
registerMainWebsocket(wss);
registerMainWebsocket(store, wss);

const proxy = httpProxy.createProxy();
const fileServer = new httpStatic.Server(OVERLAY_ROOT);
Expand Down
11 changes: 7 additions & 4 deletions src/overlay/Router.tsx
Expand Up @@ -4,15 +4,18 @@ import {Global} from '@emotion/react';
import {observer} from 'mobx-react';

import globalCss from 'src/shared/globalCss';
import store from 'src/shared/store';
import {AppStore} from 'src/shared/store';
import withStore from 'src/utils/withStore';

import NotFound from './components/NotFound';
import {ensureNoOBSDefaultStyles} from './utils/obsFixes';
import {registeredOverlays} from '.';

type Props = RouteComponentProps<{overlayKey: string}>;
type Props = RouteComponentProps<{overlayKey: string}> & {
store: AppStore;
};

const MapOverlay: React.FC<Props> = observer(props => {
const MapOverlay: React.FC<Props> = observer(({store, ...props}) => {
if (!store.isInitalized) {
return null;
}
Expand All @@ -34,7 +37,7 @@ const Router = () => {
return (
<BrowserRouter>
<Global styles={globalCss} />
<Route path="/:overlayKey" component={MapOverlay} />
<Route path="/:overlayKey" component={withStore(MapOverlay)} />
</BrowserRouter>
);
};
Expand Down
18 changes: 13 additions & 5 deletions src/overlay/app.tsx
Expand Up @@ -6,13 +6,21 @@ import * as ReactDOM from 'react-dom';
import {io} from 'socket.io-client';

import Router from 'overlay/Router';
import {registerClientWebsocket} from 'src/shared/store/ipc';
import {createStore} from 'src/shared/store';
import {StoreContext} from 'src/shared/store/context';
import {registerWebsocketListener} from 'src/shared/store/ipc';

const overlaysStore = createStore();

// Create main element
const mainElement = document.createElement('div');
document.body.appendChild(mainElement);

// Render components
ReactDOM.render(<Router />, mainElement);
const main = (
<StoreContext.Provider value={overlaysStore}>
<Router />
</StoreContext.Provider>
);

ReactDOM.render(main, mainElement);

registerClientWebsocket(io());
registerWebsocketListener(overlaysStore, io());

0 comments on commit 6fab96c

Please sign in to comment.