extensions : gui renderer
2
packages/kbot/extensions/gui/.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.scss linguist-detectable=false
|
||||
*.sass linguist-detectable=false
|
||||
13
packages/kbot/extensions/gui/.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: guasam
|
||||
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
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
86
packages/kbot/extensions/gui/.gitignore
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
.DS_Store
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# Webpack
|
||||
.webpack/
|
||||
|
||||
# Electron-Forge
|
||||
out/
|
||||
5
packages/kbot/extensions/gui/.prettierrc
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"jsxSingleQuote": true
|
||||
}
|
||||
567
packages/kbot/extensions/gui/CHANGELOG.md
Normal file
@ -0,0 +1,567 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to the project are listed here.
|
||||
|
||||
For more information visit:
|
||||
https://github.com/codesbiome/electron-react-webpack-typescript-2024
|
||||
|
||||
<br>
|
||||
|
||||
### v8.1.0
|
||||
|
||||
- 🎉 Electron version upgraded `v23.0.0`.
|
||||
- Using `eslint.config.json` as eslint configuration.
|
||||
- Tweaked app themes colors.
|
||||
- Upgraded outdated packages:
|
||||
|
||||
| Package | Version |
|
||||
| ------------------------------------ | --------- |
|
||||
| electron | `^31.2.1` |
|
||||
| @electron-forge | `7.4.0` |
|
||||
| electron-squirrel-startup | `^1.0.1` |
|
||||
| @pmmmwh/react-refresh-webpack-plugin | `^0.5.15` |
|
||||
| @typescript-eslint | `^7.16.1` |
|
||||
| css-loader | `^7.1.2` |
|
||||
| eslint | `^9.7.0` |
|
||||
| eslint-plugin-react | `^7.34.4` |
|
||||
| react-refresh | `^0.14.2` |
|
||||
| sass | `^1.77.8` |
|
||||
| sass-loader | `^14.2.1` |
|
||||
| style-loader | `^4.0.0` |
|
||||
| typescript | `^5.5.3` |
|
||||
| webpack | `^5.93.0` |
|
||||
| react | `^18.3.1` |
|
||||
| react-dom | `^18.3.1` |
|
||||
|
||||
<br>
|
||||
|
||||
### v8.0.0
|
||||
|
||||
- 🎉 Application UI and Themes (light/dark).
|
||||
- Using latest Electron version `v28`
|
||||
- Changed app accent colors & added credits menu item.
|
||||
- Integrated `electron-window` components & modules in project's file structure.
|
||||
- Separated dark/light themes from application stylesheet for easy modification.
|
||||
- Added `@styles` alias for easily import stylesheets.
|
||||
- Removed `less-loader` by default from project.
|
||||
- Removed unused `misc` directory.
|
||||
- Removed unused `src/common` directory.
|
||||
- Converted `less` to `scss` for window components stylesheet.
|
||||
- Updated forge config with more useful hints.
|
||||
- Upgraded outdated packages to their latest supported versions.
|
||||
|
||||
<br>
|
||||
|
||||
### v7.8.0
|
||||
|
||||
Upgraded outdated packages:
|
||||
|
||||
| Package | Version |
|
||||
| ------------------------------ | -------- |
|
||||
| electron | `27.1.2` |
|
||||
| @electron-forge | `7.1.0` |
|
||||
| @typescript-eslint | `6.13.1` |
|
||||
| eslint-plugin-import | `2.29.0` |
|
||||
| eslint | `8.54.0` |
|
||||
| less | `4.2.0` |
|
||||
| sass | `1.69.5` |
|
||||
| ts-loader | `9.5.1` |
|
||||
| typescript | `5.3.2` |
|
||||
| webpack | `5.89.0` |
|
||||
| react-refresh-webpack-plugin | `0.5.11` |
|
||||
| fork-ts-checker-webpack-plugin | `9.0.2` |
|
||||
|
||||
<br>
|
||||
|
||||
### v7.7.0
|
||||
|
||||
Upgraded outdated packages:
|
||||
|
||||
| Package | Version |
|
||||
| ---------------------------- | -------- |
|
||||
| electron | `26.2.2` |
|
||||
| @electron-forge | `6.4.2` |
|
||||
| @typescript-eslint | `6.7.3` |
|
||||
| eslint-plugin-import | `2.28.1` |
|
||||
| eslint-plugin-react | `7.33.2` |
|
||||
| eslint | `8.50.0` |
|
||||
| less | `4.2.0` |
|
||||
| sass | `1.68.0` |
|
||||
| typescript | `5.2.2` |
|
||||
| webpack | `5.88.2` |
|
||||
| react-refresh-webpack-plugin | `0.5.11` |
|
||||
|
||||
<br>
|
||||
|
||||
### v7.6.0
|
||||
|
||||
Upgraded outdated packages:
|
||||
|
||||
| Package | Version |
|
||||
| ------------------ | -------- |
|
||||
| electron | `25.2.0` |
|
||||
| @electron-forge | `6.2.1` |
|
||||
| @typescript-eslint | `6.0.0` |
|
||||
| eslint | `8.44.0` |
|
||||
| less-loader | `11.1.3` |
|
||||
| sass | `1.63.6` |
|
||||
| sass-loader | `13.3.2` |
|
||||
| ts-loader | `9.4.4` |
|
||||
| typescript | `5.1.6` |
|
||||
| webpack | `5.88.1` |
|
||||
|
||||
<br>
|
||||
|
||||
### v7.5.0
|
||||
|
||||
Upgraded outdated packages:
|
||||
|
||||
| Package | Version |
|
||||
| ------------------ | -------- |
|
||||
| electron | `25.0.1` |
|
||||
| @typescript-eslint | `5.59.9` |
|
||||
| css-loader | `6.8.1` |
|
||||
| eslint | `8.42.0` |
|
||||
| less-loader | `11.1.2` |
|
||||
| sass | `1.62.1` |
|
||||
| sass-loader | `13.3.1` |
|
||||
| style-loader | `3.3.3` |
|
||||
| ts-loader | `9.4.3` |
|
||||
| typescript | `5.1.3` |
|
||||
| webpack | `5.85.1` |
|
||||
|
||||
<br>
|
||||
|
||||
### v7.3.3
|
||||
|
||||
Upgraded outdated packages:
|
||||
|
||||
| Package | Version | |
|
||||
| ------------------ | -------- | --- |
|
||||
| electron | `24.1.2` | ⬆️ |
|
||||
| @electron-forge | `6.1.1` | ⬆️ |
|
||||
| @typescript-eslint | `5.59.0` | ⬆️ |
|
||||
| eslint | `8.39.0` | ⬆️ |
|
||||
| sass | `1.62.0` | ⬆️ |
|
||||
| sass-loader | `13.2.2` | ⬆️ |
|
||||
| typescript | `5.0.4` | ⬆️ |
|
||||
| webpack | `5.80.0` | ⬆️ |
|
||||
|
||||
<br>
|
||||
|
||||
### v7.3.2
|
||||
|
||||
Upgraded outdated packages:
|
||||
|
||||
| Package | Version | |
|
||||
| ------------------ | ---------- | --- |
|
||||
| electron | `23.2.0` | ⬆️ |
|
||||
| eslint | `8.36.0` | ⬆️ |
|
||||
| sass | `1.60.0` | ⬆️ |
|
||||
| sass-loader | `13.2.1` | ⬆️ |
|
||||
| style-loader | `3.3.2` | ⬆️ |
|
||||
| typescript | `5.0.2` | ⬆️ |
|
||||
| webpack | `5.76.3` | ⬆️ |
|
||||
| @types/node | `18.15.10` | ⬆️ |
|
||||
| @types/react | `18.0.29` | ⬆️ |
|
||||
| @types/react-dom | `18.0.11` | ⬆️ |
|
||||
| @typescript-eslint | `5.56.0` | ⬆️ |
|
||||
|
||||
<br>
|
||||
|
||||
### v7.3.1
|
||||
|
||||
Upgraded outdated packages:
|
||||
|
||||
| Package | Version | |
|
||||
| ------------------ | --------- | --- |
|
||||
| electron | `23.1.2` | ⬆️ |
|
||||
| eslint | `8.35.0` | ⬆️ |
|
||||
| sass | `1.58.3` | ⬆️ |
|
||||
| @types/node | `18.14.6` | ⬆️ |
|
||||
| @types/react | `18.0.28` | ⬆️ |
|
||||
| @types/react-dom | `18.0.11` | ⬆️ |
|
||||
| @typescript-eslint | `5.54.0` | ⬆️ |
|
||||
|
||||
<br>
|
||||
|
||||
### v7.3.0
|
||||
|
||||
- 🎉 Electron version upgraded `v23.0.0`
|
||||
- Upgraded outdated packages:
|
||||
- `electron` upgraded to `v23.0.0`
|
||||
- `@electron-forge` deps upgraded to `v6.0.5`
|
||||
- `@typescript-eslint` deps upgraded to `v5.51.0`
|
||||
- `css-loader` upgraded to `v6.7.3`
|
||||
- `eslint` upgraded to `v8.33.0`
|
||||
- `eslint-plugin-import` upgraded to `v2.27.5`
|
||||
- `eslint-plugin-react` upgraded to `v7.32.2`
|
||||
- `fork-ts-checker-webpack-plugin` upgraded to `v7.3.0`
|
||||
- `sass` upgraded to `v1.58.0`
|
||||
- `typescript` upgraded to `v4.9.5`
|
||||
|
||||
<br>
|
||||
|
||||
### v7.2.0
|
||||
|
||||
- 🎉 Electron version upgraded `v22.0.0`
|
||||
- Upgraded outdated packages:
|
||||
- `electron` upgraded to `v22.0.0`
|
||||
- `@electron-forge` deps upgraded to `v6.0.4`
|
||||
- `@pmmmwh/react-refresh-webpack-plugin` upgraded to `v0.5.10`
|
||||
- `@typescript-eslint` deps upgraded to `v5.46.0`
|
||||
- `css-loader` upgraded to `v6.7.2`
|
||||
- `eslint` upgraded to `v8.29.0`
|
||||
- `sass-loader` upgraded to `v13.2.0`
|
||||
- `ts-loader` upgraded to `v9.4.2`
|
||||
- `typescript` upgraded to `v4.9.4`
|
||||
- `webpack` upgraded to `v5.75.0`
|
||||
|
||||
<br>
|
||||
|
||||
### v7.1.0
|
||||
|
||||
- 🎉 Electron version upgraded to `v21.2.0`
|
||||
- Fixed Devtools Console warning message caused by content policy.
|
||||
- Upgraded forge config plugins format to support latest version.
|
||||
- Disabled `sandbox` by default in application window.
|
||||
- Upgraded outdated deps:
|
||||
- `electron` upgraded to `v21.2.0`
|
||||
- `@electron-forge` deps upgraded to `v6.0.0-beta.68`
|
||||
- `@pmmmwh/react-refresh-webpack-plugin` upgraded to `v0.5.8`
|
||||
- `@typescript-eslint` deps upgraded to `v5.41.0`
|
||||
- `classnames` upgraded to `v2.3.2`
|
||||
- `eslint` upgraded to `v8.26.0`
|
||||
- `eslint-plugin-react` upgraded to `v7.31.10`
|
||||
- `less-loader` upgraded to `v11.1.0`
|
||||
- `sass` upgraded to `v1.55.0`
|
||||
- `sass-loader` upgraded to `v13.1.0`
|
||||
- `ts-loader` upgraded to `v9.4.1`
|
||||
- `typescript` upgraded to `v4.8.4`
|
||||
|
||||
<br>
|
||||
|
||||
### v7.0.0
|
||||
|
||||
- 🥳 New layout for default application.
|
||||
- 🤖 Overhaul for dark/light themes with new colors.
|
||||
- Improved transition timing of title menus list.
|
||||
- Fixed native modules compiling issue with update to related webpack loader.
|
||||
- Updated forge `devContentSecurityPolicy` config for electron window.
|
||||
- Upgraded outdated deps:
|
||||
- `electron` upgraded to `v19.0.14`
|
||||
- `@electron-forge` deps upgraded to `v6.0.0-beta.65`
|
||||
- `@typescript-eslint` deps upgraded to `v5.36.1`
|
||||
- `eslint` upgraded to `v8.23.0`
|
||||
- `eslint-plugin-react` upgraded to `v7.30.1`
|
||||
- `sass` upgrded to `v1.54.0`
|
||||
- `typescript` upgraded to `v4.7.4`
|
||||
|
||||
<br>
|
||||
|
||||
### v6.2.0
|
||||
|
||||
- Upgraded outdated deps:
|
||||
- `electron` upgraded to `^19.0.9`.
|
||||
- `@typescript-eslint` deps upgraded to `v5.30.7`.
|
||||
- `eslint` upgraded to `v8.20.0"`.
|
||||
- `fork-ts-checker-webpack-plugin` upgraded to `v7.2.13`.
|
||||
- `sass` upgraded to `v1.54.0`.
|
||||
- `sass-loader` upgraded to `v13.0.2`.
|
||||
- `webpack` upgraded to `v5.74.0`.
|
||||
|
||||
<br>
|
||||
|
||||
### v6.1.0
|
||||
|
||||
- 🎉 Electron version upgraded to `v19.0.6`
|
||||
- Using `misc/window` for custom window without git submodule.
|
||||
- Upgraded outdated deps:
|
||||
- `electron` upgraded to `v19.0.6`
|
||||
- `@electron-forge` deps upgraded to `v6.0.0-beta.64`
|
||||
- `@pmmmwh/react-refresh-webpack-plugin` upgraded to `v0.5.7`
|
||||
- `@types` deps upgraded to latest version
|
||||
- `@typescript-eslint` deps upgraded to `v5.29.0`
|
||||
- `eslint` upgraded to `v8.18.0`
|
||||
- `eslint-plugin-react` upgraded to `v7.30.1`
|
||||
- `fork-ts-checker-webpack-plugin` upgraded to `v7.2.11`
|
||||
- `less` upgraded to `v4.1.3`
|
||||
- `less-loader` upgraded to `v11.0.0`
|
||||
- `react-refresh` upgraded to `v0.14.0`
|
||||
- `sass` upgraded to `v1.53.0`
|
||||
- `sass-loader` upgraded to `v13.0.1`
|
||||
- `ts-loader` upgraded to `v9.3.1`
|
||||
- `typescript` upgraded to `v4.7.4`
|
||||
- `webpack` upgraded to `5.73.0`
|
||||
|
||||
<br>
|
||||
|
||||
### v6.0.0
|
||||
|
||||
- 🙌🏻 New Layout for default application.
|
||||
- 🌑 Dark mode & 💡 Light Mode colors.
|
||||
- 🎉 Electron version upgraded to `v18.1.0`
|
||||
- Using `sass/scss` stylesheets by default for project (previously `less` was used).
|
||||
- Using `React Fast Refresh` for hot reloading, removed old `hot-loader`.
|
||||
- Titlebar Menus style overrides for improvements with rounded corners.
|
||||
- Created a new `Theme.scss` file for adjusting light/dark mode color schemes.
|
||||
- Persist theme state in `localStorage` by default.
|
||||
- Using `pnpm` instead of `yarn` as package manager for project.
|
||||
- Upgraded outdated deps:
|
||||
- `electron` upgraded to `v18.1.0`
|
||||
- `eslint` upgraded to `v8.13.0`
|
||||
- `typescript` upgraded to `v4.6.3`
|
||||
- `webpack` upgraded to `v5.72.0`
|
||||
- `react` deps upgraded to `v18.0.0`
|
||||
|
||||
<br>
|
||||
|
||||
### v5.5.0
|
||||
|
||||
- Upgraded outdated deps:
|
||||
- `electron` upgraded to `v17.2.0`
|
||||
- `eslint` ugpraded to `v8.11.0`,
|
||||
- `css-loader` upgraded to `v6.7.1`
|
||||
- `@typescript-eslint/eslint-plugin` deps upgraded to `v5.16.0`
|
||||
- `eslint-plugin-react` upgraded to `v7.29.4`
|
||||
- `ts-loader` upgraded to `v9.2.8`
|
||||
- `typescript` upgraded to `v4.6.3`
|
||||
- `webpack` upgraded to `v5.70.0`
|
||||
|
||||
<br>
|
||||
|
||||
### v5.4.0
|
||||
|
||||
- 🎉 Electron core upgraded `v17.0.1`
|
||||
- Upgraded outdated deps:
|
||||
- `@hot-loader/react-dom` upgraded to `v17.0.2`
|
||||
- `webpack` upgraded to `v5.69.1`
|
||||
- `typescript` upgraded to `v4.5.5`
|
||||
- `fork-ts-checker-webpack-plugin` upgraded to `v7.2.1`
|
||||
- `eslint` upgraded to `v8.9.0`
|
||||
- `css-loader` upgraded to `v6.6.0`
|
||||
- `@typescript-eslint` deps upgraded to `v5.12.1`
|
||||
|
||||
<br>
|
||||
|
||||
### v5.3.0
|
||||
|
||||
- Electron Window : File menu visible by default
|
||||
- Upgraded outdated deps:
|
||||
- `electron` upgraded to `v16.0.7`
|
||||
- `@electron-forge` deps upgraded to `v6.0.0-beta.63`
|
||||
- `@types/node` upgraded to `v17.0.8`
|
||||
- `@typescript-eslint` deps upgraded to `v5.9.1`
|
||||
- `eslint` upgraded to `v8.6.0`
|
||||
- `typescript` upgraded to `v4.5.4`
|
||||
- `webpack` upgraded to `v5.66.0`
|
||||
|
||||
<br>
|
||||
|
||||
### v5.2.0
|
||||
|
||||
- 🎉 Electron core upgraded `v16`
|
||||
- Upgraded outdated deps:
|
||||
- `@typescript-eslint` deps upgraded to `^5.5.0`
|
||||
- `eslint` upgraded to `^8.4.0`
|
||||
- `fork-ts-checker-webpack-plugin` upgraded to `^6.5.0`
|
||||
- `typescript` upgraded to `^4.5.2`
|
||||
- `webpack` upgraded to `^5.64.4`
|
||||
|
||||
<br>
|
||||
|
||||
### v5.1.0
|
||||
|
||||
- Fix: CSS/LESS `background-image` corrupted image file output.
|
||||
- Updated: Webpack Rules to load assets using [Webpack v5 Asset Modules](https://webpack.js.org/guides/asset-modules/) instead of `file-loader`
|
||||
- Fix: Typo in eslint alias map for `@components`
|
||||
- Updated: Window (submodule) to latest version.
|
||||
- Removed: Unused contextBridge api declaration.
|
||||
|
||||
<br>
|
||||
|
||||
### v5.0.0
|
||||
|
||||
- Overhauled: Application default layout and styling.
|
||||
- Overhauled: Project files structure to separate 'main' & 'renderer' modules.
|
||||
- Added: Custom Window Frame.
|
||||
- Added: Custom Window Titlebar.
|
||||
- Added: Custom Menus for Titlebar.
|
||||
- Added: Window controls for `windows` & `mac` based platform.
|
||||
- Renamed: `.eslintrc.json` to `.eslintrc`
|
||||
- Upgraded Outdated deps :
|
||||
- `eslint` upgraded to `v8.2.0`
|
||||
- `css-loader` upgraded to `v6.5.1`
|
||||
- `@typescript-eslint` deps upgraded to `v5.3.0`
|
||||
- `webpack` upgraded to `v5.62.1`
|
||||
|
||||
<br>
|
||||
|
||||
### v4.2.0
|
||||
|
||||
- 🎉 Electron core upgraded to version `v15`
|
||||
- Application colors updated for vue environment
|
||||
- Fix eslint script
|
||||
- Default window background color updated.
|
||||
- Upgrade outdated deps:
|
||||
- `electron` upgraded to `^15.0.0`
|
||||
- `@electron-forge` deps upgraded to `6.0.0-beta.61`
|
||||
- `@types/node` upgraded to `^16.9.6`
|
||||
- `@typescript-eslint` deps upgraded to `^4.31.2`
|
||||
- `css-loader` upgraded to `^6.3.0`
|
||||
|
||||
<br>
|
||||
|
||||
### v4.1.0
|
||||
|
||||
- 🎉 Electron core upgraded to version `v14`
|
||||
- Update application style properties
|
||||
- Enable `nativeWindowOpen` for main window
|
||||
- Remove `enableRemoteModule` from main window
|
||||
- Fix : Hot reloading issue caused by `liveReload` in webpack devServer
|
||||
- Added additional Webpack `devServer` configuration in `tools/forge/forge.config.js`
|
||||
- Upgraded outdated deps:
|
||||
- `@electron-forge` deps upgraded to `6.0.0-beta.60`
|
||||
- `@typescript-eslint` deps upgraded to `^4.30.0`
|
||||
- `@types/react` upgraded to `^17.0.19`
|
||||
- `electron` upgraded to `^14.0.0`
|
||||
- `eslint-plugin-import` upgraded to `^2.24.2`
|
||||
- `eslint-plugin-react` upgraded to `^7.25.1`
|
||||
- `typescript` upgraded to `^4.4.2`
|
||||
- `webpack` upgraded to `^5.51.1`
|
||||
|
||||
<br>
|
||||
|
||||
### v4.0.1
|
||||
|
||||
- Update file-loader configuration for `assets` files
|
||||
- Add packager configuration for app executable file details
|
||||
- Update `README` with similar useful projects
|
||||
|
||||
<br>
|
||||
|
||||
### v4.0.0
|
||||
|
||||
- Overhaul for Application default layout and styling.
|
||||
- Default window background color updated.
|
||||
- Default `minimal` stats output for main & renderer process via webpack.
|
||||
- Upgraded outdated deps :
|
||||
- `electron` upgraded to `^13.1.9`
|
||||
- `@electron-forge` packages upgraded to `6.0.0-beta.59`
|
||||
- `@typescript-eslint` packages upgraded to `^4.29.2`
|
||||
- `css-loader` upgraded to `^6.2.0`
|
||||
- `eslint` upgraded to `^7.32.0`
|
||||
- `fork-ts-checker-webpack-plugin` upgraded to `^6.3.2`
|
||||
- `less-loader` upgraded to `10.0.1`
|
||||
- `style-loader` upgraded to `^3.2.1`
|
||||
- `ts-loader` upgraded to `9.2.5`
|
||||
- `typescript` upgraded to `^4.3.5`
|
||||
- `webpack` upgraded to `^5.50.0`
|
||||
|
||||
<br>
|
||||
|
||||
### v3.1.0
|
||||
|
||||
- Electron core 🚀 upgraded to version 13.
|
||||
- Expose Webpack Ports settings in forge configuration.
|
||||
- Upgraded outdated packages :
|
||||
- `electron` upgraded to `^13.0.1`
|
||||
- `@typescript-eslint` packages upgraded to `^4.26.0`
|
||||
- `eslint` upgraded to `^7.27.0`
|
||||
- `css-loader` upgraded to `^5.2.6`
|
||||
- `ts-loader` upgraded to `8.3.0`
|
||||
- `typescript` upgraded to `^4.3.2`
|
||||
- `webpack` upgraded to `^5.38.1`
|
||||
- `fork-ts-checker-webpack-plugin` upgraded to `^6.2.10`
|
||||
|
||||
<br>
|
||||
|
||||
### v3.0.1
|
||||
|
||||
- Upgraded outdated packages
|
||||
- `electron'` upgraded to `^12.0.6`
|
||||
- `react` upgraded to `^17.0.2`
|
||||
- `react-dom` upgraded to `^17.0.2`
|
||||
- `css-loader` upgraded to `^5.2.4`
|
||||
- `eslint` upgraded to `^7.25.0`
|
||||
- `node-loader` upgraded to `2.0.0`
|
||||
- `ts-loader` upgraded to `8.2.0`
|
||||
- `typescript` upgraded to `^4.2.4`
|
||||
- `webpack` upgraded to `^5.36.2`
|
||||
|
||||
<br>
|
||||
|
||||
### v3.0.0
|
||||
|
||||
- Overhaul for Application component layout and styling.
|
||||
- Project Files structure updated.
|
||||
- Move static images to `assets` directory.
|
||||
- Remove `.prettierignore` file.
|
||||
- Use `.tsx` file extension for `preload` and `renderer` incase we need to use components.
|
||||
- Introduce new `assets` webpack alias.
|
||||
- Modify aliases usage for new project structure.
|
||||
- Upgraded outdated dependencies
|
||||
- `electron` upgraded to `12.0.1`
|
||||
- `css-loader` upgraded to `5.1.3`
|
||||
- `eslint` upgraded to `7.22.0`
|
||||
- `less` upgraded to `4.1.1`
|
||||
- `less-loader` upgraded to `7.3.0`
|
||||
- `ts-loader` upgraded to `8.0.18`
|
||||
- `typescript` upgraded to `4.2.3`
|
||||
- `webpack` upgraded to `5.27.1`
|
||||
|
||||
<br>
|
||||
|
||||
### v2.1.0
|
||||
|
||||
- New Year 2021 🎉🎊
|
||||
- Upgraded outdated dependencies
|
||||
- `electron` version upgraded to `11.1.1`
|
||||
- `react` version upgraded to `17.0.1`
|
||||
- `hot-loader` version upgraded to `17.0.1`
|
||||
- `webpack` version upgraded to `5.13.0`
|
||||
- `typescript` version upgraded to `4.1.3`
|
||||
- `ts-loader` version upgraded to `8.0.14`
|
||||
- `css-loader` version upgraded to `5.0.1`
|
||||
- `style-loader` version upgraded to `2.0.0`
|
||||
- `less` version upgraded to `4.1.0`
|
||||
|
||||
<br>
|
||||
|
||||
### v2.0.2
|
||||
|
||||
- Upgraded outdated dependencies
|
||||
- `electron` version upgraded to `10.x`
|
||||
- `typescript` version upgraded to `4.x`
|
||||
- `less-loader` version upgraded to `7.x`
|
||||
|
||||
<br>
|
||||
|
||||
### v2.0.1
|
||||
|
||||
- Upgraded outdated dependencies
|
||||
|
||||
<br>
|
||||
|
||||
### v2.0.0
|
||||
|
||||
- Added electron window background color
|
||||
- Devtools opening on startup is disabled
|
||||
- Added `preload` script usage (preload.ts) 👍
|
||||
- Moved webpack `aliases` to separate file
|
||||
- Added new style & color changes to boilerplate layout
|
||||
- Added prettier configuration files `.prettierrc` `.prettierignore`
|
||||
- `contextIsolation` is enabled by default
|
||||
- `nodeIntegration` `enableRemoteModule` `nodeIntegrationInWorker` `nodeIntegrationInSubFrames` are disabled default
|
||||
|
||||
<br>
|
||||
|
||||
### v1.0.0
|
||||
|
||||
- Upgrade package dependencies to latest
|
||||
- Add hot module replacement (live reload)
|
||||
- Add linting via ESLint
|
||||
- Custom webpack configuration
|
||||
- Custom forge configuration for package/bundle
|
||||
- Add aliases for project paths
|
||||
- Image loader to display images
|
||||
128
packages/kbot/extensions/gui/CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
Repository Discussions.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
19
packages/kbot/extensions/gui/CONTRIBUTING.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Contributing to ERWT
|
||||
|
||||
Thank you for investing your time in contributing to our project!
|
||||
|
||||
Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
|
||||
|
||||
<br>
|
||||
|
||||
## How to Contribute?
|
||||
|
||||
You can contribute to our project by providing `features/bugfixes/improvements` related Pull Requests.
|
||||
<br>
|
||||
Just make sure to test all the changes you provide before submission anything into this project.
|
||||
|
||||
<br>
|
||||
|
||||
## Having a question about this project?
|
||||
|
||||
Feel free to use [Discussions](https://github.com/codesbiome/electron-react-webpack-typescript-2022/discussions) to ask any questions related to this project.
|
||||
21
packages/kbot/extensions/gui/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Codesbiome
|
||||
|
||||
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.
|
||||
177
packages/kbot/extensions/gui/README.md
Normal file
@ -0,0 +1,177 @@
|
||||
# Electron React Webpack Typescript (Custom Titlebar)
|
||||
|
||||
A prebuilt project for creating desktop apps using Electron, React, Webpack & Typescript with hot-reload, easy to use custom import aliases & executable builds for distribution.
|
||||
|
||||
<br>
|
||||
<img src="assets/images/anim_v8.gif" />
|
||||
<br>
|
||||
|
||||
Special thanks to [@guasam](https://github.com/guasam) for development of Custom Window, Titlebar, UI/UX etc.
|
||||
|
||||
<br>
|
||||
|
||||
## Core Features
|
||||
|
||||
- 🌟 Electron
|
||||
- 🌀 TypeScript
|
||||
- ⚛️ React
|
||||
- 🥗 SASS/SCSS Loader
|
||||
- 🎨 CSS Loader
|
||||
- 📸 Image Loader
|
||||
- 🆎 Font Loader
|
||||
- 🧹 ESLint
|
||||
- 📦 Electron Forge
|
||||
- 📐 Custom Window Frame
|
||||
- 📐 Custom Window Titlebar
|
||||
- 📐 Custom Window Menubar
|
||||
- 🔱 Webpack & Configuration
|
||||
- 🧩 Aliases for Project Paths
|
||||
- 🗡️ Native (node) Modules Support
|
||||
- 🔥 React Fast Refresh + Webpack HMR
|
||||
- 🌞 Dark Mode + Light Mode (Theme)
|
||||
- 🎁 Package Bundling (Distribution / Release)
|
||||
|
||||
<br>
|
||||
|
||||
## Custom Electron Window Titlebar & Menus
|
||||
|
||||
This project includes [electron-window](https://github.com/guasam/electron-window) as core of custom window components and modules.
|
||||
|
||||
**Following are the list of features it provides :**
|
||||
|
||||
- Custom Titlebar for Electron Window.
|
||||
- Easily changable platform specific controls for max/min/close buttons using `windows` or `mac` value for `platform` property with `<WindowFrame>` in renderer.
|
||||
- Titlebar menus can show/hide by pressing `alt` or `option` key.
|
||||
- Window frame `title` prop displays in titlebar center when menus are toggeled off.
|
||||
- Menu entries can be customized in `src/main/window/titlebarMenus.ts` file.
|
||||
- Menu items and windows controls UI or colors can be customized easily by modifying the `src/renderer/window` components & styles.
|
||||
|
||||
<br>
|
||||
|
||||
### Custom Aliases for Paths
|
||||
|
||||
We can use predefined aliases for `import` paths already used in this project. Following are the details:
|
||||
|
||||
| Alias | Target Path |
|
||||
| ------------- | -------------------------- |
|
||||
| `@assets` | `/assets` |
|
||||
| `@main` | `/src/main` |
|
||||
| `@renderer` | `/src/renderer` |
|
||||
| `@common` | `/src/common` |
|
||||
| `@src` | `/src` |
|
||||
| `@styles` | `/src/renderer/styles` |
|
||||
| `@components` | `/src/renderer/components` |
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
### Want to use Vite instead of Webpack bundler?
|
||||
|
||||
Introducing the [ElectroVite](https://github.com/guasam/electrovite-react) project with a brief description below.
|
||||
|
||||
<br>
|
||||
|
||||
## Installation
|
||||
|
||||

|
||||
|
||||
Main version of this project contains files structure in separate context for `main` and `renderer`, with custom electron window, titlebar etc.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/codesbiome/electron-react-webpack-typescript-2024
|
||||
```
|
||||
|
||||
<br>
|
||||
<div align="center">
|
||||
<b>OR</b>
|
||||
</div>
|
||||
<br>
|
||||
|
||||

|
||||
|
||||
Minimal version of ERWT contains very simple project files structure, no custom window, no custom titlebar & menus.
|
||||
|
||||
```bash
|
||||
git clone -b minimal https://github.com/codesbiome/electron-react-webpack-typescript-2024
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
Install dependencies using [pnpm](https://pnpm.io/) or [yarn](https://www.npmjs.com/package/yarn) or [npm](https://www.npmjs.com/) :
|
||||
|
||||
```bash
|
||||
# using pnpm
|
||||
pnpm install
|
||||
|
||||
# or using yarn
|
||||
yarn install
|
||||
|
||||
# or using npm
|
||||
npm install
|
||||
```
|
||||
|
||||
<br />
|
||||
|
||||
## Start : Development
|
||||
|
||||
To develop and run your application, you need to run following command.
|
||||
<br />
|
||||
Start electron application for development :
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
<br />
|
||||
|
||||
## Lint : Development
|
||||
|
||||
To lint application source code using ESLint via this command :
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
<br />
|
||||
|
||||
## Package : Production
|
||||
|
||||
Customize and package your Electron app with OS-specific bundles (.app, .exe etc)
|
||||
|
||||
```bash
|
||||
yarn package
|
||||
```
|
||||
|
||||
<br />
|
||||
|
||||
## Make : Production
|
||||
|
||||
Making is a way of taking your packaged application and making platform specific distributables like DMG, EXE, or Flatpak files (amongst others).
|
||||
|
||||
```bash
|
||||
yarn make
|
||||
```
|
||||
|
||||
<br />
|
||||
|
||||
## Publish : Production
|
||||
|
||||
Publishing is a way of taking the artifacts generated by the `make` command and sending them to a service somewhere for you to distribute or use as updates. (This could be your update server or an S3 bucket)
|
||||
|
||||
```bash
|
||||
yarn publish
|
||||
```
|
||||
|
||||
<br />
|
||||
|
||||
## Packager & Makers Configuration
|
||||
|
||||
This provides an easy way of configuring your packaged application and making platform specific distributables like DMG, EXE, or Flatpak files.
|
||||
|
||||
This configurations file is available in :
|
||||
|
||||
```bash
|
||||
tools/forge/forge.config.js
|
||||
```
|
||||
|
||||
For further information, you can visit [Electron Forge Configuration](https://www.electronforge.io/configuration)
|
||||
3
packages/kbot/extensions/gui/assets/icons/LICENSE
Normal file
@ -0,0 +1,3 @@
|
||||
# Attribution
|
||||
|
||||
<a href="https://www.flaticon.com/free-icons/license" title="license icons">Thanks to Flaticon</a>
|
||||
BIN
packages/kbot/extensions/gui/assets/icons/chrome.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
packages/kbot/extensions/gui/assets/icons/electron.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
packages/kbot/extensions/gui/assets/icons/erwt.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
packages/kbot/extensions/gui/assets/icons/license.png
Normal file
|
After Width: | Height: | Size: 1020 B |
BIN
packages/kbot/extensions/gui/assets/icons/nodejs.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
packages/kbot/extensions/gui/assets/icons/react.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
packages/kbot/extensions/gui/assets/icons/typescript.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
packages/kbot/extensions/gui/assets/icons/webpack.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
packages/kbot/extensions/gui/assets/images/anim_v8.gif
Normal file
|
After Width: | Height: | Size: 266 KiB |
BIN
packages/kbot/extensions/gui/assets/images/appIcon.ico
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
packages/kbot/extensions/gui/assets/images/logo.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
180
packages/kbot/extensions/gui/assets/schema.json
Normal file
122
packages/kbot/extensions/gui/assets/schema_ui.json
Normal file
18
packages/kbot/extensions/gui/eslint.config.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "plugin:react/recommended"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "latest"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"react/prop-types": "off",
|
||||
"@typescript-eslint/no-var-requires": "off"
|
||||
}
|
||||
}
|
||||
90
packages/kbot/extensions/gui/package.json
Normal file
@ -0,0 +1,90 @@
|
||||
{
|
||||
"name": "erwt",
|
||||
"productName": "ERWT",
|
||||
"version": "8.1.0",
|
||||
"description": "Robust project for developing Desktop Application with Electron, React, Webpack & TypeScript.",
|
||||
"main": ".webpack/main",
|
||||
"scripts": {
|
||||
"start": "cross-env NODE_ENV=development electron-forge start",
|
||||
"package": "electron-forge package",
|
||||
"make": "electron-forge make",
|
||||
"publish": "electron-forge publish",
|
||||
"lint": "eslint src/ --ext .ts,.js,.tsx,.jsx"
|
||||
},
|
||||
"keywords": [
|
||||
"electron boilerplate",
|
||||
"minimal",
|
||||
"electron-webpack",
|
||||
"electron-react",
|
||||
"electron-typescript",
|
||||
"hmr",
|
||||
"boilerplate",
|
||||
"2024",
|
||||
"ERWT"
|
||||
],
|
||||
"author": {
|
||||
"name": "codesbiome",
|
||||
"url": "https://github.com/codesbiome"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "guasam",
|
||||
"url": "https://github.com/guasam"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codesbiome/electron-react-webpack-typescript-2024"
|
||||
},
|
||||
"license": "MIT",
|
||||
"config": {
|
||||
"forge": "./tools/forge/forge.config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "7.4.0",
|
||||
"@electron-forge/maker-deb": "7.4.0",
|
||||
"@electron-forge/maker-rpm": "7.4.0",
|
||||
"@electron-forge/maker-squirrel": "7.4.0",
|
||||
"@electron-forge/maker-zip": "7.4.0",
|
||||
"@electron-forge/plugin-webpack": "7.4.0",
|
||||
"@marshallofsound/webpack-asset-relocator-loader": "^0.5.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
|
||||
"@types/node": "^20.14.11",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/webpack-env": "^1.18.5",
|
||||
"@typescript-eslint/eslint-plugin": "^7.16.1",
|
||||
"@typescript-eslint/parser": "^7.16.1",
|
||||
"@vercel/webpack-asset-relocator-loader": "1.7.3",
|
||||
"classnames": "^2.5.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^7.1.2",
|
||||
"electron": "^31.2.1",
|
||||
"eslint": "^9.7.0",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-react": "^7.34.4",
|
||||
"file-loader": "^6.2.0",
|
||||
"fork-ts-checker-webpack-plugin": "^9.0.2",
|
||||
"json-loader": "^0.5.7",
|
||||
"node-loader": "^2.0.0",
|
||||
"react-refresh": "^0.14.2",
|
||||
"sass": "^1.77.8",
|
||||
"sass-loader": "^14.2.1",
|
||||
"style-loader": "^4.0.0",
|
||||
"ts-loader": "9.5.1",
|
||||
"typescript": "^5.5.3",
|
||||
"webpack": "^5.93.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@plastichub/fs": "^0.13.41",
|
||||
"@plastichub/osr-commons": "^0.5.2",
|
||||
"@rjsf/core": "^5.24.1",
|
||||
"@rjsf/mui": "^5.24.1",
|
||||
"@rjsf/utils": "^5.24.1",
|
||||
"@rjsf/validator-ajv8": "^5.24.1",
|
||||
"electron-squirrel-startup": "^1.0.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
}
|
||||
}
|
||||
9172
packages/kbot/extensions/gui/pnpm-lock.yaml
Normal file
48
packages/kbot/extensions/gui/src/main/app.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { app, BrowserWindow } from 'electron';
|
||||
import { createAppWindow } from './appWindow';
|
||||
|
||||
/** Handle creating/removing shortcuts on Windows when installing/uninstalling. */
|
||||
if (require('electron-squirrel-startup')) {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be called when Electron has finished
|
||||
* initialization and is ready to create browser windows.
|
||||
* Some APIs can only be used after this event occurs.
|
||||
*/
|
||||
app.on('ready', createAppWindow);
|
||||
|
||||
/**
|
||||
* Emitted when the application is activated. Various actions can
|
||||
* trigger this event, such as launching the application for the first time,
|
||||
* attempting to re-launch the application when it's already running,
|
||||
* or clicking on the application's dock or taskbar icon.
|
||||
*/
|
||||
app.on('activate', () => {
|
||||
/**
|
||||
* On OS X it's common to re-create a window in the app when the
|
||||
* dock icon is clicked and there are no other windows open.
|
||||
*/
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createAppWindow();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Emitted when all windows have been closed.
|
||||
*/
|
||||
app.on('window-all-closed', () => {
|
||||
/**
|
||||
* On OS X it is common for applications and their menu bar
|
||||
* to stay active until the user quits explicitly with Cmd + Q
|
||||
*/
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* In this file you can include the rest of your app's specific main process code.
|
||||
* You can also put them in separate files and import them here.
|
||||
*/
|
||||
63
packages/kbot/extensions/gui/src/main/appWindow.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { app, BrowserWindow } from 'electron';
|
||||
import path from 'path';
|
||||
import { registerTitlebarIpc } from '@main/window/titlebarIpc';
|
||||
|
||||
// Electron Forge automatically creates these entry points
|
||||
declare const APP_WINDOW_WEBPACK_ENTRY: string;
|
||||
declare const APP_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
|
||||
|
||||
let appWindow: BrowserWindow;
|
||||
|
||||
/**
|
||||
* Create Application Window
|
||||
* @returns {BrowserWindow} Application Window Instance
|
||||
*/
|
||||
export function createAppWindow(): BrowserWindow {
|
||||
// Create new window instance
|
||||
appWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
backgroundColor: '#202020',
|
||||
show: false,
|
||||
autoHideMenuBar: true,
|
||||
frame: false,
|
||||
titleBarStyle: 'hidden',
|
||||
icon: path.resolve('assets/images/appIcon.ico'),
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
nodeIntegrationInWorker: false,
|
||||
nodeIntegrationInSubFrames: false,
|
||||
preload: APP_WINDOW_PRELOAD_WEBPACK_ENTRY,
|
||||
sandbox: false,
|
||||
},
|
||||
});
|
||||
|
||||
// Load the index.html of the app window.
|
||||
appWindow.loadURL(APP_WINDOW_WEBPACK_ENTRY);
|
||||
|
||||
// Show window when its ready to
|
||||
appWindow.on('ready-to-show', () => appWindow.show());
|
||||
|
||||
// Register Inter Process Communication for main process
|
||||
registerMainIPC();
|
||||
|
||||
// Close all windows when main window is closed
|
||||
appWindow.on('close', () => {
|
||||
appWindow = null;
|
||||
app.quit();
|
||||
});
|
||||
|
||||
return appWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Inter Process Communication
|
||||
*/
|
||||
function registerMainIPC() {
|
||||
/**
|
||||
* Here you can assign IPC related codes for the application window
|
||||
* to Communicate asynchronously from the main process to renderer processes.
|
||||
*/
|
||||
registerTitlebarIpc(appWindow);
|
||||
}
|
||||
16
packages/kbot/extensions/gui/src/main/window/LICENSE
Normal file
@ -0,0 +1,16 @@
|
||||
Copyright (c) 2021-2022 Guasam
|
||||
|
||||
This software is provided "as-is", without any express or implied warranty. In no event
|
||||
will the authors be held liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial
|
||||
applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you
|
||||
wrote the original software. If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||
as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright (c) 2021, Guasam
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
* Read the LICENSE file for more details.
|
||||
*
|
||||
* @author : guasam
|
||||
* @project : Electron Window
|
||||
* @package : Titlebar IPC (Renderer Process)
|
||||
*/
|
||||
|
||||
import { ipcRenderer } from 'electron';
|
||||
|
||||
const titlebarContext = {
|
||||
exit() {
|
||||
ipcRenderer.invoke('window-close');
|
||||
},
|
||||
undo() {
|
||||
ipcRenderer.invoke('web-undo');
|
||||
},
|
||||
redo() {
|
||||
ipcRenderer.invoke('web-redo');
|
||||
},
|
||||
cut() {
|
||||
ipcRenderer.invoke('web-cut');
|
||||
},
|
||||
copy() {
|
||||
ipcRenderer.invoke('web-copy');
|
||||
},
|
||||
paste() {
|
||||
ipcRenderer.invoke('web-paste');
|
||||
},
|
||||
delete() {
|
||||
ipcRenderer.invoke('web-delete');
|
||||
},
|
||||
select_all() {
|
||||
ipcRenderer.invoke('web-select-all');
|
||||
},
|
||||
reload() {
|
||||
ipcRenderer.invoke('web-reload');
|
||||
},
|
||||
force_reload() {
|
||||
ipcRenderer.invoke('web-force-reload');
|
||||
},
|
||||
toggle_devtools() {
|
||||
ipcRenderer.invoke('web-toggle-devtools');
|
||||
},
|
||||
actual_size() {
|
||||
ipcRenderer.invoke('web-actual-size');
|
||||
},
|
||||
zoom_in() {
|
||||
ipcRenderer.invoke('web-zoom-in');
|
||||
},
|
||||
zoom_out() {
|
||||
ipcRenderer.invoke('web-zoom-out');
|
||||
},
|
||||
toggle_fullscreen() {
|
||||
ipcRenderer.invoke('web-toggle-fullscreen');
|
||||
},
|
||||
minimize() {
|
||||
ipcRenderer.invoke('window-minimize');
|
||||
},
|
||||
toggle_maximize() {
|
||||
ipcRenderer.invoke('window-toggle-maximize');
|
||||
},
|
||||
open_url(url: string) {
|
||||
ipcRenderer.invoke('open-url', url);
|
||||
},
|
||||
};
|
||||
|
||||
export type TitlebarContextApi = typeof titlebarContext;
|
||||
|
||||
export default titlebarContext;
|
||||
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) 2021, Guasam
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
* Read the LICENSE file for more details.
|
||||
*
|
||||
* @author : guasam
|
||||
* @project : Electron Window
|
||||
* @package : Titlebar Context API
|
||||
*/
|
||||
|
||||
import { TitlebarContextApi } from './titlebarContext';
|
||||
|
||||
const context: TitlebarContextApi = (window as any).electron_window?.titlebar;
|
||||
|
||||
export default context;
|
||||
95
packages/kbot/extensions/gui/src/main/window/titlebarIpc.ts
Normal file
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright (c) 2021, Guasam
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
* Read the LICENSE file for more details.
|
||||
*
|
||||
* @author : guasam
|
||||
* @project : Electron Window
|
||||
* @package : Titlebar IPC (Main Process)
|
||||
*/
|
||||
|
||||
import { BrowserWindow, ipcMain, shell } from 'electron';
|
||||
|
||||
export const registerTitlebarIpc = (mainWindow: BrowserWindow) => {
|
||||
ipcMain.handle('window-minimize', () => {
|
||||
mainWindow.minimize();
|
||||
});
|
||||
|
||||
ipcMain.handle('window-maximize', () => {
|
||||
mainWindow.maximize();
|
||||
});
|
||||
|
||||
ipcMain.handle('window-toggle-maximize', () => {
|
||||
if (mainWindow.isMaximized()) {
|
||||
mainWindow.unmaximize();
|
||||
} else {
|
||||
mainWindow.maximize();
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('window-close', () => {
|
||||
mainWindow.close();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-undo', () => {
|
||||
mainWindow.webContents.undo();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-redo', () => {
|
||||
mainWindow.webContents.redo();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-cut', () => {
|
||||
mainWindow.webContents.cut();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-copy', () => {
|
||||
mainWindow.webContents.copy();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-paste', () => {
|
||||
mainWindow.webContents.paste();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-delete', () => {
|
||||
mainWindow.webContents.delete();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-select-all', () => {
|
||||
mainWindow.webContents.selectAll();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-reload', () => {
|
||||
mainWindow.webContents.reload();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-force-reload', () => {
|
||||
mainWindow.webContents.reloadIgnoringCache();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-toggle-devtools', () => {
|
||||
mainWindow.webContents.toggleDevTools();
|
||||
});
|
||||
|
||||
ipcMain.handle('web-actual-size', () => {
|
||||
mainWindow.webContents.setZoomLevel(0);
|
||||
});
|
||||
|
||||
ipcMain.handle('web-zoom-in', () => {
|
||||
mainWindow.webContents.setZoomLevel(mainWindow.webContents.zoomLevel + 0.5);
|
||||
});
|
||||
|
||||
ipcMain.handle('web-zoom-out', () => {
|
||||
mainWindow.webContents.setZoomLevel(mainWindow.webContents.zoomLevel - 0.5);
|
||||
});
|
||||
|
||||
ipcMain.handle('web-toggle-fullscreen', () => {
|
||||
mainWindow.setFullScreen(!mainWindow.fullScreen);
|
||||
});
|
||||
|
||||
ipcMain.handle('open-url', (e, url) => {
|
||||
shell.openExternal(url);
|
||||
});
|
||||
};
|
||||
160
packages/kbot/extensions/gui/src/main/window/titlebarMenus.ts
Normal file
@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Copyright (c) 2021, Guasam
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
* Read the LICENSE file for more details.
|
||||
*
|
||||
* @author : guasam
|
||||
* @project : Electron Window
|
||||
* @package : Titlebar Menu Items
|
||||
*/
|
||||
|
||||
export type TitlebarMenuItem = {
|
||||
name: string;
|
||||
action?: string;
|
||||
shortcut?: string;
|
||||
value?: string | number;
|
||||
items?: TitlebarMenuItem[];
|
||||
};
|
||||
|
||||
export type TitlebarMenu = {
|
||||
name: string;
|
||||
items: TitlebarMenuItem[];
|
||||
};
|
||||
|
||||
const titlebarMenus: TitlebarMenu[] = [
|
||||
{
|
||||
name: 'File',
|
||||
items: [
|
||||
{
|
||||
name: 'Exit',
|
||||
action: 'exit',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Edit',
|
||||
items: [
|
||||
{
|
||||
name: 'Undo',
|
||||
action: 'undo',
|
||||
shortcut: 'Ctrl+Z',
|
||||
},
|
||||
{
|
||||
name: 'Redo',
|
||||
action: 'redo',
|
||||
shortcut: 'Ctrl+Y',
|
||||
},
|
||||
{
|
||||
name: '__',
|
||||
},
|
||||
{
|
||||
name: 'Cut',
|
||||
action: 'cut',
|
||||
shortcut: 'Ctrl+X',
|
||||
},
|
||||
{
|
||||
name: 'Copy',
|
||||
action: 'copy',
|
||||
shortcut: 'Ctrl+C',
|
||||
},
|
||||
{
|
||||
name: 'Paste',
|
||||
action: 'paste',
|
||||
shortcut: 'Ctrl+V',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
action: 'delete',
|
||||
},
|
||||
{
|
||||
name: '__',
|
||||
},
|
||||
{
|
||||
name: 'Select All',
|
||||
action: 'select_all',
|
||||
shortcut: 'Ctrl+A',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'View',
|
||||
items: [
|
||||
{
|
||||
name: 'Reload',
|
||||
action: 'reload',
|
||||
shortcut: 'Ctrl+R',
|
||||
},
|
||||
{
|
||||
name: 'Force Reload',
|
||||
action: 'force_reload',
|
||||
shortcut: 'Ctrl+Shift+R',
|
||||
},
|
||||
{
|
||||
name: 'Toogle Developer Tools',
|
||||
action: 'toggle_devtools',
|
||||
shortcut: 'Ctrl+Shift+I',
|
||||
},
|
||||
{
|
||||
name: '__',
|
||||
},
|
||||
{
|
||||
name: 'Actual Size',
|
||||
action: 'actual_size',
|
||||
shortcut: 'Ctrl+0',
|
||||
},
|
||||
{
|
||||
name: 'Zoom In',
|
||||
action: 'zoom_in',
|
||||
shortcut: 'Ctrl++',
|
||||
},
|
||||
{
|
||||
name: 'Zoom Out',
|
||||
action: 'zoom_out',
|
||||
shortcut: 'Ctrl+-',
|
||||
},
|
||||
{
|
||||
name: '__',
|
||||
},
|
||||
{
|
||||
name: 'Toggle Fullscreen',
|
||||
action: 'toggle_fullscreen',
|
||||
shortcut: 'F11',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Window',
|
||||
items: [
|
||||
{
|
||||
name: 'Maximize',
|
||||
action: 'toggle_maximize',
|
||||
shortcut: 'Toggle'
|
||||
},
|
||||
{
|
||||
name: 'Minimize',
|
||||
action: 'minimize',
|
||||
shortcut: 'Ctrl+M',
|
||||
},
|
||||
{
|
||||
name: 'Close',
|
||||
action: 'exit',
|
||||
shortcut: 'Ctrl+W',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Credits',
|
||||
items: [
|
||||
{
|
||||
name: 'Guasam',
|
||||
action: 'open_url',
|
||||
value: 'https://github.com/guasam',
|
||||
shortcut: '@guasam',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default titlebarMenus;
|
||||
@ -0,0 +1,6 @@
|
||||
import { contextBridge } from 'electron';
|
||||
import titlebarContext from './titlebarContext';
|
||||
|
||||
contextBridge.exposeInMainWorld('electron_window', {
|
||||
titlebar: titlebarContext,
|
||||
});
|
||||
10
packages/kbot/extensions/gui/src/renderer/app.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>ERWT Boilerplate</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
35
packages/kbot/extensions/gui/src/renderer/appPreload.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import '@main/window/windowPreload';
|
||||
|
||||
// Say something
|
||||
console.log('[ERWT] : Preload execution started');
|
||||
|
||||
// Get versions
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const app = document.getElementById('app');
|
||||
const { env } = process;
|
||||
const versions: Record<string, unknown> = {};
|
||||
|
||||
// ERWT Package version
|
||||
versions['erwt'] = env['npm_package_version'];
|
||||
versions['license'] = env['npm_package_license'];
|
||||
|
||||
// Process versions
|
||||
for (const type of ['chrome', 'node', 'electron']) {
|
||||
versions[type] = process.versions[type].replace('+', '');
|
||||
}
|
||||
|
||||
// NPM deps versions
|
||||
for (const type of ['react']) {
|
||||
const v = env['npm_package_dependencies_' + type];
|
||||
if (v) versions[type] = v.replace('^', '');
|
||||
}
|
||||
|
||||
// NPM @dev deps versions
|
||||
for (const type of ['webpack', 'typescript']) {
|
||||
const v = env['npm_package_devDependencies_' + type];
|
||||
if (v) versions[type] = v.replace('^', '');
|
||||
}
|
||||
|
||||
// Set versions to app data
|
||||
app.setAttribute('data-versions', JSON.stringify(versions));
|
||||
});
|
||||
17
packages/kbot/extensions/gui/src/renderer/appRenderer.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import WindowFrame from '@renderer/window/WindowFrame';
|
||||
import Application from '@components/Application';
|
||||
|
||||
// Say something
|
||||
console.log('[ERWT] : Renderer execution started');
|
||||
|
||||
// Application to Render
|
||||
const app = (
|
||||
<WindowFrame title='ERWT Boilerplate' platform='windows'>
|
||||
<Application />
|
||||
</WindowFrame>
|
||||
);
|
||||
|
||||
// Render application in DOM
|
||||
createRoot(document.getElementById('app')).render(app);
|
||||
@ -0,0 +1,19 @@
|
||||
import chrome from '@assets/icons/chrome.png';
|
||||
import react from '@assets/icons/react.png';
|
||||
import typescript from '@assets/icons/typescript.png';
|
||||
import erwt from '@assets/icons/erwt.png';
|
||||
import electron from '@assets/icons/electron.png';
|
||||
import nodejs from '@assets/icons/nodejs.png';
|
||||
import webpack from '@assets/icons/webpack.png';
|
||||
import license from '@assets/icons/license.png';
|
||||
|
||||
export default {
|
||||
chrome,
|
||||
react,
|
||||
typescript,
|
||||
erwt,
|
||||
electron,
|
||||
nodejs,
|
||||
webpack,
|
||||
license,
|
||||
};
|
||||
358
packages/kbot/extensions/gui/src/renderer/styles/app.scss
Normal file
@ -0,0 +1,358 @@
|
||||
/**
|
||||
* Licensed under the MIT License. See LICENSE file in the project root for license information.
|
||||
* Copyright (c) 2022 Codesbiome, guasam
|
||||
*
|
||||
* @author : guasam
|
||||
* @project : ERWT Boilerplate
|
||||
* @package : Application Sass Stylesheet
|
||||
*/
|
||||
|
||||
@import './dark_theme.scss';
|
||||
@import './light_theme.scss';
|
||||
|
||||
/**
|
||||
*==========================================================================
|
||||
* Application Specific Stylesheet
|
||||
*==========================================================================
|
||||
*
|
||||
* Here we use the codes to apply application specific style
|
||||
*/
|
||||
|
||||
::selection {
|
||||
background: var(--selection-bgcolor);
|
||||
color: var(--selection-color);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: var(--scroll-width);
|
||||
|
||||
&-track {
|
||||
background: var(--scroll-track-bgcolor);
|
||||
}
|
||||
|
||||
&-thumb {
|
||||
background: var(--scroll-thumb-bgcolor);
|
||||
}
|
||||
|
||||
&-thumb:hover {
|
||||
background: var(--scroll-thumb-hover-bgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-size: var(--app-font-size);
|
||||
font-family: var(--app-font-family);
|
||||
color: var(--app-color);
|
||||
background: var(--app-bgcolor);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* Grid texture */
|
||||
body {
|
||||
background-size: 32px 32px;
|
||||
background-image:
|
||||
linear-gradient(to right, #7070700d 1px, transparent 1px),
|
||||
linear-gradient(to bottom, #7070700d 1px, transparent 1px);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
|
||||
&.has-border {
|
||||
border: var(--app-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
background: var(--button-bgcolor);
|
||||
color: var(--button-color);
|
||||
font-weight: normal;
|
||||
text-shadow: 0px 1px var(--button-shadow-color);
|
||||
font-family: var(--app-font-family);
|
||||
border: var(--button-border);
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 6px;
|
||||
font-size: 0.875rem;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
outline: none;
|
||||
min-width: 140px;
|
||||
|
||||
&:hover {
|
||||
background: var(--button-hover-bgcolor);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: var(--button-active-bgcolor);
|
||||
}
|
||||
|
||||
&>span {
|
||||
color: var(--button-badge-color);
|
||||
background-color: var(--button-badge-bgcolor);
|
||||
font-size: 12px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: none;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 22px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.rotate {
|
||||
animation: rotate 4.5s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.main-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
img {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 400;
|
||||
color: var(--erwt-heading-color);
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-teaser {
|
||||
position: relative;
|
||||
display: flex;
|
||||
line-height: 25px;
|
||||
font-size: 14px;
|
||||
color: #d8d8d894;
|
||||
width: 60%;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 3rem;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
padding-right: 1rem;
|
||||
border-radius: 0 0 8px 8px;
|
||||
box-shadow: 0 8px 10px 0px rgba(0, 0, 0, 0.01);
|
||||
}
|
||||
|
||||
.main-teaser:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: calc(100% + 40px);
|
||||
height: 1px;
|
||||
background: var(--app-accent-color);
|
||||
left: -20px;
|
||||
box-shadow: 0 10px 20px 1px rgb(0 0 0 / 85%);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.versions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 20px inset rgb(0 0 0 / 3%);
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.versions .item {
|
||||
background: #0000003b;
|
||||
color: #d1d1d1;
|
||||
width: calc(50% - 1rem);
|
||||
padding: 6px 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
|
||||
&>* {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 10px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&>span {
|
||||
color: gray;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
#erwt {
|
||||
// user-select: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
background: var(--erwt-gradient);
|
||||
|
||||
.header {
|
||||
padding: 4rem 2rem 0rem 2rem;
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 2rem;
|
||||
background: var(--app-footer-bgColor);
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*==========================================================================
|
||||
* Titlebar Overrides for different themes
|
||||
*==========================================================================
|
||||
*/
|
||||
|
||||
.window-titlebar {
|
||||
background: var(--titlebar-bgcolor);
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
&-icon {
|
||||
min-height: 33px;
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.window-title {
|
||||
color: var(--titlebar-title-color);
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
&.active .menu-title {
|
||||
background: var(--titlebar-menu-title-active-bgcolor);
|
||||
box-shadow: var(--titlebar-menu-title-shadow);
|
||||
color: var(--titlebar-color);
|
||||
border-color: var(--titlebar-menu-title-active-border-color);
|
||||
border-radius: 4px 4px 0 0;
|
||||
border-top-color: var(--app-accent-color);
|
||||
}
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
font-weight: normal;
|
||||
text-shadow: none;
|
||||
color: var(--titlebar-color);
|
||||
border-color: transparent;
|
||||
border-width: 1px 1px 0 1px;
|
||||
border-style: solid;
|
||||
padding: 2px 8px;
|
||||
margin-right: 2px;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--titlebar-menu-title-hover-bgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
.menu-popup {
|
||||
display: none;
|
||||
position: fixed;
|
||||
background-color: var(--titlebar-popup-bgcolor);
|
||||
min-width: 70px;
|
||||
border: var(--titlebar-popup-border);
|
||||
border-top: 0;
|
||||
padding: 0.25rem 0;
|
||||
box-shadow: 4px 10px 10px #0000002e;
|
||||
z-index: 10000;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
|
||||
&-item {
|
||||
padding: 0.3125rem 1rem;
|
||||
|
||||
&:hover {
|
||||
background: var(--titlebar-popup-item-hover-bgcolor);
|
||||
|
||||
.popup-item-shortcut {
|
||||
color: var(--titlebar-popup-item-hover-shortcut-color);
|
||||
}
|
||||
|
||||
.popup-item-name {
|
||||
color: var(--titlebar-popup-item-hover-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup-item-separator {
|
||||
background: var(--titlebar-menu-separator-bgcolor);
|
||||
}
|
||||
|
||||
.popup-item-name {
|
||||
padding-right: 2rem;
|
||||
color: var(--titlebar-popup-item-name-color);
|
||||
text-shadow: 0px 1px var(--titlebar-popup-item-name-shadow-color);
|
||||
}
|
||||
|
||||
.popup-item-shortcut {
|
||||
color: var(--titlebar-popup-item-shortcut-color);
|
||||
text-shadow: none;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
&-controls.type-windows .control {
|
||||
color: var(--titlebar-color);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
|
||||
&:hover {
|
||||
color: var(--titlebar-color);
|
||||
background: var(--titlebar-popup-item-hover-bgcolor);
|
||||
}
|
||||
|
||||
&.close:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
/*
|
||||
*=========================================================================
|
||||
* ERWT Dark Theme
|
||||
*=========================================================================
|
||||
*
|
||||
* Here we define the Dark Theme (stylesheet) for application.
|
||||
*/
|
||||
|
||||
:root {
|
||||
// Application
|
||||
--app-accent-color: #27954f;
|
||||
--app-font-size: 16px;
|
||||
--app-font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
||||
Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
--app-bgcolor: #1d1d1d;
|
||||
--app-border-color: #3b3f44;
|
||||
|
||||
// Scrollbar
|
||||
--scroll-width: 10px;
|
||||
--scroll-track-bgcolor: #2f2f2f52;
|
||||
--scroll-thumb-bgcolor: rgba(59, 59, 59, 0.747);
|
||||
--scroll-thumb-hover-bgcolor: #555;
|
||||
|
||||
// Selection
|
||||
--selection-bgcolor: var(--app-accent-color);
|
||||
--selection-color: #fff;
|
||||
|
||||
// Button
|
||||
--button-color: #fff;
|
||||
--button-border: 1px solid #222424;
|
||||
--button-bgcolor: hsl(0, 0%, 22%);
|
||||
--button-hover-bgcolor: hsl(0, 0%, 24%);
|
||||
--button-active-bgcolor: hsl(0deg 0% 20%);
|
||||
--button-shadow-color: #00000078;
|
||||
|
||||
// Titlebar
|
||||
--titlebar-bgcolor: #252525;
|
||||
--titlebar-color: hsl(0, 0%, 85%);
|
||||
--titlebar-title-color: hsl(0, 0%, 85%);
|
||||
--titlebar-menu-border-color: #2d2c2c;
|
||||
--titlebar-menu-title-hover-bgcolor: hsl(0deg 0% 12%);
|
||||
--titlebar-menu-title-active-bgcolor: #1e1e1e;
|
||||
--titlebar-menu-title-active-border-color: var(--titlebar-menu-border-color);
|
||||
--titlebar-menu-separator-bgcolor: var(--titlebar-menu-border-color);
|
||||
--titlebar-popup-bgcolor: #1e1e1e;
|
||||
--titlebar-popup-border: 1px solid var(--titlebar-menu-border-color);
|
||||
--titlebar-popup-shadow: 4px 10px 10px rgba(0, 0, 0, 0.2);
|
||||
--titlebar-popup-item-name-color: hsl(0, 0%, 75%);
|
||||
--titlebar-popup-item-shortcut-color: hsla(0, 0%, 55%, 0.8);
|
||||
--titlebar-popup-item-hover-color: hsl(0, 0%, 85%);
|
||||
--titlebar-popup-item-hover-bgcolor: hsl(0 0% 16.22%);
|
||||
--titlebar-popup-item-hover-shortcut-color: var(--app-accent-color);
|
||||
--titlebar-popup-item-name-shadow-color: #151515;
|
||||
|
||||
// ERWT
|
||||
--erwt-heading-color: #ddddddec;
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
/*
|
||||
*=========================================================================
|
||||
* ERWT Light Theme
|
||||
*=========================================================================
|
||||
*
|
||||
* Light theme for ERWT application.
|
||||
*/
|
||||
|
||||
body:not(.dark-mode) {
|
||||
// Application
|
||||
--app-accent-color: #27954f;
|
||||
--app-bgcolor: #e2e2e2;
|
||||
|
||||
// Selection
|
||||
--selection-bgcolor: var(--app-accent-color);
|
||||
--selection-color: #fff;
|
||||
|
||||
// Scrollbar
|
||||
--scroll-track-bgcolor: #2f2f2f1f;
|
||||
--scroll-thumb-bgcolor: rgb(59 59 59 / 30%);
|
||||
--scroll-thumb-hover-bgcolor: var(--app-accent-color);
|
||||
|
||||
// Button
|
||||
--button-border: 1px solid #eaeaea;
|
||||
--button-bgcolor: #fff;
|
||||
--button-color: #424242;
|
||||
--button-shadow-color: white;
|
||||
--button-hover-bgcolor: hsl(0, 0%, 98%);
|
||||
--button-active-bgcolor: hsl(0, 0%, 96%);
|
||||
|
||||
// Titlebar
|
||||
--titlebar-bgcolor: #d5d5d5c4;
|
||||
--titlebar-color: #1f1f1f;
|
||||
--titlebar-title-color: var(--titlebar-color);
|
||||
--titlebar-menu-title-hover-bgcolor: #e6e6e69e;
|
||||
--titlebar-popup-bgcolor: hsl(0deg 0% 99%);
|
||||
--titlebar-menu-title-active-bgcolor: hsl(0deg 0% 99%);
|
||||
--titlebar-menu-title-active-border-color: #d3d6d8;
|
||||
--titlebar-popup-border: 1px solid #d3d6d8;
|
||||
--titlebar-menu-separator-bgcolor: #d3d6d8;
|
||||
--titlebar-popup-item-name-color: #0e0e0e;
|
||||
--titlebar-popup-item-name-shadow-color: rgba(255, 255, 255, 0.8);
|
||||
--titlebar-popup-item-hover-color: #000000;
|
||||
--titlebar-popup-item-hover-shortcut-color: var(--app-accent-color);
|
||||
--titlebar-popup-item-hover-bgcolor: #d6dadea2;
|
||||
|
||||
// ERWT
|
||||
--erwt-heading-color: #282828;
|
||||
|
||||
// Overrides
|
||||
.main-teaser {
|
||||
color: #2e2e2e;
|
||||
|
||||
&:after {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.versions .item {
|
||||
color: #656565;
|
||||
background: #ffffff5e;
|
||||
|
||||
&>span {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
|
||||
interface IControlButtonProps {
|
||||
readonly name: string;
|
||||
readonly path: string;
|
||||
readonly title: string;
|
||||
}
|
||||
|
||||
const ControlButton: React.FC<
|
||||
IControlButtonProps & React.HTMLAttributes<HTMLDivElement>
|
||||
> = (props) => {
|
||||
const { name, path, title, ...rest } = props;
|
||||
const { onClick } = rest;
|
||||
|
||||
const className = classNames('control', name);
|
||||
|
||||
return (
|
||||
<div
|
||||
aria-label={name}
|
||||
className={className}
|
||||
onClick={onClick}
|
||||
title={title}
|
||||
{...rest}
|
||||
>
|
||||
<svg aria-hidden='true' version='1.1' width='10' height='10'>
|
||||
<path fill='currentColor' d={path} />
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ControlButton;
|
||||
16
packages/kbot/extensions/gui/src/renderer/window/LICENSE
Normal file
@ -0,0 +1,16 @@
|
||||
Copyright (c) 2021-2022 Guasam
|
||||
|
||||
This software is provided "as-is", without any express or implied warranty. In no event
|
||||
will the authors be held liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial
|
||||
applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you
|
||||
wrote the original software. If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||
as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
196
packages/kbot/extensions/gui/src/renderer/window/Titlebar.tsx
Normal file
@ -0,0 +1,196 @@
|
||||
/**
|
||||
* Copyright (c) 2021, Guasam
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
* Read the LICENSE file for more details.
|
||||
*
|
||||
* @author : guasam
|
||||
* @project : Electron Window
|
||||
* @package : Window Titlebar (Component)
|
||||
*/
|
||||
|
||||
import React, { createRef, useContext, useEffect, useRef, useState } from 'react';
|
||||
import titlebarMenus from '@main/window/titlebarMenus';
|
||||
import classNames from 'classnames';
|
||||
import WindowControls from './WindowControls';
|
||||
import context from '@main/window/titlebarContextApi';
|
||||
import { WindowContext } from './WindowFrame';
|
||||
import './titlebar.scss';
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
mode: 'centered-title';
|
||||
icon?: string;
|
||||
};
|
||||
|
||||
const Titlebar: React.FC<Props> = (props) => {
|
||||
const activeMenuIndex = useRef<number | null>(null);
|
||||
const menusRef = titlebarMenus.map(() => createRef<HTMLDivElement>());
|
||||
const [menusVisible, setMenusVisible] = useState(true);
|
||||
const windowContext = useContext(WindowContext);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.repeat) return; // Prevent repeatation of toggle when key holding
|
||||
if (e.altKey) {
|
||||
// Hiding menus? close active menu popup
|
||||
if (menusVisible) {
|
||||
closeActiveMenu();
|
||||
}
|
||||
setMenusVisible(!menusVisible);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [menusVisible, menusRef]);
|
||||
|
||||
useEffect(() => {
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
if (activeMenuIndex.current != null) {
|
||||
if (
|
||||
menusRef[activeMenuIndex.current].current &&
|
||||
!menusRef[activeMenuIndex.current].current?.contains(event.target as Node)
|
||||
) {
|
||||
// console.log('You clicked outside of me!');
|
||||
closeActiveMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (activeMenuIndex != null) {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
// console.log('added event');
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
// console.log('remove event');
|
||||
};
|
||||
}, [activeMenuIndex, menusRef]);
|
||||
|
||||
function showMenu(index: number, e: React.MouseEvent<HTMLDivElement>) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
if (menusRef[index].current?.classList.contains('active')) {
|
||||
// close..
|
||||
closeActiveMenu();
|
||||
} else {
|
||||
// open..
|
||||
menusRef[index].current?.classList.add('active');
|
||||
activeMenuIndex.current = index;
|
||||
menusRef[index].current?.parentElement?.classList.add('active');
|
||||
}
|
||||
}
|
||||
|
||||
function onMenuHover(index: number) {
|
||||
if (activeMenuIndex.current != null) {
|
||||
menusRef[activeMenuIndex.current].current?.classList.toggle('active');
|
||||
menusRef[index].current?.classList.toggle('active');
|
||||
menusRef[index].current?.parentElement?.classList.toggle('active');
|
||||
menusRef[activeMenuIndex.current].current?.parentElement?.classList.toggle(
|
||||
'active',
|
||||
);
|
||||
|
||||
activeMenuIndex.current = index;
|
||||
}
|
||||
}
|
||||
|
||||
function closeActiveMenu() {
|
||||
if (activeMenuIndex.current != null) {
|
||||
menusRef[activeMenuIndex.current].current?.classList.remove('active');
|
||||
menusRef[activeMenuIndex.current]?.current?.parentElement?.classList.remove('active');
|
||||
activeMenuIndex.current = null;
|
||||
}
|
||||
}
|
||||
|
||||
function handleAction(action?: string, value?: string | number) {
|
||||
closeActiveMenu();
|
||||
const c: Record<string, CallableFunction> = context;
|
||||
if (action) {
|
||||
if (typeof c[action] === 'function') {
|
||||
c[action](value);
|
||||
} else {
|
||||
console.log(`action [${action}] is not available in titlebar context`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='window-titlebar'>
|
||||
{props.icon ? (
|
||||
<section className='window-titlebar-icon'>
|
||||
<img src={props.icon} alt='titlebar icon' />
|
||||
</section>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
||||
<section
|
||||
className={classNames('window-titlebar-content', {
|
||||
centered: props.mode === 'centered-title',
|
||||
})}
|
||||
>
|
||||
{menusVisible ? '' : <div className='window-title'>{props.title}</div>}
|
||||
</section>
|
||||
|
||||
<section
|
||||
className={classNames('window-titlebar-menu', {
|
||||
hidden: !menusVisible,
|
||||
})}
|
||||
>
|
||||
{titlebarMenus.map((item, menuIndex) => {
|
||||
return (
|
||||
<div className='menu-item' key={`menu_${menuIndex}`}>
|
||||
<div
|
||||
className='menu-title'
|
||||
onClick={(e) => showMenu(menuIndex, e)}
|
||||
onMouseEnter={() => onMenuHover(menuIndex)}
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
>
|
||||
{item.name}
|
||||
</div>
|
||||
<div className='menu-popup' ref={menusRef[menuIndex]}>
|
||||
{item.items?.map((menuItem, menuItemIndex) => {
|
||||
if (menuItem.name === '__') {
|
||||
return (
|
||||
<div
|
||||
key={`menu_${menuIndex}_popup_item_${menuItemIndex}`}
|
||||
className='popup-item-separator'
|
||||
></div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={`menu_${menuIndex}_popup_item_${menuItemIndex}`}
|
||||
className='menu-popup-item'
|
||||
onClick={() =>
|
||||
handleAction(menuItem.action, menuItem.value)
|
||||
}
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
>
|
||||
<div className='popup-item-name'>{menuItem.name}</div>
|
||||
<div className='popup-item-shortcut'>
|
||||
{menuItem.shortcut}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
|
||||
<WindowControls platform={windowContext.platform} tooltips={true} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Titlebar;
|
||||
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2021, Guasam
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
* Read the LICENSE file for more details.
|
||||
*
|
||||
* @author : guasam
|
||||
* @project : Electron Window
|
||||
* @package : Window Controls - Close, Minimize, Maximize (Component)
|
||||
*/
|
||||
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import context from '@main/window/titlebarContextApi';
|
||||
|
||||
import ControlButton from './ControlButton';
|
||||
|
||||
type Props = {
|
||||
platform: string;
|
||||
tooltips?: boolean;
|
||||
};
|
||||
|
||||
const closePath =
|
||||
'M 0,0 0,0.7 4.3,5 0,9.3 0,10 0.7,10 5,5.7 9.3,10 10,10 10,9.3 5.7,5 10,0.7 10,0 9.3,0 5,4.3 0.7,0 Z';
|
||||
const maximizePath = 'M 0,0 0,10 10,10 10,0 Z M 1,1 9,1 9,9 1,9 Z';
|
||||
const minimizePath = 'M 0,5 10,5 10,6 0,6 Z';
|
||||
|
||||
const WindowControls: React.FC<Props> = (props) => {
|
||||
return (
|
||||
<section
|
||||
className={classNames(
|
||||
'window-titlebar-controls',
|
||||
`type-${props.platform}`,
|
||||
)}
|
||||
>
|
||||
<ControlButton
|
||||
name='minimize'
|
||||
onClick={() => context.minimize()}
|
||||
path={minimizePath}
|
||||
title={props.tooltips ? 'Minimize' : null}
|
||||
/>
|
||||
<ControlButton
|
||||
name='maximize'
|
||||
onClick={() => context.toggle_maximize()}
|
||||
path={maximizePath}
|
||||
title={props.tooltips ? 'Maximize' : null}
|
||||
/>
|
||||
<ControlButton
|
||||
name='close'
|
||||
onClick={() => context.exit()}
|
||||
path={closePath}
|
||||
title={props.tooltips ? 'Close' : null}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default WindowControls;
|
||||
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2021, Guasam
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
* Read the LICENSE file for more details.
|
||||
*
|
||||
* @author : guasam
|
||||
* @project : Electron Window
|
||||
* @package : Window Frame (Component)
|
||||
*/
|
||||
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import Titlebar from './Titlebar';
|
||||
import logo from '@assets/images/logo.png';
|
||||
|
||||
type Props = {
|
||||
title?: string;
|
||||
borderColor?: string;
|
||||
platform: 'windows' | 'mac';
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
type Context = {
|
||||
platform: 'windows' | 'mac';
|
||||
};
|
||||
|
||||
export const WindowContext = React.createContext<Context>({
|
||||
platform: 'windows',
|
||||
});
|
||||
|
||||
const WindowFrame: React.FC<Props> = (props) => {
|
||||
const itsRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const { parentElement } = itsRef.current;
|
||||
parentElement.classList.add('has-electron-window');
|
||||
parentElement.classList.add('has-border');
|
||||
|
||||
// Apply border color if prop given
|
||||
if (props.borderColor) {
|
||||
parentElement.style.borderColor = props.borderColor;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<WindowContext.Provider value={{ platform: props.platform }}>
|
||||
{/* Reference creator */}
|
||||
<div className='start-electron-window' ref={itsRef}></div>
|
||||
{/* Window Titlebar */}
|
||||
<Titlebar
|
||||
title={props.title ?? 'Electron Window'}
|
||||
mode='centered-title'
|
||||
icon={logo}
|
||||
/>
|
||||
{/* Window Content (Application to render) */}
|
||||
<div className='window-content'>{props.children}</div>
|
||||
</WindowContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default WindowFrame;
|
||||
182
packages/kbot/extensions/gui/src/renderer/window/schema.json
Normal file
122
packages/kbot/extensions/gui/src/renderer/window/schema_ui.json
Normal file
211
packages/kbot/extensions/gui/src/renderer/window/titlebar.scss
Normal file
@ -0,0 +1,211 @@
|
||||
$titlebar-baseSize: 16px;
|
||||
$titlebar-height: 28px;
|
||||
$titlebar-bg: #171b21;
|
||||
$titlebar-iconSize: 16px;
|
||||
$em: $titlebar-baseSize*1em;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Window Titlebar
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.window-titlebar {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
font-size: $titlebar-baseSize;
|
||||
height: $titlebar-height;
|
||||
background: $titlebar-bg;
|
||||
-webkit-app-region: drag;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
|
||||
&>section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-content {
|
||||
flex: 1;
|
||||
font-size: calc($titlebar-baseSize - 3px);
|
||||
color: #a9b0bb;
|
||||
|
||||
&.centered {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
&-icon {
|
||||
padding: 0 0.75em;
|
||||
|
||||
img {
|
||||
width: $titlebar-iconSize;
|
||||
height: $titlebar-iconSize;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-item {
|
||||
&-name {
|
||||
padding-right: 2rem;
|
||||
color: #d8d8d8;
|
||||
}
|
||||
|
||||
&-shortcut {
|
||||
color: #73757c;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
&-separator {
|
||||
height: 1px;
|
||||
background: #3c4043;
|
||||
margin: 4px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Titlebar Menu
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.window-titlebar .menu {
|
||||
flex: 1;
|
||||
|
||||
&-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&-item.active {
|
||||
.menu-title {
|
||||
background: #3c4043;
|
||||
color: #bfbfbf;
|
||||
}
|
||||
}
|
||||
|
||||
&-title {
|
||||
padding: 4px 10px;
|
||||
font-size: 0.8125rem;
|
||||
text-shadow: 0px 1px 1px black;
|
||||
-webkit-app-region: no-drag;
|
||||
color: #97a0b1;
|
||||
|
||||
&:hover {
|
||||
background-color: #1f252c;
|
||||
}
|
||||
}
|
||||
|
||||
&-popup {
|
||||
display: none;
|
||||
position: fixed;
|
||||
background: #292a2d;
|
||||
min-width: 70px;
|
||||
border: 1px solid #3c4043;
|
||||
padding: 0.25rem 0;
|
||||
box-shadow: 2px 1px 4px hsla(0, 0%, 0%, 0.5);
|
||||
z-index: 10000;
|
||||
|
||||
&.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.8125rem;
|
||||
text-shadow: 0px 1px 1px black;
|
||||
padding: 0.375rem 1rem;
|
||||
|
||||
&:hover {
|
||||
background: #1761cb;
|
||||
|
||||
.popup-item-shortcut {
|
||||
color: #8cbbff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Titlebar Controls (Max, Min, Close)
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.window-titlebar-controls {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
color: #969799;
|
||||
|
||||
&.type-windows {
|
||||
.control {
|
||||
padding: 0 1.15em;
|
||||
font-size: 0.875em;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
-webkit-app-region: no-drag;
|
||||
|
||||
&.close:hover {
|
||||
background: #e10000;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #242d38;
|
||||
color: #d8d9db;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.type-mac {
|
||||
.control {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: #0e0e0e99;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 0.675rem;
|
||||
color: transparent;
|
||||
-webkit-app-region: no-drag;
|
||||
opacity: 0.8;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.control.close {
|
||||
background: #f46d60;
|
||||
}
|
||||
|
||||
.control.maximize {
|
||||
background: #59ca56;
|
||||
}
|
||||
|
||||
.control.minimize {
|
||||
background: #f9c04e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Window Content
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.window-content {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
}
|
||||
4
packages/kbot/extensions/gui/src/typings/index.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module '*.css';
|
||||
declare module '*.png';
|
||||
declare module '*.jpg';
|
||||
declare module '*.jpeg';
|
||||
88
packages/kbot/extensions/gui/tools/forge/forge.config.js
Normal file
@ -0,0 +1,88 @@
|
||||
// Forge Configuration
|
||||
const path = require('path');
|
||||
const rootDir = process.cwd();
|
||||
|
||||
module.exports = {
|
||||
// Packager Config
|
||||
packagerConfig: {
|
||||
// Create asar archive for main, renderer process files
|
||||
asar: true,
|
||||
// Set executable name
|
||||
executableName: 'ERWT',
|
||||
// Set application copyright
|
||||
appCopyright: '© 2021-2024 Codesbiome, Guasam',
|
||||
// Set application icon
|
||||
icon: path.resolve('assets/images/appIcon.ico'),
|
||||
},
|
||||
// Forge Makers
|
||||
makers: [
|
||||
{
|
||||
// Squirrel.Windows is a no-prompt, no-hassle, no-admin method of installing
|
||||
// Windows applications and is therefore the most user friendly you can get.
|
||||
name: '@electron-forge/maker-squirrel',
|
||||
config: {
|
||||
name: 'electron-react-typescript-webpack-2022',
|
||||
},
|
||||
},
|
||||
{
|
||||
// The Zip target builds basic .zip files containing your packaged application.
|
||||
// There are no platform specific dependencies for using this maker and it will run on any platform.
|
||||
name: '@electron-forge/maker-zip',
|
||||
platforms: ['darwin'],
|
||||
},
|
||||
{
|
||||
// The deb target builds .deb packages, which are the standard package format for Debian-based
|
||||
// Linux distributions such as Ubuntu.
|
||||
name: '@electron-forge/maker-deb',
|
||||
config: {},
|
||||
},
|
||||
{
|
||||
// The RPM target builds .rpm files, which is the standard package format for
|
||||
// RedHat-based Linux distributions such as Fedora.
|
||||
name: '@electron-forge/maker-rpm',
|
||||
config: {},
|
||||
},
|
||||
],
|
||||
// Forge Plugins
|
||||
plugins: [
|
||||
{
|
||||
name: '@electron-forge/plugin-webpack',
|
||||
config: {
|
||||
// Fix content-security-policy error when image or video src isn't same origin
|
||||
// Remove 'unsafe-eval' to get rid of console warning in development mode.
|
||||
devContentSecurityPolicy: `default-src 'self' 'unsafe-inline' data:; script-src 'self' 'unsafe-inline' data:`,
|
||||
// Webpack Dev Server port
|
||||
port: 3000,
|
||||
// Logger port
|
||||
loggerPort: 9000,
|
||||
// Main process webpack configuration
|
||||
mainConfig: path.join(rootDir, 'tools/webpack/webpack.main.js'),
|
||||
// Renderer process webpack configuration
|
||||
renderer: {
|
||||
// Configuration file path
|
||||
config: path.join(rootDir, 'tools/webpack/webpack.renderer.js'),
|
||||
// Entrypoints of the application
|
||||
entryPoints: [
|
||||
{
|
||||
// Window process name
|
||||
name: 'app_window',
|
||||
// React Hot Module Replacement (HMR)
|
||||
rhmr: 'react-hot-loader/patch',
|
||||
// HTML index file template
|
||||
html: path.join(rootDir, 'src/renderer/app.html'),
|
||||
// App Renderer
|
||||
js: path.join(rootDir, 'src/renderer/appRenderer.tsx'),
|
||||
// App Preload
|
||||
preload: {
|
||||
js: path.join(rootDir, 'src/renderer/appPreload.tsx'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
devServer: {
|
||||
liveReload: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -0,0 +1,12 @@
|
||||
const { createWebpackAliases } = require('./webpack.helpers');
|
||||
|
||||
// Export aliases
|
||||
module.exports = createWebpackAliases({
|
||||
'@assets': 'assets',
|
||||
'@components': 'src/renderer/components',
|
||||
'@common': 'src/common',
|
||||
'@main': 'src/main',
|
||||
'@renderer': 'src/renderer',
|
||||
'@src': 'src',
|
||||
'@styles': 'src/renderer/styles',
|
||||
});
|
||||
@ -0,0 +1,20 @@
|
||||
const path = require('path');
|
||||
const cwd = process.cwd();
|
||||
|
||||
|
||||
function inDev() {
|
||||
return process.env.NODE_ENV == 'development';
|
||||
}
|
||||
|
||||
function createWebpackAliases (aliases) {
|
||||
const result = {};
|
||||
for (const name in aliases) {
|
||||
result[name] = path.join(cwd, aliases[name]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
inDev,
|
||||
createWebpackAliases,
|
||||
};
|
||||
16
packages/kbot/extensions/gui/tools/webpack/webpack.main.js
Normal file
@ -0,0 +1,16 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* This is the main entry point for your application, it's the first file
|
||||
* that runs in the main process.
|
||||
*/
|
||||
entry: ['./src/main/app.ts'],
|
||||
// Put your normal webpack config below here
|
||||
module: {
|
||||
rules: require('./webpack.rules'),
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json'],
|
||||
alias: require('./webpack.aliases'),
|
||||
},
|
||||
stats: 'minimal',
|
||||
};
|
||||
@ -0,0 +1,10 @@
|
||||
const webpack = require('webpack');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
||||
const { inDev } = require('./webpack.helpers');
|
||||
|
||||
module.exports = [
|
||||
new ForkTsCheckerWebpackPlugin(),
|
||||
inDev() && new webpack.HotModuleReplacementPlugin(),
|
||||
inDev() && new ReactRefreshWebpackPlugin(),
|
||||
].filter(Boolean);
|
||||
@ -0,0 +1,22 @@
|
||||
const rules = require('./webpack.rules');
|
||||
const plugins = require('./webpack.plugins');
|
||||
|
||||
module.exports = {
|
||||
module: {
|
||||
rules,
|
||||
},
|
||||
plugins: plugins,
|
||||
resolve: {
|
||||
extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],
|
||||
alias: {
|
||||
// Custom Aliases
|
||||
...require('./webpack.aliases'),
|
||||
},
|
||||
},
|
||||
stats: 'minimal',
|
||||
/**
|
||||
* Fix: Enable inline-source-map to fix following:
|
||||
* Dev tools: unable to load source maps over custom protocol
|
||||
*/
|
||||
devtool: 'inline-source-map',
|
||||
};
|
||||
51
packages/kbot/extensions/gui/tools/webpack/webpack.rules.js
Normal file
@ -0,0 +1,51 @@
|
||||
module.exports = [
|
||||
{
|
||||
// Add support for native node modules
|
||||
test: /native_modules\/.+\.node$/,
|
||||
use: 'node-loader',
|
||||
},
|
||||
{
|
||||
test: /\.(m?js|node)$/,
|
||||
parser: { amd: false },
|
||||
use: {
|
||||
loader: '@vercel/webpack-asset-relocator-loader',
|
||||
options: {
|
||||
outputAssetBase: 'native_modules',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// Typescript loader
|
||||
test: /\.tsx?$/,
|
||||
exclude: /(node_modules|\.webpack)/,
|
||||
use: {
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// CSS Loader
|
||||
test: /\.css$/,
|
||||
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
|
||||
},
|
||||
{
|
||||
// SCSS (SASS) Loader
|
||||
test: /\.s[ac]ss$/i,
|
||||
use: [
|
||||
{ loader: 'style-loader' },
|
||||
{ loader: 'css-loader' },
|
||||
{ loader: 'sass-loader' },
|
||||
],
|
||||
},
|
||||
{
|
||||
// Assets loader
|
||||
// More information here https://webpack.js.org/guides/asset-modules/
|
||||
test: /\.(gif|jpe?g|tiff|png|webp|bmp|svg|eot|ttf|woff|woff2)$/i,
|
||||
type: 'asset',
|
||||
generator: {
|
||||
filename: 'assets/[hash][ext][query]',
|
||||
},
|
||||
},
|
||||
];
|
||||
28
packages/kbot/extensions/gui/tsconfig.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"jsx": "react",
|
||||
"allowJs": true,
|
||||
"target": "ES6",
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"noImplicitAny": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"outDir": "dist",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"paths": {
|
||||
"*": ["node_modules/*"],
|
||||
"@assets/*": ["./assets/*"],
|
||||
"@components/*": ["./src/renderer/components/*"],
|
||||
"@common/*": ["./src/common/*"],
|
||||
"@main/*": ["./src/main/*"],
|
||||
"@renderer/*": ["./src/renderer/*"],
|
||||
"@src/*": ["./src/*"],
|
||||
"@misc/*": ["./misc/*"],
|
||||
"@styles/*": ["./src/renderer/styles/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*", "tools/**/*"]
|
||||
}
|
||||