From c768cf225f0548e48c1682e4bf02cdc873bc871f Mon Sep 17 00:00:00 2001 From: Lino Schmidt Date: Wed, 23 Nov 2022 15:04:29 +0100 Subject: [PATCH] New setting-save method --- src/components/blenderController.ts | 8 +- src/components/logReader.ts | 25 ++- src/components/paths.ts | 3 +- src/components/settings.ts | 287 ++++++++++++++++--------- src/components/ui/mainPage.tsx | 22 +- src/components/ui/renderFinishPage.tsx | 12 +- src/components/ui/renderingPage.tsx | 6 +- src/components/ui/settingsPage.tsx | 28 +-- 8 files changed, 249 insertions(+), 142 deletions(-) diff --git a/src/components/blenderController.ts b/src/components/blenderController.ts index 4fc8d9e..398265c 100644 --- a/src/components/blenderController.ts +++ b/src/components/blenderController.ts @@ -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)); }); diff --git a/src/components/logReader.ts b/src/components/logReader.ts index 9890691..0c7dfc9 100644 --- a/src/components/logReader.ts +++ b/src/components/logReader.ts @@ -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 }; \ No newline at end of file diff --git a/src/components/paths.ts b/src/components/paths.ts index ab53202..928b97c 100644 --- a/src/components/paths.ts +++ b/src/components/paths.ts @@ -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"); diff --git a/src/components/settings.ts b/src/components/settings.ts index c7c92b0..f24252a 100644 --- a/src/components/settings.ts +++ b/src/components/settings.ts @@ -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,125 +10,219 @@ enum VideoFormat { mkv="mkv", } -const defaultSettings = { - fps: 30, - width: 540, - stickDistance: 5, - stickMode2: true, - videoFormat: VideoFormat.webm, - log: '', - output: defaultOutputPath +type JSONProfile = { + profileName: string, + fps: number, + width: number, + stickDistance: number, + stickMode2: boolean, + videoFormat: VideoFormat +}; + +type JSONSettings = { + activeProfile: string, + profiles: JSONProfile[], + log: string, + output: string, } -let allSettingsFound = true; +const defaultSettings:JSONSettings = { + activeProfile: "Default", + profiles: [ + { + profileName: "Default", + fps: 30, + width: 540, + stickDistance: 5, + stickMode2: true, + videoFormat: VideoFormat.webm + } + ], + log: '', + output: defaultOutputPath +}; + 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") { - allSettingsFound = false; - return defaultSettings; + + return await fetch(OLDSettingPath).then(function(response) { + return response.text(); + }).catch(function(err) { + logger.info(err); + return "fileLoadFailed"; + }).then(function(data) { + if(data === "fileLoadFailed") { + return defaultSettings; + } + + const parser = new DOMParser(); + const xmlDoc = parser.parseFromString(data, 'text/xml'); + + return { + 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; + }); } - const parser = new DOMParser(); - 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, - 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;}) - } + 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 = ` - - - ${optiones.fps} - ${optiones.width} - ${optiones.stickDistance} - ${optiones.stickMode2} - ${optiones.videoFormat} - ${(optiones.log === "")?"None":optiones.log} - ${optiones.output} - - `; + 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 } \ No newline at end of file diff --git a/src/components/ui/mainPage.tsx b/src/components/ui/mainPage.tsx index 64de297..abaa32e 100644 --- a/src/components/ui/mainPage.tsx +++ b/src/components/ui/mainPage.tsx @@ -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([]); useEffect(() => { @@ -32,14 +32,14 @@ function MainPage() {

Output Folder:

-

openFolder(settingList.output)}>{output}

+

openFolder(getInOutSettings().output)}>{output}

@@ -60,8 +60,8 @@ function updateLogTable(setLogTable:React.Dispatch({log.time.length.formatted}) @@ -69,7 +69,7 @@ function updateLogTable(setLogTable:React.Dispatch>) 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>) { ] }).then(result => { if(result.filePaths.length > 0) { - updateSettings({output:String(result.filePaths)}); + setInOutSettings({output:String(result.filePaths)}); updateHook(String(result.filePaths)); } }).catch(err => { diff --git a/src/components/ui/renderFinishPage.tsx b/src/components/ui/renderFinishPage.tsx index e60e2bb..328d488 100644 --- a/src/components/ui/renderFinishPage.tsx +++ b/src/components/ui/renderFinishPage.tsx @@ -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([
  • ]); @@ -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
  • { openPage(Page.Main); }}>Finish - +

    diff --git a/src/components/ui/renderingPage.tsx b/src/components/ui/renderingPage.tsx index cc99951..20c0f5a 100644 --- a/src/components/ui/renderingPage.tsx +++ b/src/components/ui/renderingPage.tsx @@ -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 (
    -

    {"Log " + logNumber + "/" + getLogList().length}

    +

    {"Log " + logNumber + "/" + getInOutSettings().logList.length}

    {status}

    {remainingTime}

    - +
    ) } diff --git a/src/components/ui/settingsPage.tsx b/src/components/ui/settingsPage.tsx index 50b19af..492acf9 100644 --- a/src/components/ui/settingsPage.tsx +++ b/src/components/ui/settingsPage.tsx @@ -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? : null}