mirror of
https://github.com/LinoSchmidt/StickExporterTX.git
synced 2026-03-20 17:44:29 +01:00
Slightly better ui, added react and typescript
This commit is contained in:
15
.babelrc
Normal file
15
.babelrc
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"@babel/plugin-transform-runtime",
|
||||
{
|
||||
"regenerator": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
29
.eslintrc
Normal file
29
.eslintrc
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"react-hooks",
|
||||
"import"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:react/recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
"react/prop-types": "off",
|
||||
"global-require": "off",
|
||||
"import/no-dynamic-require": "off"
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"pragma": "React",
|
||||
"version": "detect"
|
||||
}
|
||||
}
|
||||
}
|
||||
51
configs/webpack.base.config.js
Normal file
51
configs/webpack.base.config.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import path from 'path';
|
||||
import ESLintPlugin from "eslint-webpack-plugin";
|
||||
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
|
||||
|
||||
export default {
|
||||
mode: 'production',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(ts|js)x?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ["style-loader", "css-loader"],
|
||||
},
|
||||
],
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, '../src/.webpack'),
|
||||
libraryTarget: 'commonjs2',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.ts', '.jsx', '.tsx', '.json'],
|
||||
},
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
async: false
|
||||
}),
|
||||
new ESLintPlugin({
|
||||
extensions: ["js", "jsx", "ts", "tsx"],
|
||||
}),
|
||||
],
|
||||
node: {
|
||||
__dirname: false,
|
||||
__filename: false,
|
||||
},
|
||||
experiments: {
|
||||
topLevelAwait: true,
|
||||
},
|
||||
}
|
||||
10
configs/webpack.main.config.babel.js
Normal file
10
configs/webpack.main.config.babel.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import baseConfig from "./webpack.base.config.js";
|
||||
import {merge} from 'webpack-merge';
|
||||
|
||||
export default merge(baseConfig, {
|
||||
target: 'electron-main',
|
||||
entry: './src/index.ts',
|
||||
output: {
|
||||
filename: 'index.js'
|
||||
},
|
||||
});
|
||||
10
configs/webpack.renderer.config.babel.js
Normal file
10
configs/webpack.renderer.config.babel.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import baseConfig from "./webpack.base.config.js";
|
||||
import {merge} from 'webpack-merge';
|
||||
|
||||
export default merge(baseConfig, {
|
||||
target: 'electron-renderer',
|
||||
entry: './src/renderer.tsx',
|
||||
output: {
|
||||
filename: 'renderer.js'
|
||||
},
|
||||
});
|
||||
21201
package-lock.json
generated
21201
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
53
package.json
53
package.json
@@ -3,11 +3,13 @@
|
||||
"name": "stickexportertx",
|
||||
"productName": "StickExporterTX",
|
||||
"description": "3D stick exporter for EdgeTX/OpenTX logs",
|
||||
"main": "src/index.js",
|
||||
"main": "src/.webpack/index.js",
|
||||
"scripts": {
|
||||
"start": "electron-forge start",
|
||||
"publish": "electron-builder build --publish always",
|
||||
"build": "electron-builder build"
|
||||
"build:main": "webpack --config configs/webpack.main.config.babel.js",
|
||||
"build:renderer": "webpack --config configs/webpack.renderer.config.babel.js",
|
||||
"build": "npm run build:main && npm run build:renderer",
|
||||
"start": "npm run build && electron .",
|
||||
"build:app": "npm run build && electron-builder build"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": {
|
||||
@@ -122,15 +124,46 @@
|
||||
"@electron/remote": "^2.0.8",
|
||||
"electron-log": "^4.4.7",
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"xml-formatter": "^2.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "^6.0.0-beta.63",
|
||||
"@electron-forge/maker-deb": "^6.0.0-beta.63",
|
||||
"@electron-forge/maker-rpm": "^6.0.0-beta.63",
|
||||
"@electron-forge/maker-squirrel": "^6.0.0-beta.63",
|
||||
"@electron-forge/maker-zip": "^6.0.0-beta.63",
|
||||
"@babel/core": "^7.18.2",
|
||||
"@babel/plugin-transform-runtime": "^7.18.2",
|
||||
"@babel/preset-env": "^7.18.2",
|
||||
"@babel/preset-react": "^7.17.12",
|
||||
"@babel/preset-typescript": "^7.17.12",
|
||||
"@babel/register": "^7.17.7",
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@types/react": "^18.0.9",
|
||||
"@types/react-dom": "^18.0.5",
|
||||
"@types/webpack": "^5.28.0",
|
||||
"@types/webpack-dev-server": "^4.7.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.27.0",
|
||||
"@typescript-eslint/parser": "^5.27.0",
|
||||
"@vercel/webpack-asset-relocator-loader": "^1.7.2",
|
||||
"babel-loader": "^8.2.5",
|
||||
"css-loader": "^6.7.1",
|
||||
"electron": "18.1.0",
|
||||
"electron-builder": "^23.0.3"
|
||||
"electron-builder": "^23.0.3",
|
||||
"eslint": "^8.16.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-react": "^7.30.0",
|
||||
"eslint-plugin-react-hooks": "^4.5.0",
|
||||
"eslint-webpack-plugin": "^3.1.1",
|
||||
"fork-ts-checker-webpack-plugin": "^7.2.11",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"node-loader": "^2.0.0",
|
||||
"sass": "^1.52.1",
|
||||
"sass-loader": "^13.0.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"ts-loader": "^9.3.0",
|
||||
"ts-node": "^10.8.0",
|
||||
"typescript": "^4.7.2",
|
||||
"webpack": "^5.72.1",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.9.1",
|
||||
"webpack-merge": "^5.8.0"
|
||||
}
|
||||
}
|
||||
|
||||
50
src/components/logger.ts
Normal file
50
src/components/logger.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import electronLog from 'electron-log';
|
||||
import {dataPath} from './paths';
|
||||
import {dialog} from '@electron/remote';
|
||||
import path from 'path';
|
||||
import {exec} from "child_process";
|
||||
|
||||
electronLog.transports.console.format = "{h}:{i}:{s} {text}";
|
||||
electronLog.transports.file.getFile();
|
||||
electronLog.transports.file.resolvePath = () => path.join(dataPath, "logs", "main.log");
|
||||
|
||||
const logger = {
|
||||
info: function (message:string) {
|
||||
electronLog.info(message);
|
||||
},
|
||||
error: function (message:string) {
|
||||
electronLog.error(message);
|
||||
},
|
||||
warning: function (message:string) {
|
||||
electronLog.warn(message);
|
||||
},
|
||||
errorMSG: function (message:string) {
|
||||
logger.error(message);
|
||||
|
||||
dialog.showMessageBox({
|
||||
type: 'error',
|
||||
buttons: ['Open Log', 'OK'],
|
||||
defaultId: 1,
|
||||
title: 'Something went wrong!',
|
||||
message: 'An error has occurred:',
|
||||
detail: message
|
||||
}).then(res => {
|
||||
if(res.response === 0) {
|
||||
exec('start "" "' + path.join(dataPath, "logs") + '"');
|
||||
}
|
||||
});
|
||||
},
|
||||
warningMSG: function (message:string) {
|
||||
logger.warning(message);
|
||||
|
||||
dialog.showMessageBox({
|
||||
type: 'warning',
|
||||
buttons: ['OK'],
|
||||
defaultId: 1,
|
||||
title: 'Warning!',
|
||||
message: message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default logger;
|
||||
9
src/components/paths.ts
Normal file
9
src/components/paths.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import path from 'path';
|
||||
import {app} from '@electron/remote';
|
||||
|
||||
export const dataPath = app.getPath('userData');
|
||||
export const SettingPath = path.join(dataPath, "settings.xml");
|
||||
|
||||
export const blenderPath = path.join("assets", "blender-win", "blender");
|
||||
export const templatePath = path.join("assets", "template.blend");
|
||||
export const blenderScriptPath = path.join("assets", "blenderScript.py");
|
||||
43
src/components/render.ts
Normal file
43
src/components/render.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import {blenderPath, blenderScriptPath, SettingPath, templatePath} from "./paths";
|
||||
import {exec} from "child_process";
|
||||
import logger from "./logger";
|
||||
import React from "react";
|
||||
|
||||
function Render(setStatusDisplay:React.Dispatch<React.SetStateAction<string>>, setLogNumber:React.Dispatch<React.SetStateAction<string>>) {
|
||||
const blenderCons = exec('"' + blenderPath + '" "' + templatePath + '" --background --python "' + blenderScriptPath + '" -- "' + SettingPath.replaceAll('\\', '/') + '"', {maxBuffer: Infinity});
|
||||
|
||||
let frames = "0";
|
||||
let lastFrame = "0";
|
||||
let lastData = "Initializing...";
|
||||
|
||||
setStatusDisplay(lastData);
|
||||
|
||||
blenderCons.stdout?.on("data", (data:string) => {
|
||||
logger.info(data);
|
||||
|
||||
if(data.startsWith("Frames:")) {
|
||||
frames = data.split(":")[1];
|
||||
} else if(data.startsWith("Fra:")) {
|
||||
lastFrame = data.split(":")[1].split(" ")[0]
|
||||
lastData = "Render Frame " + lastFrame + "/" + frames;
|
||||
} else if(data.startsWith("Finished")) {
|
||||
if(lastFrame == frames) {
|
||||
lastData = "Finished Render Successfully!"
|
||||
} else {
|
||||
logger.errorMSG("Render Failed!");
|
||||
}
|
||||
} else if(data.includes("Blender quit")) {
|
||||
if(lastData != "Finished Render Successfully!") {
|
||||
logger.errorMSG("Render Failed!");
|
||||
}
|
||||
} else if(data.startsWith("Init:")) {
|
||||
lastData = "Initialize Frame " + data.split(":")[1] + "/" + frames;
|
||||
} else if(data.startsWith("Lognr:")) {
|
||||
setLogNumber(data.split(":")[1]);
|
||||
}
|
||||
|
||||
setStatusDisplay(lastData);
|
||||
});
|
||||
}
|
||||
|
||||
export default Render;
|
||||
98
src/components/settings.ts
Normal file
98
src/components/settings.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import formatXML from "xml-formatter";
|
||||
import {SettingPath} from './paths';
|
||||
import fs from "fs";
|
||||
import logger from "./logger";
|
||||
|
||||
function getXMLChild(doc:Document, child:string) {
|
||||
return String(doc.getElementsByTagName(child)[0].childNodes[0].nodeValue);
|
||||
}
|
||||
|
||||
const settingList = await fetch(SettingPath).then(function(response){
|
||||
return response.text();
|
||||
}).then(function(data){
|
||||
const parser = new DOMParser();
|
||||
const xmlDoc = parser.parseFromString(data, 'text/xml');
|
||||
|
||||
return {
|
||||
fps: parseInt(getXMLChild(xmlDoc, "fps")),
|
||||
width: parseInt(getXMLChild(xmlDoc, "width")),
|
||||
stickDistance: parseInt(getXMLChild(xmlDoc, "stickDistance")),
|
||||
stickMode2: (getXMLChild(xmlDoc, "stickMode2") === "true"),
|
||||
log: getXMLChild(xmlDoc, "log"),
|
||||
output: getXMLChild(xmlDoc, "output")
|
||||
}
|
||||
|
||||
}).catch(function(error) {
|
||||
logger.errorMSG(error);
|
||||
|
||||
return {
|
||||
fps: 30,
|
||||
width: 540,
|
||||
stickDistance: 5,
|
||||
stickMode2: true,
|
||||
log: '"None"',
|
||||
output: "None"
|
||||
}
|
||||
});
|
||||
|
||||
function settingListLoadDefault() {
|
||||
updateSettings({
|
||||
fps: 30,
|
||||
width: 540,
|
||||
stickDistance: 5,
|
||||
stickMode2: true
|
||||
});
|
||||
}
|
||||
|
||||
function updateSettings(optiones:{fps?:number, width?:number, stickDistance?:number, stickMode2?:boolean, log?:string, output?:string}) {
|
||||
if(optiones.fps === undefined) {
|
||||
optiones.fps = settingList.fps;
|
||||
} else {
|
||||
settingList.fps = optiones.fps;
|
||||
}
|
||||
if(optiones.width === undefined) {
|
||||
optiones.width = settingList.width;
|
||||
} else {
|
||||
settingList.width = optiones.width;
|
||||
}
|
||||
if(optiones.stickDistance === undefined) {
|
||||
optiones.stickDistance = settingList.stickDistance;
|
||||
} else {
|
||||
settingList.stickDistance = optiones.stickDistance;
|
||||
}
|
||||
if(optiones.stickMode2 === undefined) {
|
||||
optiones.stickMode2 = settingList.stickMode2;
|
||||
} else {
|
||||
settingList.stickMode2 = optiones.stickMode2;
|
||||
}
|
||||
if(optiones.log === undefined) {
|
||||
optiones.log = settingList.log;
|
||||
} else {
|
||||
settingList.log = optiones.log;
|
||||
}
|
||||
if(optiones.output === undefined) {
|
||||
optiones.output = settingList.output;
|
||||
} else {
|
||||
settingList.output = optiones.output;
|
||||
}
|
||||
|
||||
const xmlStr = '<?xml version="1.0"?><settings><fps>' + optiones.fps +
|
||||
'</fps><width>' + optiones.width +
|
||||
'</width><stickDistance>' + optiones.stickDistance +
|
||||
'</stickDistance><stickMode2>' + ((optiones.stickMode2)?"true":"false") +
|
||||
'</stickMode2><log>' + optiones.log +
|
||||
'</log><output>' + optiones.output +
|
||||
'</output></settings>';
|
||||
|
||||
fs.writeFile(SettingPath, formatXML(xmlStr, {collapseContent: true}), function(err) {
|
||||
if(err) {
|
||||
logger.errorMSG(String(err));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
updateSettings,
|
||||
settingListLoadDefault,
|
||||
settingList
|
||||
}
|
||||
98
src/components/ui/mainSide.tsx
Normal file
98
src/components/ui/mainSide.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import React, {useState, useEffect} from "react";
|
||||
import { dialog } from "@electron/remote";
|
||||
import { settingList, updateSettings } from "../settings";
|
||||
import logger from "../logger";
|
||||
import {exec} from "child_process";
|
||||
import Render from "../render";
|
||||
|
||||
function MainSide() {
|
||||
const [status, setStatus] = useState("Idle");
|
||||
const [logNumber, setLogNumber] = useState("0");
|
||||
const [logs, setLogs] = useState(settingList.log);
|
||||
const [output, setOutput] = useState(settingList.output);
|
||||
const [logTable, setLogTable] = useState(logs.substring(1).slice(0, -1).split('""').map((log, index) => {
|
||||
return <tr key={index}>
|
||||
<td>{log}</td>
|
||||
</tr>
|
||||
}));
|
||||
useEffect(() => {
|
||||
setLogTable(logs.substring(1).slice(0, -1).split('""').map((log, index) => {
|
||||
return <tr key={index}>
|
||||
<td>{log}</td>
|
||||
</tr>
|
||||
}));
|
||||
}, [logs]);
|
||||
|
||||
return (
|
||||
<div id="content">
|
||||
<button onClick={() => Render(setStatus, setLogNumber)}>Start Render</button>
|
||||
<p>{"Log " + logNumber + "/" + String(settingList.log.split("\"\"").length)}</p>
|
||||
<div className="dataDiv">
|
||||
<p>{status}</p>
|
||||
<button onClick={() => openOutputFolder()}>Open Output Folder</button>
|
||||
</div>
|
||||
<hr/>
|
||||
<div className="dataDiv">
|
||||
<p>Logs:</p>
|
||||
<table>
|
||||
<tbody>
|
||||
{logTable}
|
||||
</tbody>
|
||||
</table>
|
||||
<button onClick={() => openLog(setLogs)}>Open Log</button>
|
||||
</div>
|
||||
<div className="dataDiv">
|
||||
<p id="output">{"Output Folder: " + output}</p>
|
||||
<button onClick={() => openVid(setOutput)}>Open Video</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function openLog(updateHook:React.Dispatch<React.SetStateAction<string>>) {
|
||||
dialog.showOpenDialog({
|
||||
properties: [
|
||||
"multiSelections"
|
||||
],
|
||||
filters: [
|
||||
{
|
||||
name: "TX-Logs",
|
||||
extensions: [
|
||||
"csv"
|
||||
]
|
||||
}
|
||||
]
|
||||
}).then(result => {
|
||||
let logStr = "";
|
||||
result.filePaths.forEach(value => {
|
||||
logStr += "\"" + String(value) + "\"";
|
||||
});
|
||||
updateSettings({log:logStr});
|
||||
updateHook(logStr);
|
||||
}).catch(err => {
|
||||
logger.errorMSG(err);
|
||||
});
|
||||
}
|
||||
|
||||
function openVid(updateHook:React.Dispatch<React.SetStateAction<string>>) {
|
||||
dialog.showOpenDialog({
|
||||
properties: [
|
||||
"openDirectory"
|
||||
]
|
||||
}).then(result => {
|
||||
updateSettings({output:String(result.filePaths)});
|
||||
updateHook(String(result.filePaths));
|
||||
}).catch(err => {
|
||||
logger.errorMSG(err);
|
||||
});
|
||||
}
|
||||
|
||||
function openOutputFolder() {
|
||||
if(settingList.output == "None") {
|
||||
logger.warningMSG("No output folder set!");
|
||||
} else {
|
||||
exec('start "" "' + settingList.output + '"');
|
||||
}
|
||||
}
|
||||
|
||||
export default MainSide;
|
||||
36
src/components/ui/menu.tsx
Normal file
36
src/components/ui/menu.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from "react";
|
||||
import { openSide, Side } from "../../renderer";
|
||||
|
||||
const UpdateButton = () => (
|
||||
<div id="update-available">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
{/* Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. */}
|
||||
<path
|
||||
d="M480 352h-133.5l-45.25 45.25C289.2 409.3 273.1 416 256 416s-33.16-6.656-45.25-18.75L165.5 352H32c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h448c17.67 0 32-14.33 32-32v-96C512 366.3 497.7 352 480 352zM432 456c-13.2 0-24-10.8-24-24c0-13.2 10.8-24 24-24s24 10.8 24 24C456 445.2 445.2 456 432 456zM233.4 374.6C239.6 380.9 247.8 384 256 384s16.38-3.125 22.62-9.375l128-128c12.49-12.5 12.49-32.75 0-45.25c-12.5-12.5-32.76-12.5-45.25 0L288 274.8V32c0-17.67-14.33-32-32-32C238.3 0 224 14.33 224 32v242.8L150.6 201.4c-12.49-12.5-32.75-12.5-45.25 0c-12.49 12.5-12.49 32.75 0 45.25L233.4 374.6z" />
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
|
||||
const MainSideButtons = () => (
|
||||
<div id="settings-button" onClick={() => openSide(Side.Settings)}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
{/* Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. */}
|
||||
<path
|
||||
d="M495.9 166.6C499.2 175.2 496.4 184.9 489.6 191.2L446.3 230.6C447.4 238.9 448 247.4 448 256C448 264.6 447.4 273.1 446.3 281.4L489.6 320.8C496.4 327.1 499.2 336.8 495.9 345.4C491.5 357.3 486.2 368.8 480.2 379.7L475.5 387.8C468.9 398.8 461.5 409.2 453.4 419.1C447.4 426.2 437.7 428.7 428.9 425.9L373.2 408.1C359.8 418.4 344.1 427 329.2 433.6L316.7 490.7C314.7 499.7 307.7 506.1 298.5 508.5C284.7 510.8 270.5 512 255.1 512C241.5 512 227.3 510.8 213.5 508.5C204.3 506.1 197.3 499.7 195.3 490.7L182.8 433.6C167 427 152.2 418.4 138.8 408.1L83.14 425.9C74.3 428.7 64.55 426.2 58.63 419.1C50.52 409.2 43.12 398.8 36.52 387.8L31.84 379.7C25.77 368.8 20.49 357.3 16.06 345.4C12.82 336.8 15.55 327.1 22.41 320.8L65.67 281.4C64.57 273.1 64 264.6 64 256C64 247.4 64.57 238.9 65.67 230.6L22.41 191.2C15.55 184.9 12.82 175.3 16.06 166.6C20.49 154.7 25.78 143.2 31.84 132.3L36.51 124.2C43.12 113.2 50.52 102.8 58.63 92.95C64.55 85.8 74.3 83.32 83.14 86.14L138.8 103.9C152.2 93.56 167 84.96 182.8 78.43L195.3 21.33C197.3 12.25 204.3 5.04 213.5 3.51C227.3 1.201 241.5 0 256 0C270.5 0 284.7 1.201 298.5 3.51C307.7 5.04 314.7 12.25 316.7 21.33L329.2 78.43C344.1 84.96 359.8 93.56 373.2 103.9L428.9 86.14C437.7 83.32 447.4 85.8 453.4 92.95C461.5 102.8 468.9 113.2 475.5 124.2L480.2 132.3C486.2 143.2 491.5 154.7 495.9 166.6V166.6zM256 336C300.2 336 336 300.2 336 255.1C336 211.8 300.2 175.1 256 175.1C211.8 175.1 176 211.8 176 255.1C176 300.2 211.8 336 256 336z" />
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
|
||||
const OtherSideButtons = () => (
|
||||
<button id="settings-back" onClick={() => openSide(Side.Main)}>Back</button>
|
||||
)
|
||||
|
||||
const Menu = ({updateAvailable, side}:{updateAvailable:boolean, side:Side}) => (
|
||||
<header>
|
||||
<h1 id="main-headline">{(side == Side.Main)? "StickExporterTX" : "Settings"}</h1>
|
||||
{updateAvailable? <UpdateButton/> : null}
|
||||
{(side == Side.Main)? <MainSideButtons/> : <OtherSideButtons/>}
|
||||
</header>
|
||||
)
|
||||
|
||||
export default Menu;
|
||||
58
src/components/ui/settingsSide.tsx
Normal file
58
src/components/ui/settingsSide.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import React, {useState} from "react";
|
||||
import { settingList, updateSettings, settingListLoadDefault } from "../settings";
|
||||
|
||||
function SettingsSide() {
|
||||
|
||||
const [fps, setFps] = useState(settingList.fps);
|
||||
const [width, setWidth] = useState(settingList.width);
|
||||
const [stickDistance, setStickDistance] = useState(settingList.stickDistance);
|
||||
const [stickMode2, setStickMode2] = useState(settingList.stickMode2);
|
||||
|
||||
return (
|
||||
<div id="content">
|
||||
<div className="dataDiv">
|
||||
<p>FPS: </p>
|
||||
<input id="fpsInput" type="number" value={fps.toString()} min="1" step="1" onChange={e => {
|
||||
updateSettings({fps:parseInt(e.target.value)});
|
||||
setFps(settingList.fps);
|
||||
}}/>
|
||||
</div>
|
||||
<div className="dataDiv">
|
||||
<p>Width: </p>
|
||||
<input id="widthInput" type="number" value={width.toString()} min="1" step="1" onChange={e => {
|
||||
updateSettings({width:parseInt(e.target.value)});
|
||||
setWidth(settingList.width);
|
||||
}}/>
|
||||
</div>
|
||||
<div className="dataDiv">
|
||||
<p>Stick Distance: </p>
|
||||
<input id="stickDistanceInput" type="number" value={stickDistance.toString()} min="0" step="1" onChange={e => {
|
||||
updateSettings({stickDistance:parseInt(e.target.value)});
|
||||
setStickDistance(settingList.stickDistance);
|
||||
}}/>
|
||||
</div>
|
||||
<div className="dataDiv">
|
||||
<p>Stick Mode:</p>
|
||||
<label htmlFor="stickMode" className="toggle-switchy" data-style="rounded" data-text="12">
|
||||
<input checked={stickMode2} type="checkbox" id="stickMode" onChange={e => {
|
||||
updateSettings({stickMode2:e.target.checked});
|
||||
setStickMode2(settingList.stickMode2);
|
||||
}}/>
|
||||
<span className="toggle">
|
||||
<span className="switch"></span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<button onClick={() => {
|
||||
settingListLoadDefault();
|
||||
|
||||
setFps(settingList.fps);
|
||||
setWidth(settingList.width);
|
||||
setStickDistance(settingList.stickDistance);
|
||||
setStickMode2(settingList.stickMode2);
|
||||
}}>Reset Settings</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SettingsSide;
|
||||
@@ -1,14 +0,0 @@
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
background-color: #172336;
|
||||
color: white;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.dataDiv {
|
||||
display: flex;
|
||||
}
|
||||
.dataDiv p {
|
||||
margin-right: 10px;
|
||||
}
|
||||
104
src/index.css
Normal file
104
src/index.css
Normal file
@@ -0,0 +1,104 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #172336;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.dataDiv {
|
||||
display: flex;
|
||||
}
|
||||
.dataDiv p {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #9DA8B9;
|
||||
border-radius: 5px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: #0d131e;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding: 20px 25px;
|
||||
background-color: #0d131e;
|
||||
height: 20px;
|
||||
color: #9DA8B9;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
header h1 {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#settings-back {
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
background-color: #2196F3;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
#settings-back:hover {
|
||||
transform: scale(1.05);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#content {
|
||||
padding-left: 25px;
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
#settings-button {
|
||||
cursor: pointer;
|
||||
background-color: #2196F3;
|
||||
border-radius: 50%;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
align-items: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
#settings-button svg {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
fill: white;
|
||||
margin-left: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
#settings-button:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
#update-available {
|
||||
cursor: pointer;
|
||||
background-color: #21f3ad;
|
||||
border-radius: 20%;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
align-items: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin-right: 15px;
|
||||
display: none;
|
||||
}
|
||||
#update-available svg {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
fill: white;
|
||||
margin-left: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
#update-available:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
@@ -1,50 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
|
||||
<meta charset="UTF-8" />
|
||||
<title>StickExporterTX</title>
|
||||
|
||||
<link rel="stylesheet" href="./css/style.css"/>
|
||||
<link rel="stylesheet" href="./css/toggle-switchy.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<button onclick="startRender()">Start Render</button>
|
||||
<p id="logNumber">Log 0/0</p>
|
||||
<div class="dataDiv">
|
||||
<p id="status">Idle</p>
|
||||
<button onclick="openOutputFolder()">Open Output Folder</button>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="dataDiv">
|
||||
<p>FPS: </p>
|
||||
<input id="fpsInput" type="number" value="25" min="1" step="1" onchange="setFPS();">
|
||||
</div>
|
||||
<div class="dataDiv">
|
||||
<p>Width: </p>
|
||||
<input id="widthInput" type="number" value="540" min="1" step="1" onchange="setWidth();">
|
||||
</div>
|
||||
<div class="dataDiv">
|
||||
<p>Stick Distance: </p>
|
||||
<input id="stickDistanceInput" type="number" value="540" min="0" step="1" onchange="setStickDistance();">
|
||||
</div>
|
||||
<div class="dataDiv">
|
||||
<p>Stick Mode:</p>
|
||||
<label for="stickMode" class="toggle-switchy" data-style="rounded" data-text="12">
|
||||
<input checked type="checkbox" id="stickMode" onchange="setStickMode();">
|
||||
<span class="toggle">
|
||||
<span class="switch"></span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="dataDiv">
|
||||
<p id="log">Logs:<br/></p>
|
||||
<button onclick="openLog();">Open Log</button>
|
||||
</div>
|
||||
<div class="dataDiv">
|
||||
<p id="output">Output Folder: </p>
|
||||
<button onclick="openVid();">Open Video</button>
|
||||
</div>
|
||||
<script src="./js/render.js"></script>
|
||||
<body style="background-color: #172336;margin:0;padding:0;color:white;font-family:sans-serif;">
|
||||
<div id="root"></div>
|
||||
|
||||
<script src="./.webpack/renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,5 @@
|
||||
const { app, BrowserWindow } = require('electron');
|
||||
const path = require('path');
|
||||
import {app, BrowserWindow} from 'electron';
|
||||
import {initialize as remoteInitialize, enable as remoteEnable} from '@electron/remote/main';
|
||||
|
||||
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
||||
if (require('electron-squirrel-startup')) {
|
||||
@@ -14,21 +14,20 @@ const createWindow = () => {
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
enableRemoteModule: true
|
||||
contextIsolation: false
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.setMenu(null);
|
||||
if(app.isPackaged) mainWindow.setMenu(null);
|
||||
|
||||
require('@electron/remote/main').initialize();
|
||||
require("@electron/remote/main").enable(mainWindow.webContents);
|
||||
remoteInitialize();
|
||||
remoteEnable(mainWindow.webContents);
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile(path.join(__dirname, 'index.html'));
|
||||
mainWindow.loadFile("src/index.html");
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools();
|
||||
if(!app.isPackaged) mainWindow.webContents.openDevTools();
|
||||
};
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
@@ -54,4 +53,4 @@ app.on('activate', () => {
|
||||
});
|
||||
|
||||
// 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.
|
||||
// code. You can also put them in separate files and import them here.
|
||||
205
src/js/render.js
205
src/js/render.js
@@ -1,205 +0,0 @@
|
||||
var lastData = "Initialise..."
|
||||
var frames = "0";
|
||||
var lastFrame = "0";
|
||||
var logCount = 0;
|
||||
|
||||
var fps = 25
|
||||
var width = 540
|
||||
var stickDistance = 5
|
||||
var stickMode2 = true
|
||||
var log = '"None"'
|
||||
var output = "None"
|
||||
|
||||
const statusDisplay = document.getElementById("status");
|
||||
const fpsDisplay = document.getElementById("fpsInput");
|
||||
const widthDistplay = document.getElementById("widthInput");
|
||||
const stickDistanceDisplay = document.getElementById("stickDistanceInput");
|
||||
const stickModeDisplay = document.getElementById("stickMode");
|
||||
const logDisplay = document.getElementById("log");
|
||||
const outputDisplay = document.getElementById("output");
|
||||
const logNumberDisplay = document.getElementById("logNumber");
|
||||
|
||||
const logger = require('electron-log');
|
||||
const fs = require("fs");
|
||||
const formatXml = require("xml-formatter");
|
||||
const {dialog, app} = require("@electron/remote");
|
||||
const path = require('path');
|
||||
|
||||
const dataFolder = app.getPath('userData');
|
||||
const SettingFolder = path.join(dataFolder, "settings.xml");
|
||||
|
||||
const blenderPath = path.join("assets", "blender", "blender");
|
||||
const templatePath = path.join("assets", "template.blend");
|
||||
const blenderScriptPath = path.join("assets", "blenderScript.py");
|
||||
|
||||
logger.transports.console.format = "{h}:{i}:{s} {text}";
|
||||
logger.transports.file.getFile();
|
||||
logger.transports.file.resolvePath = () => path.join(dataFolder, "logs", "main.log");
|
||||
|
||||
function startRender() {
|
||||
const {exec} = require("child_process");
|
||||
var blenderCons = exec('"' + blenderPath + '" "' + templatePath + '" --background --python "' + blenderScriptPath + '" -- "' + SettingFolder.replaceAll('\\', '/') + '"', {maxBuffer: Infinity});
|
||||
|
||||
frames = "0";
|
||||
lastFrame = "0";
|
||||
statusDisplay.innerHTML = lastData = "Initialise...";
|
||||
statusDisplay.style.color = "white";
|
||||
logNumberDisplay.innerHTML = "Log 0/" + String(logCount);
|
||||
blenderCons.stdout.on("data", (data) => {
|
||||
var dataStr = String(data);
|
||||
logger.info(dataStr);
|
||||
|
||||
if(dataStr.startsWith("Frames:")) {
|
||||
frames = dataStr.split(":")[1];
|
||||
} else if(dataStr.startsWith("Fra:")) {
|
||||
lastFrame = dataStr.split(":")[1].split(" ")[0]
|
||||
lastData = "Render Frame " + lastFrame + "/" + frames;
|
||||
} else if(dataStr.startsWith("Finished")) {
|
||||
if(lastFrame == frames) {
|
||||
lastData = "Finished Render Successfully!"
|
||||
statusDisplay.style.color = "white";
|
||||
} else {
|
||||
lastData = "Something went wrong! Check Logs."
|
||||
statusDisplay.style.color = "red";
|
||||
}
|
||||
} else if(dataStr.includes("Blender quit")) {
|
||||
if(lastData != "Finished Render Successfully!") {
|
||||
lastData = "Something went wrong! Check Logs.";
|
||||
statusDisplay.style.color = "red";
|
||||
}
|
||||
} else if(dataStr.startsWith("Init:")) {
|
||||
lastData = "Initialize Frame " + dataStr.split(":")[1] + "/" + frames;
|
||||
} else if(dataStr.startsWith("Lognr:")) {
|
||||
logNumberDisplay.innerHTML = "Log " + dataStr.split(":")[1] + "/" + String(logCount);
|
||||
}
|
||||
|
||||
if(statusDisplay.innerHTML != lastData) {
|
||||
statusDisplay.innerHTML = lastData;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getXMLChild(doc, child) {
|
||||
return String(doc.getElementsByTagName(child)[0].childNodes[0].nodeValue);
|
||||
}
|
||||
|
||||
function updateSettingDisplay() {
|
||||
fpsDisplay.value = String(fps);
|
||||
widthDistplay.value = String(width);
|
||||
stickDistanceDisplay.value = String(stickDistance);
|
||||
stickModeDisplay.checked = stickMode2;
|
||||
logDisplay.innerHTML = "Logs:<br/>" + log.substring(1).slice(0, -1).replaceAll("\"\"", "<br/>");
|
||||
outputDisplay.innerHTML = "Output Folder: " + output;
|
||||
logCount = log.split("\"\"").length;
|
||||
logNumberDisplay.innerHTML = "Log 0/" + String(logCount);
|
||||
}
|
||||
|
||||
function updateSettings() {
|
||||
var xmlStr = '<?xml version="1.0"?><settings><fps>' + String(fps) +
|
||||
'</fps><width>' + String(width) +
|
||||
'</width><stickDistance>' + String(stickDistance) +
|
||||
'</stickDistance><stickMode2>' + ((stickMode2)?"true":"false") +
|
||||
'</stickMode2><log>' + log +
|
||||
'</log><output>' + output +
|
||||
'</output></settings>';
|
||||
|
||||
fs.writeFile(SettingFolder, formatXml(xmlStr, {collapseContent: true}), function(err) {
|
||||
if(err) {
|
||||
statusDisplay.innerHTML = "Couldn't write Log! Check Logs.";
|
||||
statusDisplay.style.color = "red";
|
||||
logger.error(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fetch(SettingFolder).then(function(response){
|
||||
return response.text();
|
||||
}).then(function(data){
|
||||
let parser = new DOMParser();
|
||||
let xmlDoc = parser.parseFromString(data, 'text/xml');
|
||||
|
||||
fps = parseInt(getXMLChild(xmlDoc, "fps"));
|
||||
width = parseInt(getXMLChild(xmlDoc, "width"));
|
||||
stickDistance = parseInt(getXMLChild(xmlDoc, "stickDistance"));
|
||||
if(getXMLChild(xmlDoc, "stickMode2") == "false") {
|
||||
stickMode2 = false;
|
||||
} else {
|
||||
stickMode2 = true;
|
||||
}
|
||||
log = getXMLChild(xmlDoc, "log");
|
||||
output = getXMLChild(xmlDoc, "output");
|
||||
|
||||
updateSettingDisplay();
|
||||
}).catch(function(error) {
|
||||
logger.error(error);
|
||||
updateSettingDisplay();
|
||||
updateSettings();
|
||||
});
|
||||
|
||||
function openLog() {
|
||||
dialog.showOpenDialog({
|
||||
properties: [
|
||||
"multiSelections"
|
||||
],
|
||||
filters: [
|
||||
{
|
||||
name: "TX-Logs",
|
||||
extensions: [
|
||||
"csv"
|
||||
]
|
||||
}
|
||||
]
|
||||
}).then(result => {
|
||||
logStr = "";
|
||||
result.filePaths.forEach(value => {
|
||||
logStr += "\"" + String(value) + "\"";
|
||||
});
|
||||
log = logStr;
|
||||
updateSettingDisplay();
|
||||
updateSettings();
|
||||
}).catch(err => {
|
||||
statusDisplay.innerHTML = "Something went wrong! Check Logs.";
|
||||
statusDisplay.style.color = "red";
|
||||
logger.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
function openVid() {
|
||||
dialog.showOpenDialog({
|
||||
properties: [
|
||||
"openDirectory"
|
||||
]
|
||||
}).then(result => {
|
||||
output = String(result.filePaths);
|
||||
updateSettingDisplay();
|
||||
updateSettings();
|
||||
}).catch(err => {
|
||||
statusDisplay.innerHTML = "Something went wrong! Check Logs.";
|
||||
statusDisplay.style.color = "red";
|
||||
logger.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
function setFPS() {
|
||||
fps = parseInt(fpsDisplay.value);
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
function setWidth() {
|
||||
width = parseInt(widthDistplay.value);
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
function setStickDistance() {
|
||||
stickDistance = parseInt(stickDistanceDisplay.value);
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
function setStickMode() {
|
||||
stickMode2 = stickModeDisplay.checked;
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
function openOutputFolder() {
|
||||
require("child_process").exec('start "" "' + output + '"');
|
||||
}
|
||||
30
src/renderer.tsx
Normal file
30
src/renderer.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import Menu from "./components/ui/menu";
|
||||
import MainSide from "./components/ui/mainSide";
|
||||
import SettingsSite from "./components/ui/settingsSide";
|
||||
import "./index.css";
|
||||
import "./toggle-switchy.css";
|
||||
|
||||
enum Side {
|
||||
Main,
|
||||
Settings
|
||||
}
|
||||
|
||||
function openSide(side:Side) {
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<Menu updateAvailable={true} side={side}/>
|
||||
{(side == Side.Main)? <MainSide/> : <SettingsSite/>}
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root'));
|
||||
}
|
||||
|
||||
openSide(Side.Main);
|
||||
|
||||
|
||||
|
||||
export {
|
||||
openSide,
|
||||
Side,
|
||||
}
|
||||
110
tsconfig.json
Normal file
110
tsconfig.json
Normal file
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "es2018", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
"lib": [
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
"ESNext"
|
||||
], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
"jsx": "react", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "esnext", /* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
"baseUrl": ".", /* Specify the base directory to resolve non-relative module names. */
|
||||
"paths": {
|
||||
"*": ["node_modules/*"]
|
||||
}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
"resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
"sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
"outDir": "dist", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
"noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
"isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
"allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
},
|
||||
"include": ["src/**/*", "js"]
|
||||
}
|
||||
Reference in New Issue
Block a user