fix: circular dependency in main process

By looking at error messages in http://localhost:9000/
This commit is contained in:
tiddlygit-test 2021-01-20 23:45:10 +08:00
parent c02fb95809
commit 2f0e892dfb
8 changed files with 60 additions and 48 deletions

View file

@ -87,13 +87,12 @@ cd TiddlyGit-Desktop
npm i
# Run development mode
npm run electron-dev
# You can see webpack error messages in http://localhost:9000/
npm start
# Build for production
npm run dist
npm run package
```
### Publish

View file

@ -8,7 +8,8 @@ import { autoUpdater } from 'electron-updater';
import unhandled from 'electron-unhandled';
import { openNewGitHubIssue, debugInfo } from 'electron-util';
import { clearMainBindings, buildLanguageMenu } from '@services/libs/i18n/i18next-electron-fs-backend';
import { clearMainBindings } from '@services/libs/i18n/i18next-electron-fs-backend';
import { buildLanguageMenu } from '@services/libs/i18n/buildLanguageMenu';
import { ThemeChannel, MainChannel } from '@/constants/channels';
import { container } from '@services/container';
import { logger } from '@services/libs/log';

View file

@ -2,8 +2,6 @@ import isDev from 'electron-is-dev';
import path from 'path';
import os from 'os';
import './listeners';
const isMac = process.platform === 'darwin';
const sourcePath = path.resolve(__dirname, '..', '..');

View file

@ -3,14 +3,14 @@ import { ipcMain } from 'electron';
import { container } from '@services/container';
import type { IWindowService } from '@services/windows';
import { WindowNames } from '@services/windows/WindowProperties';
import { mainBindings } from './i18next-electron-fs-backend';
import serviceIdentifier from '@services/serviceIdentifier';
export default function bindI18nListener(): void {
export default async function bindI18nListener(): Promise<void> {
const windows = container.get<IWindowService>(serviceIdentifier.Window);
const mainWindow = windows.get(WindowNames.main);
if (mainWindow === undefined) {
throw new Error('Window is undefined in bindI18nListener()');
}
const { mainBindings } = await import('./i18next-electron-fs-backend');
mainBindings(ipcMain, mainWindow);
}

View file

@ -0,0 +1,46 @@
import fs from 'fs-extra';
import path from 'path';
import type { IWindowService } from '@services/windows';
import serviceIdentifier from '@services/serviceIdentifier';
import { container } from '@services/container';
import { LOCALIZATION_FOLDER } from '@services/constants/paths';
import { I18NChannels } from '@/constants/channels';
import type { IPreferenceService } from '@services/preferences';
import type { IViewService } from '@services/view';
import type { IMenuService, DeferredMenuItemConstructorOptions } from '@services/menu';
const whitelistMap = JSON.parse(fs.readFileSync(path.join(LOCALIZATION_FOLDER, 'whitelist.json'), 'utf-8')) as Record<string, string>;
const whiteListedLanguages = Object.keys(whitelistMap);
/**
* Register languages into language menu, call this function after container init
*/
export function buildLanguageMenu(): void {
const preferenceService = container.get<IPreferenceService>(serviceIdentifier.Preference);
const windowService = container.get<IWindowService>(serviceIdentifier.Window);
const viewService = container.get<IViewService>(serviceIdentifier.View);
const menuService = container.get<IMenuService>(serviceIdentifier.MenuService);
const subMenu: DeferredMenuItemConstructorOptions[] = [];
for (const language of whiteListedLanguages) {
subMenu.push({
label: whitelistMap[language],
click: async () => {
const i18n = (await import('./')).default;
await Promise.all([preferenceService.set('language', language), i18n.changeLanguage(language)]);
viewService.forEachView((view) => {
view.webContents.send(I18NChannels.changeLanguageRequest, {
lng: language,
});
});
windowService.sendToAllWindows(I18NChannels.changeLanguageRequest, {
lng: language,
});
},
});
}
menuService.insertMenu('Language', subMenu);
}

View file

@ -1,16 +1,13 @@
/* eslint-disable unicorn/prevent-abbreviations */
import fs from 'fs-extra';
import path from 'path';
import { IpcRenderer, IpcMain, BrowserWindow, IpcMainInvokeEvent, IpcRendererEvent, MenuItemConstructorOptions } from 'electron';
import { IpcRenderer, IpcMain, BrowserWindow, IpcMainInvokeEvent, IpcRendererEvent } from 'electron';
import type { IWindowService } from '@services/windows';
import type { IPreferenceService } from '@services/preferences';
import type { IViewService } from '@services/view';
import serviceIdentifier from '@services/serviceIdentifier';
import { container } from '@services/container';
import { LOCALIZATION_FOLDER } from '@services/constants/paths';
import { I18NChannels } from '@/constants/channels';
import i18n from '.';
export interface IReadFileRequest {
filename: string;
@ -101,36 +98,3 @@ export const clearMainBindings = function (ipcMain: IpcMain): void {
ipcMain.removeAllListeners(I18NChannels.readFileRequest);
ipcMain.removeAllListeners(I18NChannels.writeFileRequest);
};
const whitelistMap = JSON.parse(fs.readFileSync(path.join(LOCALIZATION_FOLDER, 'whitelist.json'), 'utf-8')) as Record<string, string>;
const whiteListedLanguages = Object.keys(whitelistMap);
/**
* Register languages into language menu, call this function after container init
*/
export function buildLanguageMenu(): void {
const preferenceService = container.get<IPreferenceService>(serviceIdentifier.Preference);
const windowService = container.get<IWindowService>(serviceIdentifier.Window);
const viewService = container.get<IViewService>(serviceIdentifier.View);
const menuService = container.get<IMenuServiceService>(serviceIdentifier.MenuService);
const subMenu: MenuItemConstructorOptions[] = [];
for (const language of whiteListedLanguages) {
subMenu.push({
label: whitelistMap[language],
click: async () => {
await Promise.all([preferenceService.set('language', language), i18n.changeLanguage(language)]);
viewService.forEachView((view) => {
view.webContents.send(I18NChannels.changeLanguageRequest, {
lng: language,
});
});
windowService.sendToAllWindows(I18NChannels.changeLanguageRequest, {
lng: language,
});
},
});
}
menuService.insertMenu('Language', subMenu);
}

View file

@ -23,7 +23,7 @@ void i18next.use(Backend).init({
});
export async function initI18NAfterServiceReady(): Promise<void> {
bindI18nListener();
await bindI18nListener();
await changeToDefaultLanguage(i18next);
}

View file

@ -2,7 +2,11 @@ import { Menu, MenuItemConstructorOptions, shell } from 'electron';
import { debounce, take, drop } from 'lodash';
import { injectable } from 'inversify';
interface DeferredMenuItemConstructorOptions extends Omit<MenuItemConstructorOptions, 'label' | 'enabled' | 'submenu'> {
/**
* MenuItemConstructorOptions that allows properties like "label", "enabled", "submenu" to be () => xxx
* So these value can be determined at every build time (menu will be rebuilt every time the preferences change)
*/
export interface DeferredMenuItemConstructorOptions extends Omit<MenuItemConstructorOptions, 'label' | 'enabled' | 'submenu'> {
label?: (() => string) | string;
enabled?: (() => boolean) | boolean;
submenu?: