bugs and performances

This commit is contained in:
Jean Ouina 2020-08-04 13:10:08 +02:00
parent 8f427e387d
commit 36545c4d09
7 changed files with 328 additions and 312 deletions

View File

@ -82,7 +82,7 @@ Core.prototype.init = async function() {
Utils.log("Startup", "Loading Themes"); Utils.log("Startup", "Loading Themes");
await themeModule.loadThemes(); await themeModule.loadThemes();
DOM.addStyle("customcss", atob(DataStore.getBDData("bdcustomcss"))); DOM.addStyle("customcss", Buffer.from(DataStore.getBDData("bdcustomcss"), "base64").toString("utf8"));
window.addEventListener("beforeunload", function() { window.addEventListener("beforeunload", function() {
if (settingsCookie["bda-dc-0"]) document.querySelector(".btn.btn-disconnect").click(); if (settingsCookie["bda-dc-0"]) document.querySelector(".btn.btn-disconnect").click();

View File

@ -22,8 +22,8 @@ export default new class DataStore {
initialize() { initialize() {
try { try {
if (!fs.existsSync(this.BDFile)) fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4), "binary"); if (!fs.existsSync(this.BDFile)) fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4), "utf-8");
const data = JSON.parse(fs.readFileSync(this.BDFile, "binary")) const data = JSON.parse(fs.readFileSync(this.BDFile, "utf-8"))
if (data.hasOwnProperty("settings")) this.data = data; if (data.hasOwnProperty("settings")) this.data = data;
if (!fs.existsSync(this.settingsFile)) return; if (!fs.existsSync(this.settingsFile)) return;
let settings = __non_webpack_require__(this.settingsFile); let settings = __non_webpack_require__(this.settingsFile);
@ -62,7 +62,7 @@ export default new class DataStore {
setSettingGroup(key, data) { setSettingGroup(key, data) {
this.data.settings[releaseChannel][key] = data; this.data.settings[releaseChannel][key] = data;
fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4), "binary"); fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4), "utf-8");
} }
getBDData(key) { getBDData(key) {
@ -71,7 +71,7 @@ export default new class DataStore {
setBDData(key, value) { setBDData(key, value) {
this.data[key] = value; this.data[key] = value;
fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4), "binary"); fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4), "utf-8");
} }
getPluginData(pluginName, key) { getPluginData(pluginName, key) {
@ -85,12 +85,12 @@ export default new class DataStore {
if (value === undefined) return; if (value === undefined) return;
if (this.pluginData[pluginName] === undefined) this.pluginData[pluginName] = {}; if (this.pluginData[pluginName] === undefined) this.pluginData[pluginName] = {};
this.pluginData[pluginName][key] = value; this.pluginData[pluginName][key] = value;
fs.writeFileSync(this.getPluginFile(pluginName), JSON.stringify(this.pluginData[pluginName], null, 4), "binary"); fs.writeFileSync(this.getPluginFile(pluginName), JSON.stringify(this.pluginData[pluginName], null, 4), "utf-8");
} }
deletePluginData(pluginName, key) { deletePluginData(pluginName, key) {
if (this.pluginData[pluginName] === undefined) this.pluginData[pluginName] = {}; if (this.pluginData[pluginName] === undefined) this.pluginData[pluginName] = {};
delete this.pluginData[pluginName][key]; delete this.pluginData[pluginName][key];
fs.writeFileSync(this.getPluginFile(pluginName), JSON.stringify(this.pluginData[pluginName], null, 4), "binary"); fs.writeFileSync(this.getPluginFile(pluginName), JSON.stringify(this.pluginData[pluginName], null, 4), "utf-8");
} }
}; };

View File

@ -6,9 +6,6 @@ import webpackModules from "../modules/webpackModules"
import { remote } from "electron" import { remote } from "electron"
import MarginTop from "./margintop" import MarginTop from "./margintop"
const keys = {
settingTitle: uuidv4()
}
let formModule let formModule
export default class ApiPreview extends React.PureComponent { export default class ApiPreview extends React.PureComponent {
constructor(){ constructor(){
@ -32,7 +29,7 @@ export default class ApiPreview extends React.PureComponent {
These components are here for the plugin devs. They can quickly embed any component below with this panel. These components are here for the plugin devs. They can quickly embed any component below with this panel.
<div style={{marginTop: "20px"}}></div> <div style={{marginTop: "20px"}}></div>
<Lightcord.Api.Components.general.AlertBox type="info">All these components have error handling. If you want none, add `.original` after the component path.</Lightcord.Api.Components.general.AlertBox> <Lightcord.Api.Components.general.AlertBox type="info">All these components have error handling. If you want none, add `.original` after the component path.</Lightcord.Api.Components.general.AlertBox>
<Lightcord.Api.Components.general.AlertBox type="warn">We do not recommend modifying these component by a plugin. Only do this if you know what you are doing.</Lightcord.Api.Components.general.AlertBox> <Lightcord.Api.Components.general.AlertBox type="warn">We do not recommend modifying these component with plugins. Only do this if you know what you are doing.</Lightcord.Api.Components.general.AlertBox>
</formModule.FormText> </formModule.FormText>
<MarginTop></MarginTop> <MarginTop></MarginTop>
<Lightcord.Api.Components.inputs.Button color="brand" look="outlined" size="medium" hoverColor="green" onClick={() => { <Lightcord.Api.Components.inputs.Button color="brand" look="outlined" size="medium" hoverColor="green" onClick={() => {
@ -42,238 +39,9 @@ export default class ApiPreview extends React.PureComponent {
</Lightcord.Api.Components.inputs.Button> </Lightcord.Api.Components.inputs.Button>
</formModule.FormSection>, </formModule.FormSection>,
allComponents.map(comp => { allComponents.map(comp => {
let AllPreviews = [] const compName = comp.displayName || comp.name
if(comp.AllPreviews)AllPreviews = comp.AllPreviews const compPath = `Lightcord.Api.Components.${Object.keys(window.Lightcord.Api.Components).find(e => window.Lightcord.Api.Components[e][compName])}.${compName}`
let onChange = (tab) => { return <ComponentPreview key={compPath} comp={comp} />
setState({
tab
})
}
let setState = (newState) => {
this.setState({
states: [Object.assign(state, newState)].concat(this.state.states.filter(e => e.elem !== comp))
})
}
let state = this.state.states.find(e => e.elem === comp)
if(!state){
state = {
tab: "preview",
elem: comp,
options: {}
}
this.state.states.push(state)
}
let getProps = () => {
let final = {}
AllPreviews.forEach(category => {
final[Object.keys(category[0])[0]] = category[0][Object.keys(category[0])[0]]
})
Object.keys(state.options).forEach(key => {
final[key] = AllPreviews.find(e => e.find(e => e[key]))[state.options[key]][key]
})
return final
}
let renderPreview = () => {
return <div style={{margin: "20px"}}>
<div style={{
backgroundColor: "var(--background-secondary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
{React.createElement(comp, getProps())}
</div>
</div>
}
let renderCode = () => {
return <div style={{margin: "20px"}}>
<div style={{
backgroundColor: "var(--background-secondary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
<window.Lightcord.Api.Components.general.SettingSubTitle>
JSX
</window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.CodeBlock language="jsx" content={generateCode("jsx")}/>
<window.Lightcord.Api.Components.general.SettingSubTitle>
React
</window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.CodeBlock language="js" content={generateCode("react")}/>
</div>
</div>
}
let getStrForProp = (value, compPath, lang) => {
if(typeof value === "string"){
return value
}else if(typeof value === "boolean"){
return String(value)
}else if(typeof value === "function"){
return value.toString()
}else if(typeof value === "object"){
if(value && value.$$typeof && (value.$$typeof === Symbol.for("react.element") || value.$$typeof === 0xeac7)){
if(compPath === "Lightcord.Api.Components.general.Tabs"){
if(lang === "react"){
return `React.createElement("div", {style: {
marginTop: "20px", marginBottom: "20px"
}},
React.createElement("div", {style: {
backgroundColor: "var(--background-secondary)",
padding: "30px 30px",
borderRadius: "8px"
}, className: "lc-tab-box-shadow" },
React.createElement(Lightcord.Api.Components.general.Title, null, "Preview tabs")
)
)`
}else if(lang === "jsx"){
return `<div style={{
marginTop: "20px", marginBottom: "20px"
}}>
<div style={{
backgroundColor: "var(--background-secondary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
<Lightcord.Api.Components.general.Title>Preview tabs</Lightcord.Api.Components.general.Title>
</div>
</div>`
}
}
return "Your components here."
}
return JSON.stringify(value, null, " ")
}else if(typeof value === "number"){
return String(value)
}
return String(value)
}
let generateCode = function(lang){ // code formatting is hard
const compName = comp.displayName || comp.name
let categories = Object.keys(window.Lightcord.Api.Components)
const compCategory = categories.find(e => window.Lightcord.Api.Components[e][compName])
const compPath = `Lightcord.Api.Components.${compCategory}.${compName}`
const props = getProps()
if(lang === "jsx"){
let propStrings = []
let childrenProp = null
Object.keys(props).forEach(key => {
if(key == "children"){
childrenProp = getStrForProp(props[key], compPath, lang)
}else{
let str = key+"="
if(typeof props[key] === "string"){
str += JSON.stringify(props[key])
}else{
str += `{${getStrForProp(props[key], compPath, lang)}}`
}
propStrings.push(str)
}
})
let openTag
if(childrenProp){
openTag = `<${compPath} ${propStrings.join(" ")}>`
let closeTag = `</${compPath}>`
return `${openTag}\n ${childrenProp}\n${closeTag}`
}else{
openTag = `<${compPath} ${propStrings.join(" ")}/>`
return openTag
}
}else if(lang === "react"){
let children = props.children || null
delete props.children
if(children && children.$$typeof && (children.$$typeof === Symbol.for("react.element") || children.$$typeof === 0xeac7)){
children = getStrForProp(children, compPath, lang)
}
let propStrings = []
Object.keys(props).forEach(key => {
let visibleKey = /[^\w\d_]/g.test(key) ? JSON.stringify(key) : key
let str = visibleKey+": "
if(typeof props[key] === "string"){
str += JSON.stringify(props[key])
}else{
str += getStrForProp(props[key], compPath, lang).split("\n").map((str, i) => {
if(i === 0)return str
return " " + str
}).join("\n")
}
propStrings.push(str)
})
let propObject = "{"
if(propStrings.length){
propStrings.forEach((str, i) => {
let isLast = i === propStrings.length - 1
let isFirst = i === 0
if(!isFirst){
propObject += ","
}
propObject += "\n "
propObject += str
if(isLast){
propObject +="\n}"
}
})
}else{
propObject += "}"
}
let childrenData = typeof children === "string" && children.startsWith("React.createElement") ? children : JSON.stringify(children)
return `React.createElement(${compPath}, ${propObject}, ${childrenData})`
}
}
let help = comp.help || {}
let info = help.info ? <window.Lightcord.Api.Components.general.AlertBox type="info">
{help.info}
</window.Lightcord.Api.Components.general.AlertBox> : null
let warn = help.warn ? <window.Lightcord.Api.Components.general.AlertBox type="warn">
{help.warn}
</window.Lightcord.Api.Components.general.AlertBox> : null
let danger = help.danger ? <window.Lightcord.Api.Components.general.AlertBox type="danger">
{help.danger}
</window.Lightcord.Api.Components.general.AlertBox> : null
let error = help.error ? <window.Lightcord.Api.Components.general.AlertBox type="error">
{help.error}
</window.Lightcord.Api.Components.general.AlertBox> : null
let success = help.success ? <window.Lightcord.Api.Components.general.AlertBox type="success">
{help.success}
</window.Lightcord.Api.Components.general.AlertBox> : null
return (<div>
<window.Lightcord.Api.Components.general.SettingsTitle>
{comp.displayName || comp.name}
</window.Lightcord.Api.Components.general.SettingsTitle>
{info}
{success}
{warn}
{error}
{danger}
{AllPreviews.map(category => {
if(category[0].onClick)return null
if(category[0].text)return null
if(category[0].children)return null
if(category.length === 1)return null
let key = Object.keys(category[0])[0]
return [
<window.Lightcord.Api.Components.general.SettingSubTitle>
{key}
</window.Lightcord.Api.Components.general.SettingSubTitle>,
<window.Lightcord.Api.Components.inputs.Dropdown options={category.map((e, index) => {
return {
value: "opt-"+index,
label: JSON.stringify(e[Object.keys(e)[0]])
}
})} value={"opt-"+(state.options[key] || "0")} onChange={(value) => {
setState({
options: Object.assign({}, state.options, {
[key]: (value.value || "0").replace("opt-", "")
})
})
}} searchable={true}/>,
<div style={{marginBottom: "8px"}}></div>
]
})}
<window.Lightcord.Api.Components.general.Tabs tabs={[{label: "Preview", id: "preview"}, {label: "Code", id: "code"}]}
active={state.tab} children={state.tab === "preview" ? renderPreview() : renderCode()} onChange={onChange}/>
</div>)
}) })
] ]
} }
@ -281,4 +49,244 @@ export default class ApiPreview extends React.PureComponent {
get renders(){ get renders(){
} }
}
class ComponentPreview extends React.Component {
constructor(props){
super(props)
this.state = {
tab: "preview",
elem: props.comp,
options: {}
}
}
render(){
const comp = this.props.comp
let AllPreviews = []
if(comp.AllPreviews)AllPreviews = comp.AllPreviews
let state = this.state
let getProps = () => {
let final = {}
AllPreviews.forEach(category => {
final[Object.keys(category[0])[0]] = category[0][Object.keys(category[0])[0]]
})
Object.keys(state.options).forEach(key => {
final[key] = AllPreviews.find(e => e.find(e => e[key]))[state.options[key]][key]
})
return final
}
let renderPreview = () => {
return <div style={{margin: "20px"}}>
<div style={{
backgroundColor: "var(--background-secondary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
{React.createElement(comp, getProps())}
</div>
</div>
}
let renderCode = () => {
return <div style={{margin: "20px"}}>
<div style={{
backgroundColor: "var(--background-secondary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
<window.Lightcord.Api.Components.general.SettingSubTitle>
JSX
</window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.ErrorCatcher>
{React.createElement(() => {
return <window.Lightcord.Api.Components.general.CodeBlock language="jsx" content={generateCode("jsx")}/>
})}
</window.Lightcord.Api.Components.general.ErrorCatcher>
<window.Lightcord.Api.Components.general.SettingSubTitle>
React
</window.Lightcord.Api.Components.general.SettingSubTitle>
<window.Lightcord.Api.Components.general.ErrorCatcher>
{React.createElement(() => {
return <window.Lightcord.Api.Components.general.CodeBlock language="js" content={generateCode("react")}/>
})}
</window.Lightcord.Api.Components.general.ErrorCatcher>
</div>
</div>
}
let getStrForProp = (value, compPath, lang) => {
if(typeof value === "string"){
return value
}else if(typeof value === "boolean"){
return String(value)
}else if(typeof value === "function"){
return value.toString()
}else if(typeof value === "object"){
if(value && value.$$typeof && (value.$$typeof === Symbol.for("react.element") || value.$$typeof === 0xeac7)){
if(compPath === "Lightcord.Api.Components.general.Tabs"){
if(lang === "react"){
return `React.createElement("div", {style: {
marginTop: "20px", marginBottom: "20px"
}},
React.createElement("div", {style: {
backgroundColor: "var(--background-secondary)",
padding: "30px 30px",
borderRadius: "8px"
}, className: "lc-tab-box-shadow" },
React.createElement(Lightcord.Api.Components.general.Title, null, "Preview tabs")
)
)`
}else if(lang === "jsx"){
return `<div style={{
marginTop: "20px", marginBottom: "20px"
}}>
<div style={{
backgroundColor: "var(--background-secondary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
<Lightcord.Api.Components.general.Title>Preview tabs</Lightcord.Api.Components.general.Title>
</div>
</div>`
}
}
return "Your components here."
}
return JSON.stringify(value, null, " ")
}else if(typeof value === "number"){
return String(value)
}
return String(value)
}
let generateCode = function(lang){ // code formatting is hard
const compName = comp.displayName || comp.name
let categories = Object.keys(window.Lightcord.Api.Components)
const compCategory = categories.find(e => window.Lightcord.Api.Components[e][compName])
const compPath = `Lightcord.Api.Components.${compCategory}.${compName}`
const props = getProps()
if(lang === "jsx"){
let propStrings = []
let childrenProp = null
Object.keys(props).forEach(key => {
if(key == "children"){
childrenProp = getStrForProp(props[key], compPath, lang)
}else{
let str = key+"="
if(typeof props[key] === "string"){
str += JSON.stringify(props[key])
}else{
str += `{${getStrForProp(props[key], compPath, lang)}}`
}
propStrings.push(str)
}
})
let openTag
if(childrenProp){
openTag = `<${compPath} ${propStrings.join(" ")}>`
let closeTag = `</${compPath}>`
return `${openTag}\n ${childrenProp}\n${closeTag}`
}else{
openTag = `<${compPath} ${propStrings.join(" ")}/>`
return openTag
}
}else if(lang === "react"){
let children = props.children || null
delete props.children
if(children && children.$$typeof && (children.$$typeof === Symbol.for("react.element") || children.$$typeof === 0xeac7)){
children = getStrForProp(children, compPath, lang)
}
let propStrings = []
Object.keys(props).forEach(key => {
let visibleKey = /[^\w\d_]/g.test(key) ? JSON.stringify(key) : key
let str = visibleKey+": "
if(typeof props[key] === "string"){
str += JSON.stringify(props[key])
}else{
str += getStrForProp(props[key], compPath, lang).split("\n").map((str, i) => {
if(i === 0)return str
return " " + str
}).join("\n")
}
propStrings.push(str)
})
let propObject = "{"
if(propStrings.length){
propStrings.forEach((str, i) => {
let isLast = i === propStrings.length - 1
let isFirst = i === 0
if(!isFirst){
propObject += ","
}
propObject += "\n "
propObject += str
if(isLast){
propObject +="\n}"
}
})
}else{
propObject += "}"
}
let childrenData = typeof children === "string" && children.startsWith("React.createElement") ? children : JSON.stringify(children)
return `React.createElement(${compPath}, ${propObject}, ${childrenData})`
}
}
let help = comp.help || {}
let info = help.info ? <window.Lightcord.Api.Components.general.AlertBox type="info">
{help.info}
</window.Lightcord.Api.Components.general.AlertBox> : null
let warn = help.warn ? <window.Lightcord.Api.Components.general.AlertBox type="warn">
{help.warn}
</window.Lightcord.Api.Components.general.AlertBox> : null
let danger = help.danger ? <window.Lightcord.Api.Components.general.AlertBox type="danger">
{help.danger}
</window.Lightcord.Api.Components.general.AlertBox> : null
let error = help.error ? <window.Lightcord.Api.Components.general.AlertBox type="error">
{help.error}
</window.Lightcord.Api.Components.general.AlertBox> : null
let success = help.success ? <window.Lightcord.Api.Components.general.AlertBox type="success">
{help.success}
</window.Lightcord.Api.Components.general.AlertBox> : null
return (<div>
<window.Lightcord.Api.Components.general.SettingsTitle>
{comp.displayName || comp.name}
</window.Lightcord.Api.Components.general.SettingsTitle>
{info}
{success}
{warn}
{error}
{danger}
{AllPreviews.map(category => {
if(category[0].onClick)return null
if(category[0].text)return null
if(category[0].children)return null
if(category.length === 1)return null
let key = Object.keys(category[0])[0]
return [
<window.Lightcord.Api.Components.general.SettingSubTitle>
{key}
</window.Lightcord.Api.Components.general.SettingSubTitle>,
<window.Lightcord.Api.Components.inputs.Dropdown options={category.map((e, index) => {
return {
value: "opt-"+index,
label: JSON.stringify(e[Object.keys(e)[0]])
}
})} value={"opt-"+(state.options[key] || "0")} onChange={(value) => {
this.setState({
options: Object.assign({}, state.options, {
[key]: (value.value || "0").replace("opt-", "")
})
})
}} searchable={true}/>,
<div style={{marginBottom: "8px"}}></div>
]
})}
<window.Lightcord.Api.Components.general.Tabs tabs={[{label: "Preview", id: "preview"}, {label: "Code", id: "code"}]}
active={state.tab} children={state.tab === "preview" ? renderPreview() : renderCode()} onChange={(tab) => {
this.setState({
tab
})
}}/>
</div>)
}
} }

View File

@ -135,8 +135,8 @@ export default class CardList extends BDV2.reactComponent {
getAddons() { getAddons() {
const sortedAddons = this.list.sort((a, b) => { const sortedAddons = this.list.sort((a, b) => {
const cap = this.state.sort.charAt(0).toUpperCase() + this.state.sort.slice(1); const cap = this.state.sort.charAt(0).toUpperCase() + this.state.sort.slice(1);
const first = a.plugin && a.plugin[`get${cap}`] ? this.getString(a.plugin[`get${cap}`]()) : a[this.state.sort]; const first = a.plugin && a.plugin[`get${cap}`] ? this.getString(a.plugin[`get${cap}`]()) : this.getString(a[this.state.sort]);
const second = b.plugin && b.plugin[`get${cap}`] ? this.getString(b.plugin[`get${cap}`]()) : b[this.state.sort]; const second = b.plugin && b.plugin[`get${cap}`] ? this.getString(b.plugin[`get${cap}`]()) : this.getString(b[this.state.sort]);
if (typeof(first) == "string") return first.toLocaleLowerCase().localeCompare(second.toLocaleLowerCase()); if (typeof(first) == "string") return first.toLocaleLowerCase().localeCompare(second.toLocaleLowerCase());
if (first > second) return 1; if (first > second) return 1;
if (second > first) return -1; if (second > first) return -1;

View File

@ -72,7 +72,7 @@ export default class V2C_CssEditor extends BDV2.reactComponent {
const _ccss = DataStore.getBDData("bdcustomcss"); const _ccss = DataStore.getBDData("bdcustomcss");
let ccss = ""; let ccss = "";
if (_ccss && _ccss !== "") { if (_ccss && _ccss !== "") {
ccss = atob(_ccss); ccss = Buffer.from(_ccss, "base64").toString("utf8");
} }
return ccss; return ccss;
} }
@ -193,7 +193,7 @@ export default class V2C_CssEditor extends BDV2.reactComponent {
} }
saveCss() { saveCss() {
DataStore.setBDData("bdcustomcss", btoa(this.editor.session.getValue())); DataStore.setBDData("bdcustomcss", Buffer.from(this.editor.session.getValue(), "utf-8").toString("base64"));
} }
detach() { detach() {

View File

@ -62,7 +62,7 @@ export default class V2C_CssEditorDetached extends BDV2.reactComponent {
const _ccss = DataStore.getBDData("bdcustomcss"); const _ccss = DataStore.getBDData("bdcustomcss");
let ccss = ""; let ccss = "";
if (_ccss && _ccss !== "") { if (_ccss && _ccss !== "") {
ccss = atob(_ccss); ccss = Buffer.from(_ccss, "base64").toString("utf8");
} }
return ccss; return ccss;
} }
@ -169,6 +169,6 @@ export default class V2C_CssEditorDetached extends BDV2.reactComponent {
} }
saveCss() { saveCss() {
DataStore.setBDData("bdcustomcss", btoa(this.editor.session.getValue())); DataStore.setBDData("bdcustomcss", Buffer.from(this.editor.session.getValue(), "utf-8").toString("base64"));
} }
} }

View File

@ -1,63 +1,71 @@
// Imported from main Discord package. // Imported from main Discord package.
import * as fs from "fs" import * as fs from "fs"
import * as path from "path" import * as path from "path"
// TODO: sync fs operations could cause slowdown and/or freezes, depending on usage // TODO: sync fs operations could cause slowdown and/or freezes, depending on usage
// if this is fine, remove this todo // if this is fine, remove this todo
export default class Settings { export default class Settings {
path: string; path: string;
lastSaved: string; lastSaved: string;
settings: any; settings: any;
lastModified: number; lastModified: number;
constructor(root:string) { constructor(root:string) {
this.path = path.join(root, 'settings.json'); this.path = path.join(root, 'settings.json');
console.log(this.path) console.log(this.path)
try { try {
this.lastSaved = fs.readFileSync(this.path, "utf8"); this.lastSaved = fs.readFileSync(this.path, "utf8");
this.settings = JSON.parse(this.lastSaved); this.settings = JSON.parse(this.lastSaved);
} catch (e) { } catch (e) {
this.lastSaved = ''; this.lastSaved = '';
this.settings = {}; this.settings = {};
} }
this.lastModified = this._lastModified(); this.lastModified = this._lastModified();
} }
_lastModified() { _lastModified() {
try { try {
return fs.statSync(this.path).mtime.getTime(); return fs.statSync(this.path).mtime.getTime();
} catch (e) { } catch (e) {
return 0; return 0;
} }
} }
get(key, defaultValue = false) { get(key, defaultValue = false) {
if (this.settings.hasOwnProperty(key)) { if (this.settings.hasOwnProperty(key)) {
return this.settings[key]; return this.settings[key];
} }
return defaultValue; return defaultValue;
} }
set(key, value) { set(key, value) {
this.settings[key] = value; this.settings[key] = value;
} }
save() { delete(key){
if (this.lastModified && this.lastModified !== this._lastModified()) { delete this.settings[key]
console.warn('Not saving settings, it has been externally modified.'); }
return;
} exists(key){
return key in this.settings
try { }
const toSave = JSON.stringify(this.settings, null, 2);
if (this.lastSaved != toSave) { save() {
this.lastSaved = toSave; if (this.lastModified && this.lastModified !== this._lastModified()) {
fs.writeFileSync(this.path, toSave, "utf8"); console.warn('Not saving settings, it has been externally modified.');
this.lastModified = this._lastModified(); return;
} }
} catch (err) {
console.warn('Failed saving settings with error: ', err); try {
} const toSave = JSON.stringify(this.settings, null, 2);
} if (this.lastSaved != toSave) {
} this.lastSaved = toSave;
fs.writeFileSync(this.path, toSave, "utf8");
this.lastModified = this._lastModified();
}
} catch (err) {
console.warn('Failed saving settings with error: ', err);
}
}
}