mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2025-12-06 02:30:47 -08:00
fix: circular dependency in main process
By looking at error messages in http://localhost:9000/
This commit is contained in:
parent
c02fb95809
commit
2f0e892dfb
8 changed files with 60 additions and 48 deletions
|
|
@ -87,13 +87,12 @@ cd TiddlyGit-Desktop
|
||||||
npm i
|
npm i
|
||||||
|
|
||||||
# Run development mode
|
# Run development mode
|
||||||
|
# You can see webpack error messages in http://localhost:9000/
|
||||||
npm run electron-dev
|
npm start
|
||||||
|
|
||||||
# Build for production
|
# Build for production
|
||||||
|
|
||||||
npm run dist
|
npm run package
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Publish
|
### Publish
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ import { autoUpdater } from 'electron-updater';
|
||||||
import unhandled from 'electron-unhandled';
|
import unhandled from 'electron-unhandled';
|
||||||
import { openNewGitHubIssue, debugInfo } from 'electron-util';
|
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 { ThemeChannel, MainChannel } from '@/constants/channels';
|
||||||
import { container } from '@services/container';
|
import { container } from '@services/container';
|
||||||
import { logger } from '@services/libs/log';
|
import { logger } from '@services/libs/log';
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ import isDev from 'electron-is-dev';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
|
||||||
import './listeners';
|
|
||||||
|
|
||||||
const isMac = process.platform === 'darwin';
|
const isMac = process.platform === 'darwin';
|
||||||
|
|
||||||
const sourcePath = path.resolve(__dirname, '..', '..');
|
const sourcePath = path.resolve(__dirname, '..', '..');
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@ import { ipcMain } from 'electron';
|
||||||
import { container } from '@services/container';
|
import { container } from '@services/container';
|
||||||
import type { IWindowService } from '@services/windows';
|
import type { IWindowService } from '@services/windows';
|
||||||
import { WindowNames } from '@services/windows/WindowProperties';
|
import { WindowNames } from '@services/windows/WindowProperties';
|
||||||
import { mainBindings } from './i18next-electron-fs-backend';
|
|
||||||
import serviceIdentifier from '@services/serviceIdentifier';
|
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 windows = container.get<IWindowService>(serviceIdentifier.Window);
|
||||||
const mainWindow = windows.get(WindowNames.main);
|
const mainWindow = windows.get(WindowNames.main);
|
||||||
if (mainWindow === undefined) {
|
if (mainWindow === undefined) {
|
||||||
throw new Error('Window is undefined in bindI18nListener()');
|
throw new Error('Window is undefined in bindI18nListener()');
|
||||||
}
|
}
|
||||||
|
const { mainBindings } = await import('./i18next-electron-fs-backend');
|
||||||
mainBindings(ipcMain, mainWindow);
|
mainBindings(ipcMain, mainWindow);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
46
src/services/libs/i18n/buildLanguageMenu.ts
Normal file
46
src/services/libs/i18n/buildLanguageMenu.ts
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,13 @@
|
||||||
/* eslint-disable unicorn/prevent-abbreviations */
|
/* eslint-disable unicorn/prevent-abbreviations */
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
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 { IWindowService } from '@services/windows';
|
||||||
import type { IPreferenceService } from '@services/preferences';
|
|
||||||
import type { IViewService } from '@services/view';
|
|
||||||
import serviceIdentifier from '@services/serviceIdentifier';
|
import serviceIdentifier from '@services/serviceIdentifier';
|
||||||
import { container } from '@services/container';
|
import { container } from '@services/container';
|
||||||
import { LOCALIZATION_FOLDER } from '@services/constants/paths';
|
import { LOCALIZATION_FOLDER } from '@services/constants/paths';
|
||||||
import { I18NChannels } from '@/constants/channels';
|
import { I18NChannels } from '@/constants/channels';
|
||||||
import i18n from '.';
|
|
||||||
|
|
||||||
export interface IReadFileRequest {
|
export interface IReadFileRequest {
|
||||||
filename: string;
|
filename: string;
|
||||||
|
|
@ -101,36 +98,3 @@ export const clearMainBindings = function (ipcMain: IpcMain): void {
|
||||||
ipcMain.removeAllListeners(I18NChannels.readFileRequest);
|
ipcMain.removeAllListeners(I18NChannels.readFileRequest);
|
||||||
ipcMain.removeAllListeners(I18NChannels.writeFileRequest);
|
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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ void i18next.use(Backend).init({
|
||||||
});
|
});
|
||||||
|
|
||||||
export async function initI18NAfterServiceReady(): Promise<void> {
|
export async function initI18NAfterServiceReady(): Promise<void> {
|
||||||
bindI18nListener();
|
await bindI18nListener();
|
||||||
await changeToDefaultLanguage(i18next);
|
await changeToDefaultLanguage(i18next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,11 @@ import { Menu, MenuItemConstructorOptions, shell } from 'electron';
|
||||||
import { debounce, take, drop } from 'lodash';
|
import { debounce, take, drop } from 'lodash';
|
||||||
import { injectable } from 'inversify';
|
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;
|
label?: (() => string) | string;
|
||||||
enabled?: (() => boolean) | boolean;
|
enabled?: (() => boolean) | boolean;
|
||||||
submenu?:
|
submenu?:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue