/* * Copyright (C) 2021-2022 Kristóf Marussy * * This file is part of Sophie. * * Sophie is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * SPDX-License-Identifier: AGPL-3.0-only */ import type { IJsonPatch } from 'mobx-state-tree'; import { Action, action, sharedStore, SharedStoreListener, SophieRenderer, } from '@sophie/shared'; import { RendererToMainIpcService } from '../services/RendererToMainIpcService'; class SophieRendererImpl implements SophieRenderer { readonly #ipcService: RendererToMainIpcService; #listener: SharedStoreListener | null = null; constructor(ipcService: RendererToMainIpcService) { this.#ipcService = ipcService; ipcService.onSharedStorePatch((patch) => { // `mobx-state-tree` will validate the patch, so we can safely cast here. this.#listener?.onPatch(patch as IJsonPatch); }); } onSharedStoreChange(listener: SharedStoreListener): void { this.#ipcService.getSharedStoreSnapshot().then((snapshot) => { if (sharedStore.is(snapshot)) { listener.onSnapshot(snapshot); this.#listener = listener; } else { console.error('Got invalid initial shared store snapshot', snapshot); } }).catch((err) => { console.error('Failed set initial shared store snapshot', err); }); } dispatchAction(actionToDispatch: Action): void { const parsedAction = action.safeParse(actionToDispatch); if (parsedAction.success) { this.#ipcService.dispatchAction(parsedAction.data); } else { console.error('Trying to dispatch invalid action', actionToDispatch, parsedAction.error); } } } export function createSophieRenderer(ipcService: RendererToMainIpcService): SophieRenderer { const impl = new SophieRendererImpl(ipcService); return { onSharedStoreChange: impl.onSharedStoreChange.bind(impl), dispatchAction: impl.dispatchAction.bind(impl), }; }