New setting-save method

This commit is contained in:
2022-11-23 15:04:29 +01:00
parent f585c81d38
commit c768cf225f
8 changed files with 249 additions and 142 deletions

View File

@@ -4,7 +4,7 @@ import logger from "./logger";
import { setBlenderLoading, setBlenderStatus } from "./ui/menu";
import { setLogNumber, setPastTime, setRemainingTime, setRenderDisplayProgress, setStatus, setPastTimeNow, setRemainingTimeNow } from "./ui/renderingPage";
import {imageLoading, imageLoaded} from "./ui/settingsPage";
import { getLogList, getLogSize, settingList } from "./settings";
import { getLogSize, getInOutSettings } from "./settings";
import isValid from "is-valid-path";
import { pageSetRendering, setProgress, openPage, Page } from "../renderer";
import { ipcRenderer } from "electron";
@@ -198,15 +198,15 @@ function blender(command:blenderCmd) {
}
} else if(command === blenderCmd.startRendering) {
if(readyToAcceptCommand) {
if(settingList.log == "") {
if(getInOutSettings().log == "") {
logger.warningMSG("No log selected!");
} else if(!isValid(settingList.log)) {
} else if(!isValid(getInOutSettings().log)) {
logger.warningMSG("Output path is invalid!");
} else {
currentLogPortion = 0;
const logSizeList:number[] = [];
getLogList().forEach(function (value, index) {
getInOutSettings().logList.forEach(function (value, index) {
logSizeList.push(getLogSize(index));
});

View File

@@ -1,8 +1,9 @@
import logger from "./logger";
import {parse as csvParse} from "csv-parse";
import {settingList} from "./settings";
import {getInOutSettings} from "./settings";
import {platformCharacter} from "./paths";
import {formatDate} from "./dateFormat";
import fs from "fs";
async function openLogFile(filePath:string, rawData:boolean) {
const data = await fetch(filePath).then(function(response) {
@@ -162,8 +163,8 @@ async function getLogTime(filePath:string) {
async function getAllLogs() {
const loadList = [];
if(settingList.log.length > 0) {
const logs = settingList.log.substring(1).slice(0, -1).split('""');
if(getInOutSettings().log.length > 0) {
const logs = getInOutSettings().log.substring(1).slice(0, -1).split('""');
for(const log of logs) {
loadList.push({
@@ -184,8 +185,8 @@ async function reloadAllLogs() {
}
async function updateLogs() {
if(settingList.log.length > 0) {
const logs = settingList.log.substring(1).slice(0, -1).split('""');
if(getInOutSettings().log.length > 0) {
const logs = getInOutSettings().log.substring(1).slice(0, -1).split('""');
for(const log of logs) {
if(!logList.some(x => x.path === log)) {
logList.push({
@@ -206,8 +207,20 @@ async function updateLogs() {
}
}
function getLogList() {
return getInOutSettings().log.split("\"\"");
}
function getLogSize(index:number) {
const logList = getInOutSettings().log.substring(1).slice(0, -1).split('""');
return fs.statSync(logList[index]).size;
}
export {
reloadAllLogs,
logList,
updateLogs
updateLogs,
getLogList,
getLogSize
};

View File

@@ -4,7 +4,8 @@ import { platformFolder, platform, Platform } from './platform';
export const dataPath = app.getPath('userData');
export const appPath = app.getAppPath().replace("app.asar", "");
export const SettingPath = path.join(dataPath, "settings.xml");
export const SettingPath = path.join(dataPath, "settings.json");
export const OLDSettingPath = path.join(dataPath, "settings.xml");
export const defaultOutputPath = path.join(app.getPath('videos'), "StickExporterTX");

View File

@@ -1,11 +1,6 @@
import formatXML from "xml-formatter";
import {SettingPath, defaultOutputPath} from './paths';
import fs from "fs";
import {SettingPath, defaultOutputPath, OLDSettingPath} from './paths';
import logger from "./logger";
function getXMLChild(doc:Document, child:string) {
return String(doc.getElementsByTagName(child)[0].childNodes[0].nodeValue);
}
import fs from "fs";
enum VideoFormat {
mp4="mp4",
@@ -15,36 +10,68 @@ enum VideoFormat {
mkv="mkv",
}
const defaultSettings = {
type JSONProfile = {
profileName: string,
fps: number,
width: number,
stickDistance: number,
stickMode2: boolean,
videoFormat: VideoFormat
};
type JSONSettings = {
activeProfile: string,
profiles: JSONProfile[],
log: string,
output: string,
}
const defaultSettings:JSONSettings = {
activeProfile: "Default",
profiles: [
{
profileName: "Default",
fps: 30,
width: 540,
stickDistance: 5,
stickMode2: true,
videoFormat: VideoFormat.webm,
videoFormat: VideoFormat.webm
}
],
log: '',
output: defaultOutputPath
}
};
let allSettingsFound = true;
function catchSetting(tryFunc:()=>string, catchFunc:()=>string) {
let val;
try {
val = tryFunc();
} catch(err) {
logger.info("Failed to get setting value. Using default value:" + String(err));
allSettingsFound = false;
val = catchFunc();
}
return val;
}
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();
}).catch(function(err) {
logger.info(err);
return "fileLoadFailed";
}).then(function(data) {
}).then(async function(data) {
if(data === "fileLoadFailed") {
return await fetch(OLDSettingPath).then(function(response) {
return response.text();
}).catch(function(err) {
logger.info(err);
return "fileLoadFailed";
}).then(function(data) {
if(data === "fileLoadFailed") {
allSettingsFound = false;
return defaultSettings;
}
@@ -52,88 +79,150 @@ const settingList = await fetch(SettingPath).then(function(response) {
const xmlDoc = parser.parseFromString(data, 'text/xml');
return {
fps: parseInt(catchSetting(function() {return getXMLChild(xmlDoc, "fps");},function() {return defaultSettings.fps.toString();})),
width: parseInt(catchSetting(function() {return getXMLChild(xmlDoc, "width");},function() {return defaultSettings.width.toString();})),
stickDistance: parseInt(catchSetting(function() {return getXMLChild(xmlDoc, "stickDistance");},function() {return defaultSettings.stickDistance.toString();})),
stickMode2: catchSetting(function() {return getXMLChild(xmlDoc, "stickMode2");},function() {return defaultSettings.stickMode2.toString();}) === "true",
videoFormat: catchSetting(function() {return getXMLChild(xmlDoc, "videoFormat");},function() {return defaultSettings.videoFormat.toString();}) as VideoFormat as VideoFormat,
activeProfile: defaultSettings.activeProfile,
profiles: [
{
profileName: defaultSettings.profiles[0].profileName,
fps: parseInt(catchSetting(function() {return getXMLChild(xmlDoc, "fps");},function() {return defaultSettings.profiles[0].fps.toString();})),
width: parseInt(catchSetting(function() {return getXMLChild(xmlDoc, "width");},function() {return defaultSettings.profiles[0].width.toString();})),
stickDistance: parseInt(catchSetting(function() {return getXMLChild(xmlDoc, "stickDistance");},function() {return defaultSettings.profiles[0].stickDistance.toString();})),
stickMode2: catchSetting(function() {return getXMLChild(xmlDoc, "stickMode2");},function() {return defaultSettings.profiles[0].stickMode2.toString();}) === "true",
videoFormat: catchSetting(function() {return getXMLChild(xmlDoc, "videoFormat");},function() {return defaultSettings.profiles[0].videoFormat.toString();}) as VideoFormat as VideoFormat
}
],
log: catchSetting(function() {return (getXMLChild(xmlDoc, "log") === "None")? "":getXMLChild(xmlDoc, "log");},function() {return defaultSettings.log;}),
output: catchSetting(function() {return getXMLChild(xmlDoc, "output");},function() {return defaultSettings.output;})
} as JSONSettings;
});
}
return JSON.parse(data) as JSONSettings;
});
if(!allSettingsFound) {
updateSettings({});
function createProfile(profileName:string, clone:boolean) {
settingList.profiles.push({
profileName: profileName,
fps: clone? getActiveProfile().fps:defaultSettings.profiles[0].fps,
width: clone? getActiveProfile().width:defaultSettings.profiles[0].width,
stickDistance: clone? getActiveProfile().stickDistance:defaultSettings.profiles[0].stickDistance,
stickMode2: clone? getActiveProfile().stickMode2:defaultSettings.profiles[0].stickMode2,
videoFormat: clone? getActiveProfile().videoFormat:defaultSettings.profiles[0].videoFormat
});
writeSettings();
}
function updateSettings(optiones:{fps?:number, width?:number, stickDistance?:number, stickMode2?:boolean, videoFormat?:VideoFormat, 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.videoFormat === undefined) {
optiones.videoFormat = settingList.videoFormat;
} else {
settingList.videoFormat = optiones.videoFormat;
}
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;
function ProfileLoadDefault(profileName?:string) {
if(profileName === undefined) {
profileName = getActiveProfile().profileName;
}
const xmlStr = `
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<fps>${optiones.fps}</fps>
<width>${optiones.width}</width>
<stickDistance>${optiones.stickDistance}</stickDistance>
<stickMode2>${optiones.stickMode2}</stickMode2>
<videoFormat>${optiones.videoFormat}</videoFormat>
<log>${(optiones.log === "")?"None":optiones.log}</log>
<output>${optiones.output}</output>
</settings>
`;
settingList.profiles.forEach(profile => {
if(profile.profileName === profileName) {
profile.fps = defaultSettings.profiles[0].fps;
profile.width = defaultSettings.profiles[0].width;
profile.stickDistance = defaultSettings.profiles[0].stickDistance;
profile.stickMode2 = defaultSettings.profiles[0].stickMode2;
profile.videoFormat = defaultSettings.profiles[0].videoFormat;
}
});
fs.writeFile(SettingPath, formatXML(xmlStr, {collapseContent: true}), function(err) {
writeSettings();
}
function editProfile(optiones:{fps?:number, width?:number, stickDistance?:number, stickMode2?:boolean, videoFormat?:VideoFormat}, profileName?:string) {
if(profileName === undefined) {
profileName = getActiveProfile().profileName;
}
settingList.profiles.forEach(profile => {
if(profile.profileName === profileName) {
if(optiones.fps !== undefined) {
profile.fps = optiones.fps;
}
if(optiones.width !== undefined) {
profile.width = optiones.width;
}
if(optiones.stickDistance !== undefined) {
profile.stickDistance = optiones.stickDistance;
}
if(optiones.stickMode2 !== undefined) {
profile.stickMode2 = optiones.stickMode2;
}
if(optiones.videoFormat !== undefined) {
profile.videoFormat = optiones.videoFormat;
}
}
});
writeSettings();
}
function setInOutSettings(args:{log?:string, output?:string}) {
if(args.log !== undefined) {
settingList.log = args.log;
}
if(args.output !== undefined) {
settingList.output = args.output;
}
writeSettings();
}
function getInOutSettings() {
return {log: settingList.log, output: settingList.output, logList:settingList.log.split("\"\"")};
}
function removeProfile(profileName?:string) {
if(profileName === undefined) {
profileName = getActiveProfile().profileName;
}
settingList.profiles.forEach(profile => {
if(profile.profileName === profileName) {
settingList.profiles.splice(settingList.profiles.indexOf(profile), 1);
}
});
writeSettings();
}
function setActiveProfile(profileName:string) {
settingList.profiles.forEach(profile => {
if(profile.profileName === profileName) {
settingList.activeProfile = profile.profileName;
}
});
writeSettings();
}
function writeSettings(settings?:JSONSettings) {
if(settings === undefined) {
settings = settingList;
}
fs.writeFile(SettingPath, JSON.stringify(settings), function(err) {
if(err) {
logger.errorMSG(String(err));
}
});
}
function settingListLoadDefault() {
updateSettings({
fps:defaultSettings.fps,
width:defaultSettings.width,
stickDistance:defaultSettings.stickDistance,
stickMode2:defaultSettings.stickMode2,
videoFormat:defaultSettings.videoFormat,
function getActiveProfile() {
let activeProfile;
settingList.profiles.forEach(profile => {
if(profile.profileName === settingList.activeProfile) {
activeProfile = profile;
}
});
}
function getLogList() {
return settingList.log.split("\"\"");
if(activeProfile === undefined) {
activeProfile = settingList.profiles[0];
logger.errorMSG("Active profile not found, using default profile");
}
return activeProfile;
}
function getLogSize(index:number) {
@@ -143,10 +232,14 @@ function getLogSize(index:number) {
}
export {
updateSettings,
settingListLoadDefault,
settingList,
getLogList,
createProfile,
ProfileLoadDefault,
editProfile,
removeProfile,
setActiveProfile,
getActiveProfile,
setInOutSettings,
getInOutSettings,
getLogSize,
VideoFormat
}

View File

@@ -1,6 +1,6 @@
import React, {useEffect, useState} from "react";
import { dialog } from "@electron/remote";
import { settingList, updateSettings } from "../settings";
import { setInOutSettings, getInOutSettings } from "../settings";
import logger from "../logger";
import {blender, blenderCmd} from "../blenderController";
import openFolder from "../openFolder";
@@ -8,7 +8,7 @@ import {platformCharacter} from "../paths";
import {logList, reloadAllLogs, updateLogs} from "../logReader";
function MainPage() {
const [output, setOutput] = useState(settingList.output);
const [output, setOutput] = useState(getInOutSettings().output);
const [logTable, setLogTable] = useState([<tr key={0}></tr>]);
useEffect(() => {
@@ -32,14 +32,14 @@ function MainPage() {
<div className="dataDiv">
<button id="openLogButton" onClick={() => addLog(setLogTable)}>Add Log(s)</button>
<button id="deleteLogsButton" onClick={async () => {
updateSettings({log:""});
setInOutSettings({log:""});
await reloadAllLogs();
updateLogTable(setLogTable);
}}>Delete All</button>
</div>
<div className="dataDiv" id="outputDiv">
<h4>Output Folder:</h4>
<p id="output" onClick={() => openFolder(settingList.output)}>{output}</p>
<p id="output" onClick={() => openFolder(getInOutSettings().output)}>{output}</p>
<button onClick={() => openVid(setOutput)}>Select Folder</button>
</div>
</div>
@@ -60,8 +60,8 @@ function updateLogTable(setLogTable:React.Dispatch<React.SetStateAction<JSX.Elem
fontWeight: "lighter"
}}>({log.time.length.formatted})</td>
<td><button className="listButton" onClick={async () => {
const newLogs = settingList.log.replace('"'+log.path+'"', "");
updateSettings({log:newLogs});
const newLogs = getInOutSettings().log.replace('"'+log.path+'"', "");
setInOutSettings({log:newLogs});
await updateLogs();
updateLogTable(setLogTable);
}}>Delete</button></td>
@@ -69,7 +69,7 @@ function updateLogTable(setLogTable:React.Dispatch<React.SetStateAction<JSX.Elem
}));
}
if(settingList.log == "") {
if(getInOutSettings().log == "") {
setLogTable([]);
} else {
getData();
@@ -93,14 +93,14 @@ function addLog(setLogTable:React.Dispatch<React.SetStateAction<JSX.Element[]>>)
let logStr = "";
result.filePaths.forEach(value => {
const logToAdd = "\"" + value + "\"";
if(settingList.log.includes(logToAdd)) {
if(getInOutSettings().log.includes(logToAdd)) {
logger.warningMSG("Log " + logToAdd + " already added.");
} else {
logStr += "\"" + String(value) + "\"";
}
});
const newLogs = settingList.log + logStr;
updateSettings({log:newLogs});
const newLogs = getInOutSettings().log + logStr;
setInOutSettings({log:newLogs});
await updateLogs();
updateLogTable(setLogTable);
}).catch(err => {
@@ -115,7 +115,7 @@ function openVid(updateHook:React.Dispatch<React.SetStateAction<string>>) {
]
}).then(result => {
if(result.filePaths.length > 0) {
updateSettings({output:String(result.filePaths)});
setInOutSettings({output:String(result.filePaths)});
updateHook(String(result.filePaths));
}
}).catch(err => {

View File

@@ -2,7 +2,7 @@ import React, { CSSProperties } from "react";
import {openPage, Page} from "../../renderer";
import {renderInfo} from "../blenderController";
import openFolder from "../openFolder";
import {settingList} from "../settings";
import {getInOutSettings, getActiveProfile} from "../settings";
import VideoPlayer from "./videoPlayer";
import path from 'path';
import {platformCharacter} from "../paths";
@@ -19,7 +19,7 @@ const detailsInnerStyle:CSSProperties = {
}
function RenderFinishPage() {
const [logPlaying, setLogPlaying] = React.useState(path.join(settingList.output, settingList.log.substring(1).slice(0, -1).split('""')[0].split(platformCharacter())[settingList.log.substring(1).slice(0, -1).split('""')[0].split(platformCharacter()).length - 1].replace(".csv", "."+settingList.videoFormat)));
const [logPlaying, setLogPlaying] = React.useState(path.join(getInOutSettings().output, getInOutSettings().log.substring(1).slice(0, -1).split('""')[0].split(platformCharacter())[getInOutSettings().log.substring(1).slice(0, -1).split('""')[0].split(platformCharacter()).length - 1].replace(".csv", "."+getActiveProfile().videoFormat)));
const [outputList, setOutputList] = React.useState([<li key={0}></li>]);
@@ -32,11 +32,11 @@ function RenderFinishPage() {
}
};
const [videoSource, setVideoSource] = React.useState({src: logPlaying, type: 'video/'+settingList.videoFormat.toUpperCase()});
const [videoSource, setVideoSource] = React.useState({src: logPlaying, type: 'video/'+getActiveProfile().videoFormat.toUpperCase()});
React.useEffect(() => {
setOutputList(logList.map((inputLog, index) => {
const outputLogPath = path.join(settingList.output, inputLog.name+"."+settingList.videoFormat);
const outputLogPath = path.join(getInOutSettings().output, inputLog.name+"."+getActiveProfile().videoFormat);
return <li key={index}>
<p style={{
@@ -50,7 +50,7 @@ function RenderFinishPage() {
setVideoSource({
src: logPlaying,
type: 'video/'+settingList.videoFormat.toUpperCase()
type: 'video/'+getActiveProfile().videoFormat.toUpperCase()
});
}, [logPlaying]);
@@ -78,7 +78,7 @@ function RenderFinishPage() {
}} onClick={() => {
openPage(Page.Main);
}}>Finish</button>
<button onClick={() => openFolder(settingList.output)}>Open Output Folder</button>
<button onClick={() => openFolder(getInOutSettings().output)}>Open Output Folder</button>
<div style={{
marginTop: "10px"
}}>

View File

@@ -1,5 +1,5 @@
import React, {useEffect, useState} from "react";
import { settingList, getLogList } from "../settings";
import {getInOutSettings} from "../settings";
import openFolder from "../openFolder";
import { blenderCmd, blender } from "../blenderController";
@@ -34,7 +34,7 @@ function RenderingPage() {
return (
<div id="content">
<p>{"Log " + logNumber + "/" + getLogList().length}</p>
<p>{"Log " + logNumber + "/" + getInOutSettings().logList.length}</p>
<p>{status}</p>
<div className="progress">
<div className="progress-done" style={{
@@ -69,7 +69,7 @@ function RenderingPage() {
}>{remainingTime}</p>
</div>
<button id="stopRenderButton" onClick={() => blender(blenderCmd.stopRendering)}>Stop</button>
<button onClick={() => openFolder(settingList.output)}>Open Output Folder</button>
<button onClick={() => openFolder(getInOutSettings().output)}>Open Output Folder</button>
</div>
)
}

View File

@@ -1,5 +1,5 @@
import React, {useState, useEffect, CSSProperties} from "react";
import { settingList, updateSettings, settingListLoadDefault, VideoFormat } from "../settings";
import { VideoFormat, editProfile, getActiveProfile, ProfileLoadDefault } from "../settings";
import {blender, blenderCmd, renderingPicture} from "../blenderController";
import {dataPath} from "../paths";
import path from "path";
@@ -59,11 +59,11 @@ function VideoFormatWarning({videoFormat}:{videoFormat:VideoFormat}) {
function SettingsPage() {
const [fps, setFps] = useState(settingList.fps);
const [width, setWidth] = useState(settingList.width);
const [stickDistance, setStickDistance] = useState(settingList.stickDistance);
const [stickMode2, setStickMode2] = useState(settingList.stickMode2);
const [videoFormat, setVideoFormat] = useState(settingList.videoFormat);
const [fps, setFps] = useState(getActiveProfile().fps);
const [width, setWidth] = useState(getActiveProfile().width);
const [stickDistance, setStickDistance] = useState(getActiveProfile().stickDistance);
const [stickMode2, setStickMode2] = useState(getActiveProfile().stickMode2);
const [videoFormat, setVideoFormat] = useState(getActiveProfile().videoFormat);
const [renderImg, setRenderImgInner] = useState(picturePath());
setRenderImg = setRenderImgInner;
const [renderLoading, setRenderLoadingInner] = useState(renderingPicture);
@@ -71,7 +71,7 @@ function SettingsPage() {
useEffect(() => {
const timer = setTimeout(() => {
updateSettings({width, stickDistance, stickMode2});
editProfile({width, stickDistance, stickMode2});
blender(blenderCmd.getRender);
}, 500);
@@ -80,7 +80,7 @@ function SettingsPage() {
useEffect(() => {
const timer = setTimeout(() => {
updateSettings({fps, videoFormat});
editProfile({fps, videoFormat});
}, 500);
return () => clearTimeout(timer);
@@ -140,13 +140,13 @@ function SettingsPage() {
{videoFormat === VideoFormat.avi? <VideoFormatWarning videoFormat={videoFormat}/> : null}
</span>
<button id="resetSettingsButton" onClick={() => {
settingListLoadDefault();
ProfileLoadDefault();
setFps(settingList.fps);
setWidth(settingList.width);
setStickDistance(settingList.stickDistance);
setStickMode2(settingList.stickMode2);
setVideoFormat(settingList.videoFormat);
setFps(getActiveProfile().fps);
setWidth(getActiveProfile().width);
setStickDistance(getActiveProfile().stickDistance);
setStickMode2(getActiveProfile().stickMode2);
setVideoFormat(getActiveProfile().videoFormat);
}}>Reset Settings</button>
</div>
<div id="renderImgDiv">