diff --git a/BetterDiscordApp/src/modules/core.js b/BetterDiscordApp/src/modules/core.js
index ffda02b..140c9fe 100644
--- a/BetterDiscordApp/src/modules/core.js
+++ b/BetterDiscordApp/src/modules/core.js
@@ -82,7 +82,7 @@ Core.prototype.init = async function() {
Utils.log("Startup", "Loading Themes");
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() {
if (settingsCookie["bda-dc-0"]) document.querySelector(".btn.btn-disconnect").click();
diff --git a/BetterDiscordApp/src/modules/dataStore.js b/BetterDiscordApp/src/modules/dataStore.js
index ffec2fc..e4be4b5 100644
--- a/BetterDiscordApp/src/modules/dataStore.js
+++ b/BetterDiscordApp/src/modules/dataStore.js
@@ -22,8 +22,8 @@ export default new class DataStore {
initialize() {
try {
- if (!fs.existsSync(this.BDFile)) fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4), "binary");
- const data = JSON.parse(fs.readFileSync(this.BDFile, "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, "utf-8"))
if (data.hasOwnProperty("settings")) this.data = data;
if (!fs.existsSync(this.settingsFile)) return;
let settings = __non_webpack_require__(this.settingsFile);
@@ -62,7 +62,7 @@ export default new class DataStore {
setSettingGroup(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) {
@@ -71,7 +71,7 @@ export default new class DataStore {
setBDData(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) {
@@ -85,12 +85,12 @@ export default new class DataStore {
if (value === undefined) return;
if (this.pluginData[pluginName] === undefined) this.pluginData[pluginName] = {};
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) {
if (this.pluginData[pluginName] === undefined) this.pluginData[pluginName] = {};
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");
}
};
\ No newline at end of file
diff --git a/BetterDiscordApp/src/ui/ApiPreview.jsx b/BetterDiscordApp/src/ui/ApiPreview.jsx
index a312457..621e425 100644
--- a/BetterDiscordApp/src/ui/ApiPreview.jsx
+++ b/BetterDiscordApp/src/ui/ApiPreview.jsx
@@ -6,9 +6,6 @@ import webpackModules from "../modules/webpackModules"
import { remote } from "electron"
import MarginTop from "./margintop"
-const keys = {
- settingTitle: uuidv4()
-}
let formModule
export default class ApiPreview extends React.PureComponent {
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.
All these components have error handling. If you want none, add `.original` after the component path.
- We do not recommend modifying these component by a plugin. Only do this if you know what you are doing.
+ We do not recommend modifying these component with plugins. Only do this if you know what you are doing.
{
@@ -42,238 +39,9 @@ export default class ApiPreview extends React.PureComponent {
,
allComponents.map(comp => {
- let AllPreviews = []
- if(comp.AllPreviews)AllPreviews = comp.AllPreviews
- let onChange = (tab) => {
- 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
-
- {React.createElement(comp, getProps())}
-
-
- }
- let renderCode = () => {
- return
-
-
- JSX
-
-
-
-
- React
-
-
-
-
- }
- 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 ``
- }
- }
- 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 ?
- {help.info}
- : null
- let warn = help.warn ?
- {help.warn}
- : null
- let danger = help.danger ?
- {help.danger}
- : null
- let error = help.error ?
- {help.error}
- : null
- let success = help.success ?
- {help.success}
- : null
- return (
-
- {comp.displayName || comp.name}
-
- {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 [
-
- {key}
- ,
-
{
- 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}/>,
-
- ]
- })}
-
- )
+ const compName = comp.displayName || comp.name
+ const compPath = `Lightcord.Api.Components.${Object.keys(window.Lightcord.Api.Components).find(e => window.Lightcord.Api.Components[e][compName])}.${compName}`
+ return
})
]
}
@@ -281,4 +49,244 @@ export default class ApiPreview extends React.PureComponent {
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
+
+ {React.createElement(comp, getProps())}
+
+
+ }
+ let renderCode = () => {
+ return
+
+
+ JSX
+
+
+ {React.createElement(() => {
+ return
+ })}
+
+
+ React
+
+
+ {React.createElement(() => {
+ return
+ })}
+
+
+
+ }
+ 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 ``
+ }
+ }
+ 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 ?
+ {help.info}
+ : null
+ let warn = help.warn ?
+ {help.warn}
+ : null
+ let danger = help.danger ?
+ {help.danger}
+ : null
+ let error = help.error ?
+ {help.error}
+ : null
+ let success = help.success ?
+ {help.success}
+ : null
+ return (
+
+ {comp.displayName || comp.name}
+
+ {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 [
+
+ {key}
+ ,
+
{
+ 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}/>,
+
+ ]
+ })}
+ {
+ this.setState({
+ tab
+ })
+ }}/>
+ )
+ }
}
\ No newline at end of file
diff --git a/BetterDiscordApp/src/ui/addonlist.jsx b/BetterDiscordApp/src/ui/addonlist.jsx
index e4d1e0d..9dfab7c 100644
--- a/BetterDiscordApp/src/ui/addonlist.jsx
+++ b/BetterDiscordApp/src/ui/addonlist.jsx
@@ -135,8 +135,8 @@ export default class CardList extends BDV2.reactComponent {
getAddons() {
const sortedAddons = this.list.sort((a, b) => {
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 second = b.plugin && b.plugin[`get${cap}`] ? this.getString(b.plugin[`get${cap}`]()) : b[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}`]()) : this.getString(b[this.state.sort]);
if (typeof(first) == "string") return first.toLocaleLowerCase().localeCompare(second.toLocaleLowerCase());
if (first > second) return 1;
if (second > first) return -1;
diff --git a/BetterDiscordApp/src/ui/cssEditor.js b/BetterDiscordApp/src/ui/cssEditor.js
index 47a0ff9..42f3943 100644
--- a/BetterDiscordApp/src/ui/cssEditor.js
+++ b/BetterDiscordApp/src/ui/cssEditor.js
@@ -72,7 +72,7 @@ export default class V2C_CssEditor extends BDV2.reactComponent {
const _ccss = DataStore.getBDData("bdcustomcss");
let ccss = "";
if (_ccss && _ccss !== "") {
- ccss = atob(_ccss);
+ ccss = Buffer.from(_ccss, "base64").toString("utf8");
}
return ccss;
}
@@ -193,7 +193,7 @@ export default class V2C_CssEditor extends BDV2.reactComponent {
}
saveCss() {
- DataStore.setBDData("bdcustomcss", btoa(this.editor.session.getValue()));
+ DataStore.setBDData("bdcustomcss", Buffer.from(this.editor.session.getValue(), "utf-8").toString("base64"));
}
detach() {
diff --git a/BetterDiscordApp/src/ui/cssEditorDetached.js b/BetterDiscordApp/src/ui/cssEditorDetached.js
index edc0cca..d7949f2 100644
--- a/BetterDiscordApp/src/ui/cssEditorDetached.js
+++ b/BetterDiscordApp/src/ui/cssEditorDetached.js
@@ -62,7 +62,7 @@ export default class V2C_CssEditorDetached extends BDV2.reactComponent {
const _ccss = DataStore.getBDData("bdcustomcss");
let ccss = "";
if (_ccss && _ccss !== "") {
- ccss = atob(_ccss);
+ ccss = Buffer.from(_ccss, "base64").toString("utf8");
}
return ccss;
}
@@ -169,6 +169,6 @@ export default class V2C_CssEditorDetached extends BDV2.reactComponent {
}
saveCss() {
- DataStore.setBDData("bdcustomcss", btoa(this.editor.session.getValue()));
+ DataStore.setBDData("bdcustomcss", Buffer.from(this.editor.session.getValue(), "utf-8").toString("base64"));
}
}
\ No newline at end of file
diff --git a/src/common/Settings.ts b/src/common/Settings.ts
index 9139060..ebdaab5 100644
--- a/src/common/Settings.ts
+++ b/src/common/Settings.ts
@@ -1,63 +1,71 @@
-// Imported from main Discord package.
-
-import * as fs from "fs"
-import * as path from "path"
-
-// TODO: sync fs operations could cause slowdown and/or freezes, depending on usage
-// if this is fine, remove this todo
-export default class Settings {
- path: string;
- lastSaved: string;
- settings: any;
- lastModified: number;
- constructor(root:string) {
- this.path = path.join(root, 'settings.json');
- console.log(this.path)
- try {
- this.lastSaved = fs.readFileSync(this.path, "utf8");
- this.settings = JSON.parse(this.lastSaved);
- } catch (e) {
- this.lastSaved = '';
- this.settings = {};
- }
- this.lastModified = this._lastModified();
- }
-
- _lastModified() {
- try {
- return fs.statSync(this.path).mtime.getTime();
- } catch (e) {
- return 0;
- }
- }
-
- get(key, defaultValue = false) {
- if (this.settings.hasOwnProperty(key)) {
- return this.settings[key];
- }
-
- return defaultValue;
- }
-
- set(key, value) {
- this.settings[key] = value;
- }
-
- save() {
- if (this.lastModified && this.lastModified !== this._lastModified()) {
- console.warn('Not saving settings, it has been externally modified.');
- return;
- }
-
- 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);
- }
- }
-}
+// Imported from main Discord package.
+
+import * as fs from "fs"
+import * as path from "path"
+
+// TODO: sync fs operations could cause slowdown and/or freezes, depending on usage
+// if this is fine, remove this todo
+export default class Settings {
+ path: string;
+ lastSaved: string;
+ settings: any;
+ lastModified: number;
+ constructor(root:string) {
+ this.path = path.join(root, 'settings.json');
+ console.log(this.path)
+ try {
+ this.lastSaved = fs.readFileSync(this.path, "utf8");
+ this.settings = JSON.parse(this.lastSaved);
+ } catch (e) {
+ this.lastSaved = '';
+ this.settings = {};
+ }
+ this.lastModified = this._lastModified();
+ }
+
+ _lastModified() {
+ try {
+ return fs.statSync(this.path).mtime.getTime();
+ } catch (e) {
+ return 0;
+ }
+ }
+
+ get(key, defaultValue = false) {
+ if (this.settings.hasOwnProperty(key)) {
+ return this.settings[key];
+ }
+
+ return defaultValue;
+ }
+
+ set(key, value) {
+ this.settings[key] = value;
+ }
+
+ delete(key){
+ delete this.settings[key]
+ }
+
+ exists(key){
+ return key in this.settings
+ }
+
+ save() {
+ if (this.lastModified && this.lastModified !== this._lastModified()) {
+ console.warn('Not saving settings, it has been externally modified.');
+ return;
+ }
+
+ 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);
+ }
+ }
+}