mirror of
https://github.com/upscayl/upscayl.git
synced 2024-11-12 01:40:53 +01:00
Updated project
This commit is contained in:
commit
6c18b7eeb3
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [iamWing]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ['https://paypal.me/iamWing0w0']
|
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
.vscode/
|
||||
coverage/
|
||||
dist/
|
||||
node_modules/
|
||||
out/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
|
||||
# OS X files
|
||||
.DS_Store
|
||||
._*
|
165
CHANGELOG_PRE_V4.md
Normal file
165
CHANGELOG_PRE_V4.md
Normal file
@ -0,0 +1,165 @@
|
||||
# Changelog (pre `v4`)
|
||||
All notable changes up to `v3.0.0` are documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [3.0.0] - 2020-12-26
|
||||
### Added
|
||||
- NPM packages `react-router` & `react-router-dom` to package dependencies.
|
||||
- NPM package `eslint-plugin-react-hooks` to `devDependencies` as required by
|
||||
the updated version of `eslint-config-airbnb`.
|
||||
- NPM package `copy-webpack-plugin` to `devDependencies` as replacement of
|
||||
`copy-pkg-json-webpack-plugin`.
|
||||
- NPM packages `@typescript-eslint/eslint-plugin` & `@typescript-eslint/parser`
|
||||
to `devDependencies` for using ESLint to lint TypeScript.
|
||||
|
||||
### Changed
|
||||
- __Project is now being developed based on Node.js `v14 (LTS)`.__
|
||||
- Minor version upgrades on package dependencies:
|
||||
- `eslint-import-resolver-webpack` - `0.11.1` -> `0.13.0`
|
||||
- `eslint-plugin-import` - `2.18.2` -> `2.22.1`
|
||||
- `eslint-plugin-jsx-a11y` - `6.2.3` -> `6.4.1`
|
||||
- `eslint-plugin-react` - `7.17.0` -> ``7.21.5`
|
||||
- `lodash` - `4.17.15` -> `4.17.20`
|
||||
- Major version upgrades on package dependencies:
|
||||
- `react` & `react-dom` - `16.12.0` -> `17.0.1`
|
||||
- `cross-env` - `5.2.1` -> `7.0.3`
|
||||
- `css-loader` - `1.0.1` -> `5.0.1`
|
||||
- `electron` - `3.1.13` -> `11.1.1`
|
||||
- `electron-builder` - `20.44.4` -> `22.9.1`
|
||||
- `eslint` - `5.16.0` -> `7.16.0`
|
||||
- `eslint-config-airbnb` - `17.1.1` -> `18.2.1`
|
||||
- `file-loader` - `2.0.0` -> `6.2.0`
|
||||
- `html-webpack-plugin` - `3.2.0` -> `4.5.0`
|
||||
- `mocha` - `5.2.0` -> `8.2.1`
|
||||
- `rimraf` - `2.7.1` -> `3.0.2`
|
||||
- `source-map-loader` - `0.2.4` -> `2.0.0`
|
||||
- `spectron` - `5.0.0` -> `13.0.0`
|
||||
- `style-loader` - `0.23.1` -> `2.0.0`
|
||||
- `ts-loader` - `5.4.5` -> `8.0.12`
|
||||
- `ts-node` - `7.0.1` -> `9.1.1`
|
||||
- `typescript` - `3.7.2` - > `4.1.3`
|
||||
- `webpack` - `4.41.2` -> `5.11.0`
|
||||
- `webpack-cli` - `3.3.10` -> `4.3.0`
|
||||
- Moved `@types` packages from `dependencies` to `devDependencies` as those
|
||||
have no need to be included in production builds.
|
||||
- Commands of NPM scripts `dev` & `prod` to make them work with Webpack 5.
|
||||
- Migrated to ESLint from TSLint.
|
||||
- Updated prefix of internal paths from `@` to `_` to avoid confusions with
|
||||
scoped NPM packages.
|
||||
- Indentation for `.ts` files is now set as `2` spaces instead of `4`.
|
||||
- `electron-builder` settings:
|
||||
- `win`:
|
||||
- Enabled `asar`. _(turn it off if the executable built doesn't work)_
|
||||
- Disabled one click installer.
|
||||
- Allowed custom installation directory in the installer built.
|
||||
- `mac`:
|
||||
- Changed build target back to `dmg`.
|
||||
- `buildVersion` is now being used as build number instead of just another
|
||||
parameter for semantic version number.
|
||||
- Updated section `Known issues` in `README`.
|
||||
|
||||
### Fixed
|
||||
- ESLint errors/warnings on `main.ts` & `renderer.tsx`.
|
||||
- `electron-builder` fails to build `dmg` on `macOS` (issue
|
||||
[electron-builder #3990])by upgrading the package version to `> 21.2.0`.
|
||||
|
||||
### Removed
|
||||
- NPM package `copy-pkg-json-webpack-plugin` as it doesn't work with Webpack 5
|
||||
and seems not very well maintained.
|
||||
- NPM packages `acorn` & `ajv` from `devDependencies` as they're not being used
|
||||
in this boilerplate.
|
||||
- NPM packages `tslint` & `tslint-microsoft-contrib` as TSLint is now
|
||||
deprecated.
|
||||
|
||||
## [2.0.2] - 2019-12-02
|
||||
`v2.0.2` is a minor hotfix release fixed the documentation error and build
|
||||
error on `macOS Catalina(10.15+)`.
|
||||
|
||||
### Added
|
||||
- Extended README section `Getting started` with `npm start` command
|
||||
description.
|
||||
- README section `Known issue`.
|
||||
|
||||
### Changed
|
||||
- Minor version upgrades on package dependencies.
|
||||
- `macOS` build target to `pkg` from default `dmg` due to no 32-bit apps
|
||||
support from `macOS Catalina` that caused `electron-builder` fails to build
|
||||
`dmg` image on `macOS` prior to `electron-builder@21.2.0`.
|
||||
_`pkg` build is unaffected and is used as a workaround for the current version
|
||||
prior to the major version upgrades on dependencies in next release._
|
||||
_Related issue: [electron-builder #3990](https://github.com/electron-userland/electron-builder/issues/3990)_
|
||||
|
||||
### Fixed
|
||||
- [Issue #2] - incorrect command `npm run install` to `npm install` in `README`.
|
||||
|
||||
## [2.0.1] - 2018-02-05
|
||||
`v2.0.1` is a minor hotfix release patched the `NODE_ENV` not set on Windows
|
||||
issue.
|
||||
|
||||
### Added
|
||||
- Package `cross-env` as `devDependencies`.
|
||||
- README section "Author".
|
||||
|
||||
### Fixed
|
||||
- NPM scripts won't set environment variables on Windows issue.
|
||||
|
||||
## 2.0.0 - 2018-02-04
|
||||
`v2.0.0` is a major release that most part of the boilerplate has been rewritten.
|
||||
|
||||
### Added
|
||||
- ESLint for code checking on Javascript files.
|
||||
- Airbnb's extensible `.eslintrc` package & its' peer dependencies.
|
||||
- `.eslintrc` that extends Airbnb's config and has customised rules configured.
|
||||
- _Rule `no-default-export` is set for JavaScript files to align with
|
||||
TypeScript._
|
||||
- ESLint plugin `eslint-import-resolver-webpack` for ESLint to resolve path
|
||||
aliases set in Webpack config.
|
||||
- Webpack plugin `copy-pkg-json-webpack-plugin` to generate a `package.json`
|
||||
file and pack into Webpack's bundled package for production.
|
||||
- Build commands `build:mac` & `build:win` to package & build the installer of
|
||||
your Electron app for macOS & Windows using `electron-builder`.
|
||||
- README section "Building the installer for your Electron app" & sub-section
|
||||
"Extra options".
|
||||
|
||||
### Changed
|
||||
- Refactored Webpack config file to have `mainConfig` & `rendererConfig`
|
||||
cleaned up, and set mode by environment variable.
|
||||
- `.gitignore` to ignore folder `out/` which will be auto-generated during the
|
||||
build process.
|
||||
- README section "How does it work?" is now renamed to "Getting started" &
|
||||
completed the documentation of this section.
|
||||
- README section "Folder structure" to reflect the changes in `v2.0.0`.
|
||||
|
||||
### Fixed
|
||||
- CSS files fail to inject into views issue by setting Webpack to use
|
||||
`style-loader` alongside with `css-loader` to bundle the files in Webpack
|
||||
config file.
|
||||
- `baseUrl` in `tsconfig.json` points to root directory incorrectly issue.
|
||||
Corrected to current directory so VSCode can resolves the path aliases
|
||||
correctly.
|
||||
|
||||
### Removed
|
||||
- Redux & React-Redux related settings, including packages listed on
|
||||
`devDependencies`, path aliases & folders listed in folder structure.
|
||||
- Since Electron's built-in IPC & basic React states should be enough to get
|
||||
the works done, and most Electron apps which have their application logic
|
||||
runs on Electron's `main` process rather then `renderer` process actually
|
||||
don't need React-Redux, `redux` & `react-redux` are no longer included in
|
||||
this boilerplate.
|
||||
- Redux & React-Redux can still be used on this boilerplate by installing the
|
||||
package yourself. For details, please refer to the corresponding library's
|
||||
documents, there's no different than working on any other project which
|
||||
isn't based on this boilerplate.
|
||||
- Separated Webpack config files for `development` & `production` mode.
|
||||
|
||||
[Unreleased]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/compare/v3.0.0...HEAD
|
||||
[2.0.1]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/compare/v2.0.0...v2.0.1
|
||||
[2.0.2]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/compare/v2.0.1...v2.0.2
|
||||
[3.0.0]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/compare/v2.0.2...v3.0.0
|
||||
|
||||
[Issue #2]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/issues/2
|
||||
[electron-builder #3990]: https://github.com/electron-userland/electron-builder/issues/3990
|
91
CHANGELOG_V4+.md
Normal file
91
CHANGELOG_V4+.md
Normal file
@ -0,0 +1,91 @@
|
||||
# Changelog `v4+`
|
||||
All notable changes to this project on `v4+` will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v4.0.0] - 2022-07-22
|
||||
### Added
|
||||
- Jest as default unit testing framework, with sample test suite for `main`.
|
||||
- Integrated Electron preload pattern.
|
||||
- NPM scripts:
|
||||
- `watch-test` to run Jest in watch mode.
|
||||
- `next-rc`, `next-patch`, `next-minor` & `next-major` for quick
|
||||
package version number advance.
|
||||
|
||||
### Changed
|
||||
- Webpack will now take the module path alias from `tsconfig.json` and set it
|
||||
for you thanks to `tsconfig-paths-webpack-plugin`. Manually set up in Webpack
|
||||
config is no longer needed.
|
||||
- `tsconfig` now configured to use `ES2020` features, with module resolution
|
||||
set to `Node16` to match the NodeJS version used by Electron.
|
||||
- Migrated to the new `createRoot` API introduced in React `v18`.
|
||||
- Some APIs changed in Electron `main` entry script:
|
||||
- `mainWindow` now use `loadFile` API instead of `loadURL`.
|
||||
- Replaced `app.on('ready')` with `app.whenReady()` to align with syntax from
|
||||
[Electron official quick start guide](https://www.electronjs.org/docs/latest/tutorial/quick-start).
|
||||
- `electron-builder` now configured to build `universal` `dmg` for mac, 32 &
|
||||
64 bit `exe` for Windows.
|
||||
- Moved `electron-builder`, Webpack & Webpack-related packages to
|
||||
`optionalDependencies`.
|
||||
- Revamped `README`.
|
||||
- __*Starting from this version, the maintenance schedule will be on a monthly
|
||||
update basis to keep the package dependencies up to date and keep the
|
||||
development going.*__
|
||||
|
||||
### Fixed
|
||||
- Allow to use `import default` statement on non ES modules (e.g. React,
|
||||
lodash) by enabling `esModuleInterop` in `tsconfig`.
|
||||
[#14](https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/issues/14)
|
||||
|
||||
### Removed
|
||||
- Mocha in favour of Jest.
|
||||
- Spectron as it ahs been deprecated.
|
||||
*See - [Spectron Deprecation Notice](https://www.electronjs.org/blog/spectron-deprecation-notice)*
|
||||
|
||||
### Updates on package dependencies
|
||||
### Added
|
||||
- `@types/jest`, `jest`, `ts-jest`, `eslint-plugin-jest` *- Jest support*
|
||||
- `eslint-config-airbnb-typescript` *- Enhance Airbnb's rules in TypeScript*
|
||||
- `ts-config-paths-webpack-plugin` *- Load `tsconfig` path alias into Webpack
|
||||
config*
|
||||
|
||||
### Updated
|
||||
- Major version updates:
|
||||
- `react` & `react-dom` - `17.0.1` -> `18.2.0`
|
||||
- `@types/react` - `17.0.0` -> `18.0.15`
|
||||
- `@types/react-dom` - `17.0.0` -> `18.0.6`
|
||||
- `@typescript-eslint/eslint-plugin` & `@typescript-eslint/parser` -
|
||||
`4.11.0` -> `5.30.7`
|
||||
- `electron` - `11.1.1` -> `19.0.9`
|
||||
- `eslint-config-airbnb` - `18.2.1` -> `19.0.4`
|
||||
- `copy-webpack-plugin` - `7.0.0` -> `11.0.0`
|
||||
- `css-loader` - `5.0.1` -> `6.7.1`
|
||||
- `electron-builder` - `22.9.1` -> `23.1.0`
|
||||
- `html-webpack-plugin` - `4.5.0` -> `5.5.0`
|
||||
- `style-loader` - `2.0.0` -> `3.3.1`
|
||||
- `ts-loader` - `8.0.12` -> `9.3.1`
|
||||
- `ts-config-paths` - `3.9.0` -> `4.0.0`
|
||||
- Minor & patch version updates:
|
||||
- `eslint-import-resolver-webpack` - `0.13.0` -> `0.13.2`
|
||||
- `eslint-plugin-import` - `2.22.1` -> `2.26.0`
|
||||
- `eslint-plugin-jsx-a11y` - `6.4.1` -> `6.6.1`
|
||||
- `eslint-plugin-react` - `7.21.5` -> `7.30.1`
|
||||
- `eslint-plugin-react-hoots` - `4.2.0` -> `4.6.0`
|
||||
- `lodash` - `4.17.20` -> `4.17.21`
|
||||
- `webpack` - `5.11.0` -> `5.73.0`
|
||||
- `webpack-cli` - `4.3.0` -> `4.10.0`
|
||||
|
||||
### Removed
|
||||
- `react-router`, `react-router-dom`, `@types/react-router`,
|
||||
`@types/react-router-dom`
|
||||
|
||||
*\- Not being used in any part of the boilerplate*
|
||||
- `@types/mocha`, `mocha`, `ts-node` *- Replaced by `@types/jest`, `jest` &
|
||||
`ts-jest`*
|
||||
- `spectron` *- Deprecated package; No replacement*
|
||||
|
||||
[Unreleased]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/compare/v4.0.0...HEAD
|
||||
[v4.0.0]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/compare/v3.0.0...v4.0.0
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Devtography
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
275
README.md
Normal file
275
README.md
Normal file
@ -0,0 +1,275 @@
|
||||
# Electron-React-TypeScript-Webpack-Boilerplate
|
||||
A boilerplate that let you instantly start working on your next [Electron] app
|
||||
in [TypeScript] with no time wasted messing with the config files.
|
||||
|
||||
- Ready to use [Electron] project template with [React], [Webpack] and
|
||||
[TypeScript] seamlessly integrated.
|
||||
- [ESLint] set up with TypeScript, Airbnb's rules, and [Jest] support.
|
||||
- [Jest] integrated and configured.
|
||||
- [`electron-builder`] for app packaging, with basic build config for Windows
|
||||
macOS included.
|
||||
- Clean, easy to read and alter config files. No config file is hidden behind
|
||||
yet another script!
|
||||
- Monthly maintenance to keep things up to date!
|
||||
|
||||
*This boilerplate is tested on the latest macOS and Windows. If anything
|
||||
doesn't work, please [file an issue].*
|
||||
|
||||
### Maintenance schedule
|
||||
Starting from `v4.0.0`, the project maintenance will become much more regular.
|
||||
A new release will be published on a monthly basis to keep the package
|
||||
dependencies, package configurations and APIs / syntax up to date.
|
||||
|
||||
Maintenance work will begin on 1st of each month, and expect the new version to
|
||||
be released within the first week of the month. New features from different
|
||||
tools integrated in this boilerplate might not always be implemented at once,
|
||||
especially on experimental features. If you want any particular feature to be
|
||||
implemented, please [file an issue], or consider make a [new pull request].
|
||||
|
||||
### Development plan
|
||||
- [ ] Create a `create-react-app`-like package initialiser __!!!__
|
||||
- [ ] Integrate another end-to-end testing framework to replace [Spectron]
|
||||
- [ ] Migrate to Webpack 5 `Asset Modules`
|
||||
|
||||
---
|
||||
|
||||
## 🚨 🚧 CAUTION 🚧 🚨
|
||||
- [Spectron] has officially been deprecated by the [Electron] team on
|
||||
February 1, 2022, thus, its' integration has also been dropped from this
|
||||
boilerplate on `v4+`.
|
||||
|
||||
A replacement will be integrated in future version (pending for `v5`).
|
||||
Currently evaluating different options including [Playwright] and
|
||||
[WebdriverIO].
|
||||
|
||||
*See - [Spectron Deprecation Notice]*
|
||||
|
||||
- `mocha` has been dropped and replaced by [Jest] on `v4+`. If you're using
|
||||
`mocha` as your unit testing framework, please reference to `package.json`
|
||||
from [`v3.0.0`].
|
||||
|
||||
---
|
||||
|
||||
## Getting started
|
||||
1. Clone this repository, or if you're hosting your Electron project on GitHub,
|
||||
click [`Use this template`] to create a new project.
|
||||
|
||||
2. Edit the following fields in `package.json` for your own project:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "your-project-name",
|
||||
"version": "whatever-you-like",
|
||||
"description": "your-own-description",
|
||||
"build": {
|
||||
"appId": "your-app-id",
|
||||
"productName": "your-product-name",
|
||||
"buildVersion": "your-build-number"
|
||||
},
|
||||
"author": "who's-the-author?",
|
||||
"license": "if-you-don't-want-to-use-MIT",
|
||||
"repository": "type-and-link-of-your-repo",
|
||||
"bugs": "issue-page-of-your-repo",
|
||||
"homepage": "homepage-of-your-repo"
|
||||
}
|
||||
```
|
||||
|
||||
3. `npm install` to install the dependencies.
|
||||
|
||||
*Please note that `optionalDependencies` should only be omitted on your
|
||||
CI/CD pipeline for unit testing. It's meant to save some bandwidth. You'll
|
||||
need all the packages listed for development.*
|
||||
|
||||
Done! Now run `npm run dev` to start the Webpack in development and watch mode.
|
||||
It's time to start working on your project.
|
||||
|
||||
Be aware that starting Webpack will only compile your files to `dist` folder
|
||||
but won't start the Electron app. Use `npm start` command to start your
|
||||
Electron app once the files are compiled.
|
||||
|
||||
__*Starting from `v4.0.0`, you no longer need to manually config your module
|
||||
path alias in `webpack.config.js`. All module path alias set in `tsconfig.json`
|
||||
will be configured in Webpack automatically thanks to [`tsconfig-paths`] and
|
||||
[`tsconfig-paths-webpack-plugin`].*__
|
||||
|
||||
## Build your Electron app package
|
||||
Different from the official [Electron quick start guide], this boilerplate uses
|
||||
[`electron-builder`] instead of [Electron Forge] to package your Electron app.
|
||||
|
||||
By default, the build configuration in `package.json` is configured to build the
|
||||
mac universal package (for Apple Silicon & Intel based machines) and Windows
|
||||
`exe` installer (both 32 & 64 bit). You should not need to change anything in
|
||||
the build script other than supplying the app icon unless you need to sign your
|
||||
code/package or build for Linux.
|
||||
|
||||
For code signing and notarization, or to build for Linux, please read
|
||||
[`electron-builder`'s document] for configuring the build script.
|
||||
|
||||
To package your Electron app, run `npm run prod` to get your code compiled in
|
||||
`production` mode, then use `npm run build:(win|mac)` to build the package.
|
||||
|
||||
## Known issues
|
||||
- [`electron-builder`] packages the file into Electron's `asar` archive format
|
||||
by default. Based on past experiences with old Electron & `electron-builder`
|
||||
versions, this might lead to runtime error on Windows while launching the
|
||||
installed Electron app.
|
||||
|
||||
One way to verify this issue is to build the mac package and see if your app
|
||||
runs fine on mac. If it's the case, you can override the `asar` archive
|
||||
option in the build configuration in `package.json` by adding `asar: false`
|
||||
in `win` section.
|
||||
|
||||
This solution isn't ideal but since `asar` archiving is
|
||||
meant to improve performance of reading files if bundler like Webpack is not
|
||||
being used. The app packaging workflow defined in this boilerplate already
|
||||
uses Webpack to minify your code in `production` builds, so there shouldn't
|
||||
be any significant performance different with `asar` archiving disabled.
|
||||
|
||||
## Project folders & files
|
||||
- `dist/` - [Webpack] output location
|
||||
|
||||
__Contents will be flushed automatically on execution of `npm run <dev|prod>`
|
||||
script.__
|
||||
|
||||
- `out/` - [`electron-builder`] output location
|
||||
|
||||
- `public/` - Global static assets.
|
||||
- `index.html` - Template for `HTML Webpack Plugin`
|
||||
|
||||
Update the value of `<title>` tag to change the default window title.
|
||||
|
||||
- `style.css` - `CSS` file location sample
|
||||
|
||||
Not much defined in this file. You can either put your `CSS` settings here
|
||||
or use any other tools you prefer.
|
||||
|
||||
- `src/` - Folder for all your source code
|
||||
- `main/` - For modules which run on the `main` process.
|
||||
- `main.ts` - [Electron] `main` process entry point
|
||||
|
||||
- `preload` - Preload scripts go here
|
||||
- `ipc-api.ts` - APIs for IPC between `main` & `renderer`
|
||||
|
||||
Consider convert this module into a collection of submodules if you have
|
||||
many APIs for IPC. See example as below:
|
||||
```ts
|
||||
// ipc-api/index.ts
|
||||
import submoduleA from './submodule-a';
|
||||
import submoduleB from './submodule-b';
|
||||
|
||||
export default { ...submoduleA, ...submoduleB };
|
||||
|
||||
// ipc-api/submodule-a.ts
|
||||
import { ipcRenderer } from 'electron';
|
||||
|
||||
function a { ipcRenderer.send('a'); }
|
||||
|
||||
export default { a };
|
||||
|
||||
// ipc-api/submodule-b.ts
|
||||
import { ipcRenderer } from 'electron';
|
||||
|
||||
function b { ipcRenderer.send('b'); }
|
||||
|
||||
export default { b };
|
||||
```
|
||||
|
||||
- `preload.ts` - [Electron] preload script entry point
|
||||
|
||||
There should be no need to modify this file unless you want to use other
|
||||
key(s) for your IPC APIs. By default, all APIs defined in `ipc-api`
|
||||
module are exposed under key `ipcApi` in `contextBridge`.
|
||||
|
||||
- `renderer/` - Where the frontend scripts stay
|
||||
- `App.tsx` - Root [React] component
|
||||
- `renderer.tsx` - [Electron] `renderer` process entry point
|
||||
|
||||
*`public/style.css` imported here. Change it if you want.*
|
||||
|
||||
- `types/` - Home for self-defined `.d.ts` files
|
||||
- `global.d.ts` - Extends global scope interfaces
|
||||
|
||||
This file includes ambient declaration for calling the IPC APIs defined in
|
||||
`preload/ipc-api` from the `renderer`. Remember __NOT__ to remove this
|
||||
part, otherwise TypeScript will tell you `type not exist`. However, if
|
||||
you've opted to use a different key other than `ipcAPI` in the preload
|
||||
script, __DO__ remember to update this file to match your own settings.
|
||||
|
||||
- `utils/` - Place to store the helper scripts
|
||||
- `node-env.ts` - Shortcut to determine `NODE` environment
|
||||
|
||||
- `tests/` - Unit testing files location
|
||||
|
||||
To avoid test files mixing up with the source code, [Jest] is configured to
|
||||
look for test file(s) within this folder only.
|
||||
|
||||
File name of the test files can either be `[filename].test.tsx` or
|
||||
`[filename].spec.ts(x)`. `js(x)` can also be used for test files, but I assume
|
||||
you'd use TypeScript if you're using this boilerplate.
|
||||
|
||||
- `main/main.spec.ts` - Sample test file for `src/main/main`
|
||||
- `tsconfig.json` - TypeScript config file for `tests` module
|
||||
- `.eslintignore` - [ESLint] ignore file
|
||||
- `.eslintrc` - [ESLint] config file
|
||||
|
||||
Configured to use Airbnb's rules with [TypeScript] supported, and rules for
|
||||
[Jest] applied.
|
||||
|
||||
- `.gitignore` - Git ignore file
|
||||
- `CHANGELOG_PRE_V4.md` - Changelog of this boilerplate prior to `v4.0.0`
|
||||
- `CHANGELOG_V4+.md` - Changelog of this boilerplate from `v4.0.0` onwards
|
||||
- `jest.config.js` - [Jest] config file
|
||||
- `LICENSE` - MIT license
|
||||
- `package-lock.json`
|
||||
- `package.json`
|
||||
|
||||
Includes basic build config for `electron-builder`. It's likely that you'll
|
||||
have to personalise the build config when it comes to the time you're about
|
||||
to release your app. Please read [`electron-builder`'s document] for the
|
||||
build config setup guides.
|
||||
|
||||
- `README.md`
|
||||
- `tsconfig.json` - [TypeScript] config file
|
||||
|
||||
Module path aliases are configured here. [Jest] & [Webpack] will pick up the
|
||||
alias settings here to config their own. No need to manually config in Jest
|
||||
& Webpack again.
|
||||
|
||||
- `webpack.config.json` - [Webpack] config file
|
||||
|
||||
Includes configurations targetting `electron-main`, `electron-preload`, and
|
||||
`electron-renderer` respectively.
|
||||
|
||||
## Author
|
||||
[Wing Chau](https://github.com/iamWing) [@Devtography](https://github.com/Devtography)
|
||||
|
||||
## Donation
|
||||
Maintaining this project takes time, lots of cups of coffee, and I do it for
|
||||
free. Consider buy me coffee via [donations]. 100% of donation will fund my
|
||||
coffee buying budget for quality coffee beans from great roasters I know 😉 ☕️️
|
||||
|
||||
## License
|
||||
Electron React TypeScript Webpack Boilerplate is open source software
|
||||
[licensed as MIT](LICENSE).
|
||||
|
||||
[Electron]: https://www.electronjs.org
|
||||
[React]: https://reactjs.org
|
||||
[Webpack]: https://webpack.js.org
|
||||
[TypeScript]: https://www.typescriptlang.org
|
||||
[ESLint]: http://eslint.org
|
||||
[Jest]: https://jestjs.io
|
||||
[`electron-builder`]: https://github.com/electron-userland/electron-builder
|
||||
[file an issue]: https://www.electronjs.org
|
||||
[new pull request]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/compare
|
||||
[Spectron]: https://github.com/electron-userland/spectron
|
||||
[Playwright]: https://playwright.dev
|
||||
[WebdriverIO]: https://webdriver.io
|
||||
[Spectron Deprecation Notice]: https://www.electronjs.org/blog/spectron-deprecation-notice
|
||||
[`v3.0.0`]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/releases/tag/v3.0.0
|
||||
[`Use this template`]: https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/generate
|
||||
[`tsconfig-paths`]: https://github.com/dividab/tsconfig-paths
|
||||
[`tsconfig-paths-webpack-plugin`]: https://github.com/dividab/tsconfig-paths-webpack-plugin
|
||||
[Electron quick start guide]: https://www.electronjs.org/docs/latest/tutorial/quick-start
|
||||
[Electron Forge]: https://github.com/electron-userland/electron-forge
|
||||
[`electron-builder`'s document]: https://www.electron.build
|
||||
[donations]: https://github.com/sponsors/iamWing
|
30
jest.config.js
Normal file
30
jest.config.js
Normal file
@ -0,0 +1,30 @@
|
||||
const { pathsToModuleNameMapper } = require('ts-jest')
|
||||
const { compilerOptions } = require('./tsconfig.json')
|
||||
|
||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
module.exports = config = {
|
||||
testEnvironment: 'node',
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: 'tsconfig.json',
|
||||
},
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
||||
moduleNameMapper: pathsToModuleNameMapper(
|
||||
compilerOptions.paths,
|
||||
{ prefix: '<rootDir>/' },
|
||||
),
|
||||
modulePathIgnorePatterns: [
|
||||
'<rootDir>/dist',
|
||||
'<rootDir>/node_modules',
|
||||
'<rootDir>/out',
|
||||
],
|
||||
transform: {
|
||||
'^.+\\.(ts|tsx)$': 'ts-jest',
|
||||
},
|
||||
testMatch: [
|
||||
'**/tests/**/*.(spec|test).(ts?(x)|js?(x))',
|
||||
],
|
||||
collectCoverage: true,
|
||||
verbose: true,
|
||||
};
|
89
package.json
Normal file
89
package.json
Normal file
@ -0,0 +1,89 @@
|
||||
{
|
||||
"name": "electron-react-typescript-webpack-boilerplate",
|
||||
"version": "4.0.0",
|
||||
"description": "Pre-configured boilerplate for Electron + React + TypeScript",
|
||||
"main": "./dist/main.bundle.js",
|
||||
"scripts": {
|
||||
"start": "electron ./dist/main.bundle.js",
|
||||
"webpack:dev": "rimraf dist && cross-env NODE_ENV=development webpack --watch --progress --color",
|
||||
"prod": "rimraf dist && cross-env NODE_ENV=production webpack --progress --color",
|
||||
"test": "cross-env NODE_ENV=test jest",
|
||||
"watch-test": "npm run test -- --watchAll",
|
||||
"next-rc": "npm --no-git-tag-version version prerelease --preid=rc",
|
||||
"next-patch": "npm --no-git-tag-version version patch",
|
||||
"next-minor": "npm --no-git-tag-version version minor",
|
||||
"next-major": "npm --no-git-tag-version version major",
|
||||
"build:win": "electron-builder build --win",
|
||||
"build:mac": "electron-builder build --mac"
|
||||
},
|
||||
"build": {
|
||||
"appId": "com.devtography.electron_boilerplate",
|
||||
"productName": "Electron+React+TypeScript Boilerplate",
|
||||
"directories": {
|
||||
"app": "./dist/",
|
||||
"output": "./out/"
|
||||
},
|
||||
"mac": {
|
||||
"target": {
|
||||
"target": "dmg",
|
||||
"arch": "universal"
|
||||
}
|
||||
},
|
||||
"win": {
|
||||
"target": {
|
||||
"target": "nsis",
|
||||
"arch": [
|
||||
"x64",
|
||||
"ia32"
|
||||
]
|
||||
}
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"buildVersion": "1"
|
||||
},
|
||||
"author": "Wing Chau @Devtography",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tensorflow/tfjs": "^3.19.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.2",
|
||||
"upscaler": "^1.0.0-beta.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^28.1.6",
|
||||
"@types/react": "^18.0.15",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"cross-env": "^7.0.3",
|
||||
"electron": "^19.0.9",
|
||||
"jest": "^28.1.3",
|
||||
"ts-jest": "^28.0.7",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"electron-builder": "^23.1.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"rimraf": "^3.0.2",
|
||||
"style-loader": "^3.3.1",
|
||||
"ts-loader": "^9.3.1",
|
||||
"tsconfig-paths": "^4.0.0",
|
||||
"tsconfig-paths-webpack-plugin": "^3.5.2",
|
||||
"webpack": "^5.73.0",
|
||||
"webpack-cli": "^4.10.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Devtography/electron-react-typescript-webpack-boilerplate"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Devtography/electron-react-typescript-webpack-boilerplate/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Devtography/electron-react-typescript-webpack-boilerplate#readme"
|
||||
}
|
13
public/index.html
Normal file
13
public/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app" class="app"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
3
public/style.css
Normal file
3
public/style.css
Normal file
@ -0,0 +1,3 @@
|
||||
.app {
|
||||
color: grey;
|
||||
}
|
68
src/main/main.ts
Normal file
68
src/main/main.ts
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Entry point of the Election app.
|
||||
*/
|
||||
import * as path from "path";
|
||||
import * as nodeEnv from "_utils/node-env";
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import { BrowserWindow, app, ipcMain } from "electron";
|
||||
|
||||
let mainWindow: Electron.BrowserWindow | undefined;
|
||||
|
||||
function createWindow() {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
height: 600,
|
||||
width: 800,
|
||||
webPreferences: {
|
||||
devTools: nodeEnv.dev,
|
||||
preload: path.join(__dirname, "./preload.bundle.js"),
|
||||
webSecurity: nodeEnv.prod,
|
||||
nodeIntegration: true,
|
||||
},
|
||||
});
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile("index.html").finally(() => {
|
||||
/* no action */
|
||||
});
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on("closed", () => {
|
||||
mainWindow = undefined;
|
||||
});
|
||||
}
|
||||
app.commandLine.appendSwitch("ignore-gpu-blacklist");
|
||||
app
|
||||
.whenReady()
|
||||
.then(() => {
|
||||
if (nodeEnv.dev || nodeEnv.prod) createWindow();
|
||||
|
||||
app.on("activate", () => {
|
||||
if (BrowserWindow.getAllWindows.length === 0) createWindow();
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
/* no action */
|
||||
});
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") app.quit();
|
||||
});
|
||||
|
||||
// const getUpscaledImage = async () => {
|
||||
// const file = fs.readFileSync(path.resolve(__dirname, "./image.png"));
|
||||
// const image = tf.node.decodeImage(file, 3);
|
||||
// const tensor = await upscaler.upscale(image, {
|
||||
// output: "tensor",
|
||||
// patchSize: 64,
|
||||
// padding: 6,
|
||||
// });
|
||||
// image.dispose();
|
||||
// const upscaledTensor = await tf.node.encodePng(tensor);
|
||||
// tensor.dispose();
|
||||
// return upscaledTensor;
|
||||
// };
|
||||
|
||||
ipcMain.on("hello", async () => {});
|
||||
|
||||
export const exportedForTests = nodeEnv.test ? { createWindow } : undefined;
|
4
src/preload/preload.ts
Normal file
4
src/preload/preload.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { contextBridge } from "electron";
|
||||
import { ipcRenderer } from "electron";
|
||||
|
||||
contextBridge.exposeInMainWorld("ipcRenderer", ipcRenderer);
|
121
src/renderer/App.css
Normal file
121
src/renderer/App.css
Normal file
@ -0,0 +1,121 @@
|
||||
body {
|
||||
padding: 40px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
display: flex;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#root {
|
||||
display: flex;
|
||||
}
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dropzone {
|
||||
cursor: move; /* fallback if grab cursor is unsupported */
|
||||
cursor: grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: -webkit-grab;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
padding: 40px;
|
||||
border: 5px dotted #ddd;
|
||||
margin: 0 auto;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.app {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.original-image {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.original img {
|
||||
transition-duration: 1.2s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
button {
|
||||
background: #ddd;
|
||||
padding: 5px 10px;
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
button:first-child {
|
||||
border-radius: 5px 0 0 5px;
|
||||
border-right: none;
|
||||
}
|
||||
button:last-child {
|
||||
border-radius: 0 5px 5px 0;
|
||||
}
|
||||
|
||||
button.active {
|
||||
background: #c4c4ff;
|
||||
}
|
||||
|
||||
.display {
|
||||
position: relative;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.display .image-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.display .scaled-up img {
|
||||
display: block;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
}
|
||||
|
||||
.dragOverlay {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dragger {
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
width: 4px;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
position: absolute;
|
||||
transform: translate(50px 0);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-height: 40px;
|
||||
}
|
||||
.interpolation {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
182
src/renderer/App.tsx
Normal file
182
src/renderer/App.tsx
Normal file
@ -0,0 +1,182 @@
|
||||
import Upscaler from "upscaler";
|
||||
import React, { useCallback, useState, useEffect, useRef } from "react";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import "./App.css";
|
||||
|
||||
const upscaler = new Upscaler();
|
||||
function App() {
|
||||
const [src, setSrc] = useState<string>();
|
||||
const [originalSize, setOriginalSize] = useState({ width: 0, height: 0 });
|
||||
const [scale, setScale] = useState(1);
|
||||
const [interpolation, setInterpolation] = useState("bicubic");
|
||||
const [upscaledImageSrc, setUpscaledImageSrc] = useState<string>();
|
||||
const [displayUpscaledImageSrc, setDisplayUpscaledImageSrc] = useState(false);
|
||||
const [dragX, setDragX] = useState(0.5);
|
||||
const [dragging, setDragging] = useState(false);
|
||||
const container = useRef<HTMLDivElement>();
|
||||
const onDrop = useCallback((acceptedFiles) => {
|
||||
const file = acceptedFiles[0];
|
||||
const fr = new FileReader();
|
||||
fr.onload = async () => {
|
||||
setSrc(fr.result as string);
|
||||
};
|
||||
fr.readAsDataURL(file);
|
||||
}, []);
|
||||
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
|
||||
useEffect(() => {
|
||||
if (src) {
|
||||
const img = new Image();
|
||||
img.crossOrigin = "anonymous";
|
||||
img.src = src;
|
||||
img.onload = () => {
|
||||
upscaler.upscale(img).then(setUpscaledImageSrc);
|
||||
const width = img.width;
|
||||
const height = img.height;
|
||||
setOriginalSize({
|
||||
width,
|
||||
height,
|
||||
});
|
||||
};
|
||||
}
|
||||
}, [src]);
|
||||
|
||||
useEffect(() => {
|
||||
if (originalSize) {
|
||||
let upscaledImageSrcTimer;
|
||||
const timer = setTimeout(() => {
|
||||
setScale(3);
|
||||
upscaledImageSrcTimer = setTimeout(() => {
|
||||
setDisplayUpscaledImageSrc(true);
|
||||
}, 1200);
|
||||
}, 300);
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
clearTimeout(upscaledImageSrcTimer);
|
||||
};
|
||||
}
|
||||
}, [originalSize]);
|
||||
|
||||
const startDragging = () => {
|
||||
setDragging(true);
|
||||
};
|
||||
|
||||
const drag = (e) => {
|
||||
if (dragging) {
|
||||
const offsetWidth = container.current.offsetWidth;
|
||||
const x = e.clientX - (window.innerWidth - offsetWidth) / 2 - 10;
|
||||
setDragX(x / offsetWidth);
|
||||
}
|
||||
};
|
||||
|
||||
const stopDragging = () => {
|
||||
console.log("stop");
|
||||
setDragging(false);
|
||||
};
|
||||
|
||||
if (src) {
|
||||
const left = dragX * 100;
|
||||
return (
|
||||
<div
|
||||
className="original-image"
|
||||
style={{
|
||||
width: originalSize ? originalSize.width * scale : null,
|
||||
}}
|
||||
>
|
||||
<div className="header">
|
||||
{displayUpscaledImageSrc && (
|
||||
<>
|
||||
<div className="interpolation">
|
||||
<button
|
||||
className={interpolation === "none" ? "active" : null}
|
||||
onClick={() => setInterpolation("none")}
|
||||
>
|
||||
None
|
||||
</button>
|
||||
<button
|
||||
className={interpolation === "bicubic" ? "active" : null}
|
||||
onClick={() => setInterpolation("bicubic")}
|
||||
>
|
||||
Bicubic interpolation
|
||||
</button>
|
||||
</div>
|
||||
<div>Upscaled image</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
className="display"
|
||||
style={{
|
||||
width: originalSize ? originalSize.width * scale : null,
|
||||
height: originalSize ? originalSize.height * scale : null,
|
||||
}}
|
||||
>
|
||||
{displayUpscaledImageSrc && (
|
||||
<div
|
||||
className="dragOverlay"
|
||||
ref={container}
|
||||
onMouseMove={drag}
|
||||
onMouseUp={stopDragging}
|
||||
>
|
||||
<div
|
||||
className="dragger"
|
||||
onMouseDown={startDragging}
|
||||
style={{
|
||||
left: `calc(${left}%)`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="image-container original">
|
||||
<img
|
||||
src={src}
|
||||
alt="Original"
|
||||
width={originalSize ? originalSize.width * scale : null}
|
||||
style={{
|
||||
imageRendering: interpolation === "none" ? "pixelated" : null,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{displayUpscaledImageSrc && (
|
||||
<div
|
||||
className="image-container scaled-up"
|
||||
style={{
|
||||
width: `${100 - left}%`,
|
||||
left: `${left}%`,
|
||||
}}
|
||||
>
|
||||
<img
|
||||
style={{
|
||||
left: ((originalSize.width * scale * left) / 100) * -1,
|
||||
}}
|
||||
alt="Upscaled"
|
||||
src={upscaledImageSrc}
|
||||
width={originalSize ? originalSize.width * scale : null}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{displayUpscaledImageSrc && <p>Resized to 3x</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="dropzone" {...getRootProps()}>
|
||||
<input {...getInputProps()} />
|
||||
{isDragActive ? (
|
||||
<p>Drop the files here ...</p>
|
||||
) : (
|
||||
<p>Drag 'n' drop some files here, or click to select files</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<div className="app">
|
||||
<h1>React Demo Integration</h1>
|
||||
<App />
|
||||
</div>
|
||||
);
|
||||
};
|
BIN
src/renderer/image.jpg
Normal file
BIN
src/renderer/image.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 160 KiB |
13
src/renderer/renderer.tsx
Normal file
13
src/renderer/renderer.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* React renderer.
|
||||
*/
|
||||
// Import the styles here to process them with webpack
|
||||
import "_public/style.css";
|
||||
|
||||
import App from "_renderer/App";
|
||||
import * as React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
|
||||
const container = document.getElementById("app");
|
||||
const root = createRoot(container!);
|
||||
root.render(<App />);
|
10
src/types/global.d.ts
vendored
Normal file
10
src/types/global.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
import { ipcRenderer } from "electron";
|
||||
declare global {
|
||||
interface Window {
|
||||
/** APIs for Electron IPC */
|
||||
ipcRenderer?: typeof ipcRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
// Makes TS sees this as an external modules so we can extend the global scope.
|
||||
export {};
|
12
src/utils/node-env.ts
Normal file
12
src/utils/node-env.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Predefined NODE_ENV values
|
||||
*/
|
||||
|
||||
/** `NODE_ENV=production` */
|
||||
export const prod = process.env.NODE_ENV === 'production';
|
||||
|
||||
/** `NODE_ENV=development` */
|
||||
export const dev = process.env.NODE_ENV === 'development';
|
||||
|
||||
/** `NODE_ENV=test` */
|
||||
export const test = process.env.NODE_ENV === 'test';
|
25
tests/main/main.spec.ts
Normal file
25
tests/main/main.spec.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { exportedForTests } from '_main/main';
|
||||
import { BrowserWindow } from 'electron';
|
||||
|
||||
jest.mock('electron', () => ({
|
||||
app: {
|
||||
on: jest.fn(),
|
||||
whenReady: jest.fn(() => Promise.resolve()),
|
||||
},
|
||||
ipcMain: { on: jest.fn() },
|
||||
BrowserWindow: jest.fn().mockImplementation(() => ({
|
||||
loadFile: jest.fn(() => Promise.resolve()),
|
||||
on: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
test('Private props exported for unit tests', () => {
|
||||
expect(exportedForTests).toBeDefined();
|
||||
});
|
||||
|
||||
test('func createWindow()', () => {
|
||||
const { createWindow } = exportedForTests!;
|
||||
|
||||
createWindow();
|
||||
expect(BrowserWindow).toHaveBeenCalledTimes(1);
|
||||
});
|
7
tests/tsconfig.json
Normal file
7
tests/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["./**/*"]
|
||||
}
|
28
tsconfig.json
Normal file
28
tsconfig.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": false,
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
"module": "ES2020",
|
||||
"moduleResolution": "Node16",
|
||||
|
||||
"noImplicitAny": false,
|
||||
"paths": {
|
||||
"_/*": ["src/*"],
|
||||
"_public/*": ["public/*"],
|
||||
"_main/*": ["src/main/*"],
|
||||
"_preload/*": ["src/preload/*"],
|
||||
"_renderer/*": ["src/renderer/*"],
|
||||
"_types/*": ["src/types/*"],
|
||||
"_utils/*": ["src/utils/*"],
|
||||
"_tests/*": ["tests/*"]
|
||||
},
|
||||
"typeRoots": ["./node_modules/@types", "./src/types"],
|
||||
"sourceMap": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react",
|
||||
"target": "ES2020"
|
||||
},
|
||||
"include": ["src/**/*", "tests/**/*"]
|
||||
}
|
95
webpack.config.js
Normal file
95
webpack.config.js
Normal file
@ -0,0 +1,95 @@
|
||||
const lodash = require('lodash');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||
const path = require('path');
|
||||
|
||||
function srcPaths(src) {
|
||||
return path.join(__dirname, src);
|
||||
}
|
||||
|
||||
const isEnvProduction = process.env.NODE_ENV === 'production';
|
||||
const isEnvDevelopment = process.env.NODE_ENV === 'development';
|
||||
|
||||
// #region Common settings
|
||||
const commonConfig = {
|
||||
devtool: isEnvDevelopment ? 'source-map' : false,
|
||||
mode: isEnvProduction ? 'production' : 'development',
|
||||
output: { path: srcPaths('dist') },
|
||||
node: { __dirname: false, __filename: false },
|
||||
resolve: {
|
||||
extensions: ['.js', '.json', '.ts', '.tsx'],
|
||||
plugins: [new TsconfigPathsPlugin({
|
||||
configFile: './tsconfig.json',
|
||||
extensions: ['.js', '.json', '.ts', '.tsx'],
|
||||
})],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(ts|tsx)$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'ts-loader',
|
||||
},
|
||||
{
|
||||
test: /\.(scss|css)$/,
|
||||
use: ['style-loader', 'css-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.(jpg|png|svg|ico|icns)$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[path][name].[ext]',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
// #endregion
|
||||
|
||||
const mainConfig = lodash.cloneDeep(commonConfig);
|
||||
mainConfig.entry = './src/main/main.ts';
|
||||
mainConfig.target = 'electron-main';
|
||||
mainConfig.output.filename = 'main.bundle.js';
|
||||
mainConfig.plugins = [
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: 'package.json',
|
||||
to: 'package.json',
|
||||
transform: (content, _path) => {
|
||||
const jsonContent = JSON.parse(content);
|
||||
const electronVersion = jsonContent.devDependencies.electron;
|
||||
|
||||
delete jsonContent.devDependencies;
|
||||
delete jsonContent.optionalDependencies;
|
||||
delete jsonContent.scripts;
|
||||
delete jsonContent.build;
|
||||
|
||||
jsonContent.main = './main.bundle.js';
|
||||
jsonContent.scripts = { start: 'electron ./main.bundle.js' };
|
||||
jsonContent.devDependencies = { electron: electronVersion }
|
||||
|
||||
return JSON.stringify(jsonContent, undefined, 2);
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
];
|
||||
|
||||
const preloadConfig = lodash.cloneDeep(commonConfig);
|
||||
preloadConfig.entry = './src/preload/preload.ts';
|
||||
preloadConfig.target = 'electron-preload';
|
||||
preloadConfig.output.filename = 'preload.bundle.js';
|
||||
|
||||
const rendererConfig = lodash.cloneDeep(commonConfig);
|
||||
rendererConfig.entry = './src/renderer/renderer.tsx';
|
||||
rendererConfig.target = 'electron-renderer';
|
||||
rendererConfig.output.filename = 'renderer.bundle.js';
|
||||
rendererConfig.plugins = [
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(__dirname, './public/index.html'),
|
||||
}),
|
||||
];
|
||||
|
||||
module.exports = [mainConfig, preloadConfig, rendererConfig];
|
Loading…
Reference in New Issue
Block a user