meta: integrate vite, remove webpack
This commit is contained in:
parent
dc68771232
commit
9512210624
|
@ -82,7 +82,6 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"import/no-default-export": "warn",
|
||||
"import/first": "warn",
|
||||
"import/order": [
|
||||
"warn",
|
||||
|
@ -98,9 +97,11 @@
|
|||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["src/**/*.*"],
|
||||
"files": ["src/**/*"],
|
||||
"rules": {
|
||||
"no-console": "warn"
|
||||
"no-console": "warn",
|
||||
|
||||
"import/no-default-export": "warn"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -222,7 +223,7 @@
|
|||
"processor": "svelte3/svelte3"
|
||||
},
|
||||
{
|
||||
"files": ["src/shared/types/**/*"],
|
||||
"files": ["src/shared/**/*"],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-magic-numbers": "off"
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ node_modules
|
|||
/src/**/*.js
|
||||
/src/**/*.js.map
|
||||
/frontend
|
||||
/index.html
|
||||
|
||||
# created by testing
|
||||
/test-paths
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
!*.md
|
||||
!*.ts
|
||||
!*.js
|
||||
!*.mjs
|
||||
!*.drawio
|
||||
|
||||
# but ignore stuff from .gitignore
|
||||
|
|
|
@ -186,17 +186,20 @@ This also means potentially updating:
|
|||
|
||||
- the `node` version key under `engines` in [package.json](package.json)
|
||||
- the `@types/node` package
|
||||
- the electron version in the `target` field of the [webpack config](scripts/webpack.config.js)
|
||||
- the chrome version in the `build.target` field of the [vite config](scripts/vite.config.mjs)
|
||||
- the `compilerOptions.target` fields of the [main](tsconfig.json) and [renderer](tsconfig.renderer.json) typescript configuration files
|
||||
- the `parserOptions.ecmaVersion` field in the [ESLint configuration](.eslintrc.json)
|
||||
|
||||
Run `npm run electron-version` to find out which specific version is currently running.
|
||||
|
||||
Also might be worth checking out https://github.com/electron/electron/issues/21457 if the project can be converted to transpile to ES Modules.
|
||||
|
||||
### Frontend
|
||||
|
||||
#### Translation
|
||||
|
||||
With the help of [intl-messageformat](https://www.npmjs.com/package/intl-messageformat) frontend message can be defined in the [ICU Message Format](https://unicode-org.github.io/icu/userguide/format_parse/messages/). The corresponding code can be found [here](src/shared/services/translation/t.ts). I don't think a language other than English will be necessary, but the formatting features are nice anyway.
|
||||
With the help of [intl-messageformat](https://www.npmjs.com/package/intl-messageformat) frontend messages can be defined in the [ICU Message Format](https://unicode-org.github.io/icu/userguide/format_parse/messages/). The corresponding code can be found [here](src/renderer/services/translation/t.ts). I don't think a language other than English will be necessary, but the formatting features are nice anyway.
|
||||
This code is duplicated in [src/main/modules/translation/t.ts](src/main/modules/translation/t.ts), because one is run in the browser, the other in node and it led to complications with different tsconfig options.
|
||||
|
||||
## Design
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
|
@ -10,6 +10,7 @@
|
|||
"email": "xymorot@mailbox.org"
|
||||
},
|
||||
"main": "src/main.js",
|
||||
"module": "src/renderer.js",
|
||||
"engines": {
|
||||
"node": "14",
|
||||
"npm": "7"
|
||||
|
@ -24,14 +25,18 @@
|
|||
"typeorm:migrate": "npm run typeorm:migrate:library && npm run typeorm:migrate:store",
|
||||
"typeorm:migrate:library": "typeorm migration:run -c library",
|
||||
"typeorm:migrate:store": "typeorm migration:run -c store",
|
||||
"build:webpack": "webpack --config scripts/webpack.config.js",
|
||||
"dev:webpack": "webpack --config scripts/webpack.config.js --mode development -w",
|
||||
"build:frontend:typescript": "tsc --build tsconfig.renderer.json",
|
||||
"dev:frontend:typescript": "tsc --build tsconfig.renderer.json -w --pretty --preserveWatchOutput",
|
||||
"build:frontend:bundle": "vite build -c scripts/vite.config.mjs",
|
||||
"dev:frontend:bundle": "vite -c scripts/vite.config.mjs",
|
||||
"build:frontend": "npm run build:frontend:typescript && npm run build:frontend:bundle",
|
||||
"dev:frontend": "concurrently -c blue,red -n tsc,bundle \"npm run dev:frontend:typescript\" \"npm run dev:frontend:bundle\"",
|
||||
"build:index": "node scripts/buildfile.js",
|
||||
"dev:index": "node scripts/buildfile.js --watch --dev",
|
||||
"build:ts": "tsc",
|
||||
"dev:ts": "tsc -w --pretty --preserveWatchOutput",
|
||||
"build": "concurrently -c green,yellow,cyan -n webpack,index,typescript \"npm run build:webpack\" \"npm run build:index\" \"npm run build:ts\"",
|
||||
"dev": "concurrently -c green,yellow,cyan -n webpack,index,typescript \"npm run dev:webpack\" \"npm run dev:index\" \"npm run dev:ts\"",
|
||||
"build:backend": "tsc --build tsconfig.json",
|
||||
"dev:backend": "tsc --build tsconfig.json -w --pretty --preserveWatchOutput",
|
||||
"build": "concurrently -c green,yellow,cyan -n frontend,index,backend \"npm run build:frontend\" \"npm run build:index\" \"npm run build:backend\"",
|
||||
"dev": "concurrently -c green,yellow,cyan -n frontend,index,backend \"npm run dev:frontend\" \"npm run dev:index\" \"npm run dev:backend\"",
|
||||
"test:fast": "electron-mocha --config .mocharc.json --grep \"@slow\" --invert",
|
||||
"test": "electron-mocha --config .mocharc.json",
|
||||
"coverage": "nyc npm run test",
|
||||
|
@ -61,6 +66,7 @@
|
|||
"@electron-forge/cli": "^6.0.0-beta.55",
|
||||
"@electron-forge/maker-squirrel": "^6.0.0-beta.55",
|
||||
"@prettier/plugin-xml": "^0.13.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.12",
|
||||
"@types/better-sqlite3": "^5.4.1",
|
||||
"@types/chai": "^4.2.18",
|
||||
"@types/chai-fs": "^2.0.2",
|
||||
|
@ -72,7 +78,6 @@
|
|||
"@types/node": "^14.17.0",
|
||||
"@types/sinon": "^10.0.0",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@types/webpack": "^5.28.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.24.0",
|
||||
"@typescript-eslint/parser": "^4.24.0",
|
||||
"chai": "^4.3.4",
|
||||
|
@ -100,11 +105,8 @@
|
|||
"prettier-plugin-svelte": "^2.3.0",
|
||||
"sinon": "^11.1.1",
|
||||
"svelte": "^3.38.2",
|
||||
"svelte-loader": "^3.1.1",
|
||||
"ts-loader": "^9.2.0",
|
||||
"typescript": "^4.2.4",
|
||||
"webpack": "^5.37.1",
|
||||
"webpack-cli": "^4.7.0"
|
||||
"vite": "^2.4.1"
|
||||
},
|
||||
"repository": "https://git.fuwafuwa.moe/Xymorot/RenaiApp",
|
||||
"bugs": "https://git.fuwafuwa.moe/Xymorot/RenaiApp/issues",
|
||||
|
|
|
@ -4,15 +4,14 @@ const { watch } = require('chokidar');
|
|||
const { debounce } = require('lodash');
|
||||
const minimist = require('minimist');
|
||||
const templating = require('../templates');
|
||||
const webpackConfig = require('./webpack.config');
|
||||
|
||||
/** @var {Object} argv */
|
||||
const argv = minimist(process.argv);
|
||||
|
||||
function buildIndexHtml() {
|
||||
const html = templating.compile(!!argv.dev);
|
||||
const html = templating.compile();
|
||||
|
||||
fs.writeFileSync(path.resolve(webpackConfig.output.path, 'index.html'), html);
|
||||
fs.writeFileSync(path.resolve('index.html'), html);
|
||||
console.log('compiled index.html');
|
||||
}
|
||||
|
||||
|
@ -21,7 +20,7 @@ const debouncedBuildIndexHtml = debounce(buildIndexHtml, 100, { leading: true, t
|
|||
function build() {
|
||||
if (argv.watch) {
|
||||
const templatesWatcher = watch('./templates/**/*');
|
||||
templatesWatcher.on('all', debouncedBuildIndexHtml);
|
||||
templatesWatcher.on('all', () => debouncedBuildIndexHtml());
|
||||
} else {
|
||||
buildIndexHtml();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ const ignoreList = [
|
|||
/^\/\.idea($|\/)/,
|
||||
/^\/\.vscode($|\/)/,
|
||||
|
||||
/^\/\.husky($|\/)/,
|
||||
/^\/\.nyc_output($|\/)/,
|
||||
/^\/declarations($|\/)/,
|
||||
/^\/templates($|\/)/,
|
||||
|
@ -21,18 +22,20 @@ const ignoreList = [
|
|||
/^\/\.nycrc\.yml/,
|
||||
/^\/\.prettierrc\.yml/,
|
||||
/^\/CONTRIBUTING\.md/,
|
||||
/^\/index\.html/,
|
||||
/^\/ormconfig\.yml/,
|
||||
/^\/package-lock\.json/,
|
||||
/^\/tsconfig\.json/,
|
||||
/^\/tsconfig\.renderer\.json/,
|
||||
|
||||
/^\/node_modules\/\.cache($|\/)/,
|
||||
/^\/node_modules\/\.vite($|\/)/,
|
||||
// test and mock files:
|
||||
/^.*\.(spec|mock)\.(ts|js(\.map)?)/,
|
||||
/^\/src\/.*\/test\/.*$/,
|
||||
// original typescript source and generated source map files:
|
||||
// original source and generated source map files:
|
||||
/^\/src\/.*\.(ts|js\.map)/,
|
||||
/^\/src\/.*\.eslintrc\.json/,
|
||||
/^\/src\/(renderer($|\/)|renderer\.js)/,
|
||||
];
|
||||
|
||||
const name = packageJson.productName;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* @type {import('rollup').RollupOptions}
|
||||
*/
|
||||
const options = {};
|
||||
|
||||
export default options;
|
|
@ -0,0 +1,17 @@
|
|||
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
||||
import rollupOptions from './rollup.config.mjs';
|
||||
|
||||
/**
|
||||
* @type {import('vite').UserConfig}
|
||||
*/
|
||||
const config = {
|
||||
plugins: [svelte()],
|
||||
base: '',
|
||||
build: {
|
||||
target: 'chrome91',
|
||||
outDir: 'frontend',
|
||||
rollupOptions,
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
|
@ -1,29 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: path.resolve(__dirname, '../src/renderer.ts'),
|
||||
target: 'electron13-renderer',
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../frontend'),
|
||||
filename: 'bundle.js',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.svelte$/,
|
||||
loader: 'svelte-loader',
|
||||
},
|
||||
{
|
||||
test: /\.ts$/,
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
configFile: path.resolve('tsconfig.renderer.json'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
},
|
||||
};
|
|
@ -2,6 +2,7 @@ import 'reflect-metadata';
|
|||
import { Container, interfaces } from 'inversify';
|
||||
import type { AppWindowInterface } from '../modules/app-window/app-window-interface';
|
||||
import { MainAppWindow } from '../modules/app-window/main-app-window';
|
||||
import { MainAppWindow as MainAppWindowDev } from '../modules/app-window/main-app-window.dev';
|
||||
import { Dialog } from '../modules/dialog/dialog';
|
||||
import type { DialogInterface } from '../modules/dialog/dialog-interface';
|
||||
import { Logger } from '../modules/logger/logger';
|
||||
|
@ -40,6 +41,7 @@ import { WorldNameSerializer } from '../modules/serialization/serializers/world-
|
|||
import { WorldSerializer } from '../modules/serialization/serializers/world-serializer';
|
||||
import type { SourceGetterInterface } from '../modules/source/source-getter-interface';
|
||||
import { Store } from '../modules/store/store';
|
||||
import { isDev } from './env';
|
||||
import BindingToSyntax = interfaces.BindingToSyntax;
|
||||
|
||||
export const enum Service {
|
||||
|
@ -182,4 +184,8 @@ container.bind(Service.NHENTAI_APP_WINDOW).to(NhentaiAppWindow);
|
|||
container.bind(Service.NHENTAI_API).to(NhentaiApi);
|
||||
container.bind(Service.NHENTAI_SOURCE_GETTER).to(NhentaiSourceGetter);
|
||||
|
||||
container.bind(Service.APP_WINDOW_MAIN).to(MainAppWindow);
|
||||
if (isDev()) {
|
||||
container.bind(Service.APP_WINDOW_MAIN).to(MainAppWindowDev);
|
||||
} else {
|
||||
container.bind(Service.APP_WINDOW_MAIN).to(MainAppWindow);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { app, BrowserWindow, Event, LoadFileOptions, LoadURLOptions, NewWindowWe
|
|||
import os from 'os';
|
||||
import path from 'path';
|
||||
import { isDev } from '../../core/env';
|
||||
import { completeContentSecurityPolicy, setWindowCsp } from '../session/session-util';
|
||||
import { setWindowCsp } from '../session/session-util';
|
||||
import type { AppWindowInterface } from './app-window-interface';
|
||||
import { WindowClosedError } from './window-closed-error';
|
||||
import BrowserWindowConstructorOptions = Electron.BrowserWindowConstructorOptions;
|
||||
|
@ -64,7 +64,7 @@ export abstract class AppWindow implements AppWindowInterface {
|
|||
public open(): Promise<void> {
|
||||
this._window = new BrowserWindow(this.options);
|
||||
|
||||
setWindowCsp(this._window, completeContentSecurityPolicy(this.getCsp()));
|
||||
setWindowCsp(this._window, this.getCsp());
|
||||
|
||||
this._window.on('closed', () => {
|
||||
this.onClosed();
|
||||
|
|
|
@ -17,4 +17,10 @@ export abstract class FileAppWindow extends AppWindow {
|
|||
protected load(window: BrowserWindow): Promise<void> {
|
||||
return window.loadFile(this.uri, this.loadOptions);
|
||||
}
|
||||
|
||||
protected getCsp(): Session.ContentSecurityPolicy {
|
||||
return {
|
||||
'default-src': ['file:'],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import path from 'path';
|
||||
import { injectable } from 'inversify';
|
||||
import { Service } from '../../core/container';
|
||||
import { inject } from '../../core/inject';
|
||||
import { mergeContentSecurityPolicy } from '../session/session-util';
|
||||
import { UrlAppWindow } from './url-app-window';
|
||||
|
||||
@injectable()
|
||||
export class MainAppWindow extends UrlAppWindow {
|
||||
public constructor(@inject(Service.LOGGER) logger: LoggerInterface) {
|
||||
super(logger, 'http://localhost:3000', {
|
||||
webPreferences: {
|
||||
preload: path.resolve('src/preload.js'),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
protected getCsp(): Session.ContentSecurityPolicy {
|
||||
return mergeContentSecurityPolicy(super.getCsp(), {
|
||||
'script-src-elem': ["'self'"],
|
||||
'connect-src': ['ws:'],
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import path from 'path';
|
||||
import { injectable } from 'inversify';
|
||||
import { Service } from '../../core/container';
|
||||
import { inject } from '../../core/inject';
|
||||
|
@ -8,8 +9,7 @@ export class MainAppWindow extends FileAppWindow {
|
|||
public constructor(@inject(Service.LOGGER) logger: LoggerInterface) {
|
||||
super(logger, 'frontend/index.html', {
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
preload: path.resolve('src/preload.js'),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { dialog, OpenDialogOptions } from 'electron';
|
||||
import { injectable } from 'inversify';
|
||||
import { t } from '../../../shared/services/translation/t';
|
||||
import { t } from '../translation/t';
|
||||
import type { DialogInterface } from './dialog-interface';
|
||||
|
||||
@injectable()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import path from 'path';
|
||||
import { createWriteStream } from 'fs-extra';
|
||||
import { t } from '../../../shared/services/translation/t';
|
||||
import { container, Service } from '../../core/container';
|
||||
import { ipcServer } from '../ipc/ipc-server';
|
||||
import { t } from '../translation/t';
|
||||
|
||||
ipcServer.answer(IpcChannel.NHENTAI_SAVE_FAVORITES, async (): Promise<void> => {
|
||||
const nhentaiApi = container.get(Service.NHENTAI_API);
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { isDev } from '../../core/env';
|
||||
import ContentSecurityPolicy = Session.ContentSecurityPolicy;
|
||||
import CompleteContentSecurityPolicy = Session.CompleteContentSecurityPolicy;
|
||||
|
||||
const defaultCsp: Session.ContentSecurityPolicy = {
|
||||
'default-src': ["'self'"],
|
||||
'style-src': ["'unsafe-inline'"],
|
||||
'style-src-attr': ["'unsafe-inline'"],
|
||||
};
|
||||
|
||||
function stringifyCspHeader(csp: ContentSecurityPolicy): string {
|
||||
|
@ -30,7 +29,7 @@ export function mergeContentSecurityPolicy(...contentSecurityPolicies: ContentSe
|
|||
}, {});
|
||||
}
|
||||
|
||||
export function setWindowCsp(window: Electron.BrowserWindow, csp: CompleteContentSecurityPolicy): void {
|
||||
export function setWindowCsp(window: Electron.BrowserWindow, csp: ContentSecurityPolicy): void {
|
||||
const mergedCsp: ContentSecurityPolicy = { ...defaultCsp, ...csp };
|
||||
|
||||
if (isDev()) {
|
||||
|
@ -52,27 +51,3 @@ export function setWindowCsp(window: Electron.BrowserWindow, csp: CompleteConten
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* fills script-src-elem and script-src-attr with script-src when not present,
|
||||
* fills rest of missing policies with default-src or nothing when it is not present
|
||||
*/
|
||||
export function completeContentSecurityPolicy(csp: ContentSecurityPolicy): CompleteContentSecurityPolicy {
|
||||
const defaultSrc = csp['default-src'] ?? [];
|
||||
const scriptSrc = csp['script-src'] ?? [];
|
||||
return {
|
||||
'child-src': csp['child-src'] ?? defaultSrc,
|
||||
'connect-src': csp['connect-src'] ?? defaultSrc,
|
||||
'default-src': csp['default-src'] ?? defaultSrc,
|
||||
'font-src': csp['font-src'] ?? defaultSrc,
|
||||
'frame-src': csp['frame-src'] ?? defaultSrc,
|
||||
'img-src': csp['img-src'] ?? defaultSrc,
|
||||
'media-src': csp['media-src'] ?? defaultSrc,
|
||||
'object-src': ["'none'"],
|
||||
'script-src': csp['script-src'] ?? defaultSrc,
|
||||
'script-src-elem': csp['script-src-elem'] ?? scriptSrc ?? defaultSrc,
|
||||
'script-src-attr': csp['script-src-attr'] ?? scriptSrc ?? defaultSrc,
|
||||
'style-src': csp['style-src'] ?? defaultSrc,
|
||||
'worker-src': csp['worker-src'] ?? defaultSrc,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -19,25 +19,8 @@ declare namespace Session {
|
|||
'script-src-elem'?: CspValue[];
|
||||
'script-src-attr'?: CspValue[];
|
||||
'style-src'?: CspValue[];
|
||||
'style-src-elem'?: CspValue[];
|
||||
'style-src-attr'?: CspValue[];
|
||||
'worker-src'?: CspValue[];
|
||||
};
|
||||
|
||||
/**
|
||||
* meant for usages where the browser shouldn't unexpectedly fall back to default-src
|
||||
*/
|
||||
type CompleteContentSecurityPolicy = {
|
||||
'child-src': CspValue[];
|
||||
'connect-src': CspValue[];
|
||||
'default-src': CspValue[];
|
||||
'font-src': CspValue[];
|
||||
'frame-src': CspValue[];
|
||||
'img-src': CspValue[];
|
||||
'media-src': CspValue[];
|
||||
'object-src': ["'none'"];
|
||||
'script-src': CspValue[];
|
||||
'script-src-elem': CspValue[];
|
||||
'script-src-attr': CspValue[];
|
||||
'style-src': CspValue[];
|
||||
'worker-src': CspValue[];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// same as in renderer
|
||||
|
||||
import { IntlMessageFormat } from 'intl-messageformat';
|
||||
import * as en from '../../../shared/translation/en.json';
|
||||
|
||||
const localeData = {
|
||||
[Locale.EN]: en as TranslationData,
|
||||
};
|
||||
|
||||
function getDeep(deepKey: string, data: TranslationData): string {
|
||||
const keyChain = deepKey.split('.');
|
||||
if (!keyChain.length) {
|
||||
return deepKey;
|
||||
}
|
||||
let index = 0;
|
||||
let curr: TranslationData | string = data;
|
||||
do {
|
||||
const key = keyChain[index];
|
||||
curr = curr[key];
|
||||
index++;
|
||||
} while (typeof curr !== 'string' && index < keyChain.length);
|
||||
if (typeof curr === 'string') {
|
||||
return curr;
|
||||
}
|
||||
return deepKey;
|
||||
}
|
||||
|
||||
const intlMessageFormatCache: Record<Locale, Record<string, IntlMessageFormat>> = {
|
||||
[Locale.EN]: {},
|
||||
};
|
||||
|
||||
/**
|
||||
* translates a message
|
||||
*
|
||||
* @param key - a deep key of the format "labels.actions.save"
|
||||
* @param values - arguments for the message
|
||||
* @param locale - see {@link Locale} for implemented locales
|
||||
*/
|
||||
export function t(key: string, values?: Record<string, string | number | boolean>, locale: Locale = Locale.EN): string {
|
||||
if (!intlMessageFormatCache[locale][key]) {
|
||||
const message = getDeep(key, localeData[locale]);
|
||||
intlMessageFormatCache[locale][key] = new IntlMessageFormat(message, locale);
|
||||
}
|
||||
const intlMessageFormat = intlMessageFormatCache[locale][key];
|
||||
const formatted = intlMessageFormat.format(values);
|
||||
if (typeof formatted === 'string') {
|
||||
return formatted;
|
||||
}
|
||||
return key;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
import { contextBridge, ipcRenderer } from 'electron';
|
||||
|
||||
contextBridge.exposeInMainWorld('ipcRenderer', ipcRenderer);
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { t } from '../../../shared/services/translation/t';
|
||||
import { nhentaiGetWork } from '../../services/api';
|
||||
import { t } from '../../services/translation/t';
|
||||
import Work from '../content/Work.svelte';
|
||||
import SvelteButton from '../elements/SvelteButton.svelte';
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { t } from '../../../shared/services/translation/t';
|
||||
import { nhentaiSaveFavorites } from '../../services/api';
|
||||
import { t } from '../../services/translation/t';
|
||||
import SvelteButton from '../elements/SvelteButton.svelte';
|
||||
|
||||
function handleClick() {
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import { ipcRenderer } from 'electron';
|
||||
import type { IpcRenderer } from 'electron';
|
||||
|
||||
// @ts-ignore -- https://www.electronjs.org/docs/latest/tutorial/context-isolation
|
||||
const ipcRenderer: IpcRenderer = window.ipcRenderer as IpcRenderer;
|
||||
|
||||
export const ipcClient: IpcClient = {
|
||||
ask<T extends IpcChannel>(channel: T, data?: IpcParameter<T>): Promise<IpcAnswer<T>> {
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import { IntlMessageFormat } from 'intl-messageformat';
|
||||
import { en } from './en';
|
||||
// same as in main
|
||||
|
||||
const enum Locale {
|
||||
EN = 'en',
|
||||
}
|
||||
import { IntlMessageFormat } from 'intl-messageformat';
|
||||
import * as en from '../../../shared/translation/en.json';
|
||||
|
||||
const localeData = {
|
||||
[Locale.EN]: en,
|
||||
[Locale.EN]: en as TranslationData,
|
||||
};
|
||||
|
||||
function getDeep(deepKey: string, data: TranslationData): string {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue