Skip to content

Commit

Permalink
Merge pull request #67 from Rajaniraiyn/webcontentsview
Browse files Browse the repository at this point in the history
Enhance main/zustandBridge to Support `WebContentsView` and `BrowserView` Alongside `BrowserWindow`
  • Loading branch information
goosewobbler authored Dec 6, 2024
2 parents b68f92d + 05826ac commit 44cc40c
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 11 deletions.
7 changes: 5 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ store = createStore<AppState>()(() => initialState);

#### Initialize Bridge in Main process

In the main process, the bridge needs your store and an array of BrowserWindow objects for your app, so for a single window application:
In the main process, the bridge needs your store and an array of window or view objects for your app. `BrowserWindow`, `BrowserView` and `WebContentsView` objects are supported.

So, for a single window application:

```ts
import { mainZustandBridge } from 'zutron/main';

// create mainWindow
const mainWindow = new BrowserWindow(windowConfig);

const { unsubscribe } = mainZustandBridge(store, [mainWindow]);

Expand All @@ -51,7 +54,7 @@ contextBridge.exposeInMainWorld('zutron', handlers);

#### Create hook in Renderer process

Finally, in the renderer process you will need to create the useStore hook:
Finally, in the renderer process you will need to create the `useStore` hook:

`/renderer/hooks/useStore.ts`

Expand Down
6 changes: 3 additions & 3 deletions packages/zutron/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { type BrowserWindow, ipcMain, type IpcMainEvent } from 'electron';
import { type BrowserWindow, type WebContentsView, type BrowserView, ipcMain, type IpcMainEvent } from 'electron';
import type { StoreApi } from 'zustand';

import type { Action, AnyState, Handler, MainZustandBridgeOpts, Thunk } from './index.js';

export type MainZustandBridge = <State extends AnyState, Store extends StoreApi<State>>(
store: Store,
windows: BrowserWindow[],
windows: (BrowserWindow | WebContentsView | BrowserView)[],
options?: MainZustandBridgeOpts<State>,
) => { unsubscribe: () => void };

Expand Down Expand Up @@ -55,7 +55,7 @@ export const mainZustandBridge: MainZustandBridge = (store, windows, options) =>
const dispatch = createDispatch(store, options);
ipcMain.on('subscribe', async (state: unknown) => {
for (const window of windows) {
if (window?.isDestroyed()) {
if (window.webContents.isDestroyed()) {
break;
}
window?.webContents?.send('subscribe', sanitizeState(state as AnyState));
Expand Down
12 changes: 6 additions & 6 deletions packages/zutron/test/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,15 @@ describe('createDispatch', () => {
describe('mainZustandBridge', () => {
let options: { handlers?: Record<string, Mock> };
let mockStore: Record<string, Mock>;
let mockWindows: Record<string, Mock | { send: Mock }>[];
let mockWindows: Record<string, Mock | { send: Mock; isDestroyed: Mock }>[];

beforeEach(() => {
mockStore = {
getState: vi.fn(),
setState: vi.fn(),
subscribe: vi.fn(),
};
mockWindows = [{ isDestroyed: vi.fn().mockReturnValue(false), webContents: { send: vi.fn() } }];
mockWindows = [{ webContents: { send: vi.fn(), isDestroyed: vi.fn().mockReturnValue(false) } }];
options = {};
});

Expand Down Expand Up @@ -174,8 +174,8 @@ describe('mainZustandBridge', () => {

it('should handle multiple windows', async () => {
mockWindows = [
{ isDestroyed: vi.fn().mockReturnValue(false), webContents: { send: vi.fn() } },
{ isDestroyed: vi.fn().mockReturnValue(false), webContents: { send: vi.fn() } },
{ webContents: { send: vi.fn(), isDestroyed: vi.fn().mockReturnValue(false) } },
{ webContents: { send: vi.fn(), isDestroyed: vi.fn().mockReturnValue(false) } },
];
const browserWindows = mockWindows as unknown as Electron.BrowserWindow[];

Expand All @@ -191,8 +191,8 @@ describe('mainZustandBridge', () => {

it('should handle destroyed windows', async () => {
mockWindows = [
{ isDestroyed: vi.fn().mockReturnValue(false), webContents: { send: vi.fn() } },
{ isDestroyed: vi.fn().mockReturnValue(true), webContents: { send: vi.fn() } },
{ webContents: { send: vi.fn(), isDestroyed: vi.fn().mockReturnValue(false) } },
{ webContents: { send: vi.fn(), isDestroyed: vi.fn().mockReturnValue(true) } },
];
const browserWindows = mockWindows as unknown as Electron.BrowserWindow[];

Expand Down

0 comments on commit 44cc40c

Please sign in to comment.