BetterDiscordApp-rauenzi/renderer/src/builtins/customcss.js

166 lines
6.0 KiB
JavaScript
Raw Normal View History

2023-05-20 00:37:21 +02:00
import fs from "fs";
import electron from "electron";
import Builtin from "@structs/builtin";
2023-05-19 23:14:55 +02:00
import Settings from "@modules/settingsmanager";
import DataStore from "@modules/datastore";
import React from "@modules/react";
import WebpackModules from "@modules/webpackmodules";
import Events from "@modules/emitter";
import DOMManager from "@modules/dommanager";
import Strings from "@modules/strings";
import DiscordModules from "@modules/discordmodules";
2023-05-20 00:37:21 +02:00
import Utilities from "@modules/utilities";
import CSSEditor from "@ui/customcss/csseditor";
import FloatingWindows from "@ui/floatingwindows";
import SettingsTitle from "@ui/settings/title";
2019-06-10 05:40:35 +02:00
2019-06-15 04:11:19 +02:00
const UserSettings = WebpackModules.getByProps("updateAccount");
2022-08-03 07:52:05 +02:00
const Dispatcher = DiscordModules.Dispatcher;
2019-06-10 22:37:50 +02:00
2019-06-10 05:40:35 +02:00
export default new class CustomCSS extends Builtin {
get name() {return "Custom CSS";}
get category() {return "customcss";}
get id() {return "customcss";}
2019-06-30 05:09:48 +02:00
get startDetached() {return Settings.get(this.collection, this.category, "openAction") == "detached";}
get nativeOpen() {return Settings.get(this.collection, this.category, "openAction") == "system";}
2019-06-10 22:37:50 +02:00
constructor() {
super();
2019-06-12 06:28:18 +02:00
this.savedCss = "";
this.insertedCss = "";
2019-06-15 04:11:19 +02:00
this.isDetached = false;
2019-06-10 22:37:50 +02:00
}
2019-06-10 05:40:35 +02:00
2019-06-11 04:33:45 +02:00
async enabled() {
2019-06-25 22:36:34 +02:00
Settings.registerPanel(this.id, Strings.Panels.customcss, {
2019-06-10 22:37:50 +02:00
order: 2,
2019-06-25 22:36:34 +02:00
element: () => [<SettingsTitle text={Strings.CustomCSS.editorTitle} />, React.createElement(CSSEditor, {
2019-06-12 06:28:18 +02:00
css: this.savedCss,
2019-06-10 22:37:50 +02:00
save: this.saveCSS.bind(this),
update: this.insertCSS.bind(this),
2019-06-11 22:24:57 +02:00
openNative: this.openNative.bind(this),
2019-06-15 04:11:19 +02:00
openDetached: this.openDetached.bind(this),
onChange: this.onChange.bind(this)
2019-06-11 22:24:57 +02:00
})],
2019-06-10 22:37:50 +02:00
onClick: (thisObject) => {
2019-06-15 04:11:19 +02:00
if (this.isDetached) return;
2019-06-26 20:34:01 +02:00
if (this.nativeOpen) return this.openNative();
else if (this.startDetached) return this.openDetached(this.savedCss);
2022-10-02 09:34:34 +02:00
const settingsView = Utilities.findInTree(thisObject._reactInternals, m => m && m.onSetSection, {walkable: ["child", "memoizedProps", "props", "children"]});
2019-06-26 20:34:01 +02:00
if (settingsView && settingsView.onSetSection) settingsView.onSetSection(this.id);
2019-06-10 22:37:50 +02:00
}
2019-06-10 05:40:35 +02:00
});
2019-06-10 22:37:50 +02:00
this.loadCSS();
2019-06-12 06:28:18 +02:00
this.insertCSS(this.savedCss);
2019-06-15 04:11:19 +02:00
this.watchContent();
2019-06-10 05:40:35 +02:00
}
disabled() {
Settings.removePanel(this.id);
2019-06-15 04:11:19 +02:00
this.unwatchContent();
2022-01-24 07:36:14 +01:00
this.insertCSS("");
2019-06-15 04:11:19 +02:00
}
2019-06-19 05:09:49 +02:00
2019-06-15 04:11:19 +02:00
watchContent() {
if (this.watcher) return this.error("Already watching content.");
const timeCache = {};
this.log("Starting to watch content.");
this.watcher = fs.watch(DataStore.customCSS, {persistent: false}, async (eventType, filename) => {
if (!eventType || !filename) return;
await new Promise(r => setTimeout(r, 50));
try {fs.statSync(DataStore.customCSS);}
catch (err) {
if (err.code !== "ENOENT") return;
delete timeCache[filename];
this.saveCSS("");
}
const stats = fs.statSync(DataStore.customCSS);
if (!stats || !stats.mtime || !stats.mtime.getTime()) return;
if (typeof(stats.mtime.getTime()) !== "number") return;
if (timeCache[filename] == stats.mtime.getTime()) return;
timeCache[filename] = stats.mtime.getTime();
if (eventType == "change") {
const newCSS = DataStore.loadCustomCSS();
if (newCSS == this.savedCss) return;
this.savedCss = newCSS;
this.insertCSS(this.savedCss);
Events.emit("customcss-updated", this.savedCss);
}
});
}
unwatchContent() {
if (!this.watcher) return this.error("Was not watching content.");
this.watcher.close();
delete this.watcher;
this.log("No longer watching content.");
}
onChange(value) {
if (!Settings.get("settings", "customcss", "liveUpdate")) return;
this.insertCSS(value);
this.saveCSS(value);
2019-06-10 05:40:35 +02:00
}
2019-06-10 22:37:50 +02:00
loadCSS() {
2019-06-12 06:28:18 +02:00
this.savedCss = DataStore.loadCustomCSS();
2019-06-10 22:37:50 +02:00
}
insertCSS(newCss) {
2019-06-12 06:28:18 +02:00
if (typeof(newCss) === "undefined") newCss = this.insertedCss;
else this.insertedCss = newCss;
2019-06-19 05:09:49 +02:00
DOMManager.updateCustomCSS(newCss);
2019-06-10 22:37:50 +02:00
}
saveCSS(newCss) {
2019-06-12 06:28:18 +02:00
if (typeof(newCss) !== "undefined") this.savedCss = newCss;
DataStore.saveCustomCSS(this.savedCss);
2019-06-10 22:37:50 +02:00
}
openNative() {
electron.shell.openExternal(`file://${DataStore.customCSS}`);
}
2019-06-15 04:11:19 +02:00
openDetached(currentCSS) {
const editorRef = React.createRef();
const editor = React.createElement(CSSEditor, {
id: "bd-floating-editor",
2019-06-19 05:09:49 +02:00
ref: editorRef,
2019-06-15 04:11:19 +02:00
css: currentCSS,
save: this.saveCSS.bind(this),
update: this.insertCSS.bind(this),
openNative: this.openNative.bind(this),
2023-08-29 06:18:30 +02:00
onChange: Utilities.debounce(this.onChange.bind(this), 500)
2019-06-15 04:11:19 +02:00
});
2019-06-19 21:24:05 +02:00
FloatingWindows.open({
2019-06-19 05:09:49 +02:00
onClose: () => {
this.isDetached = false;
},
2019-06-15 04:11:19 +02:00
onResize: () => {
if (!editorRef || !editorRef.current || !editorRef.current.resize) return;
editorRef.current.resize();
2019-06-11 22:24:57 +02:00
},
2019-06-25 22:36:34 +02:00
title: Strings.CustomCSS.editorTitle,
2019-06-15 04:11:19 +02:00
id: "floating-editor-window",
height: 470,
width: 410,
center: true,
resizable: true,
2019-06-19 05:09:49 +02:00
children: editor,
confirmClose: () => {
if (!editorRef || !editorRef.current) return false;
if (Settings.get("settings", "customcss", "liveUpdate")) return false;
2019-06-19 05:09:49 +02:00
return editorRef.current.hasUnsavedChanges;
},
2019-06-25 22:36:34 +02:00
confirmationText: Strings.CustomCSS.confirmationText
2019-06-11 04:33:45 +02:00
});
2019-06-15 04:11:19 +02:00
this.isDetached = true;
UserSettings.close();
2022-08-01 23:53:43 +02:00
Dispatcher.dispatch({type: "LAYER_POP"});
2019-06-10 22:37:50 +02:00
}
2019-06-15 04:11:19 +02:00
};