Lightcord/BetterDiscordApp/src/modules/settingsPanel.js

554 lines
22 KiB
JavaScript

import {settings, settingsCookie, settingsRPC, lightcordSettings} from "../0globals";
import DataStore from "./dataStore";
import V2_SettingsPanel_Sidebar from "./settingsPanelSidebar";
import Utils from "./utils";
import BDV2 from "./v2";
import ContentManager from "./contentManager";
import coloredText from "./coloredText";
import tfHour from "./24hour";
import DOM from "./domtools";
import publicServersModule from "./publicServers";
import voiceMode from "./voiceMode";
import ClassNormalizer from "./classNormalizer";
import dMode from "./devMode";
import SectionedSettingsPanel from "../ui/sectionedSettingsPanel";
import CssEditor from "../ui/cssEditor";
import CardList from "../ui/addonlist";
import V2C_PresenceSettings from "../ui/presenceSettings";
import CustomRichPresence from "./CustomRichPresence";
import V2C_AccountInfos from "../ui/AccountInfos";
import { remote, ipcRenderer } from "electron";
import AntiAdDM from "./AntiAdDM";
import blurPrivate from "./blurPrivate";
import disableTyping from "./disableTyping";
import ApiPreview from "../ui/ApiPreview";
import Switch from "../ui/switch";
import MarginTop from "../ui/margintop";
import webpackModules from "./webpackModules";
import tooltipWrap from "../ui/tooltipWrap";
import History from "../ui/icons/history";
import core from "./core";
import popoutWindow from "./popoutWindow";
import TextInputSetting from "../ui/TextInputSetting";
import { useForceUpdate } from "./hooks";
import { clearCaches } from "./pluginCertifier";
class BDSidebarHeader extends React.PureComponent {
render(){
let sidebarComponents = webpackModules.find(e => e.Separator && e.Header && e.Item)
const changelogButton = React.createElement(tooltipWrap, {color: "black", side: "top", text: "Changelog"},
React.createElement("span", {style: {float: "right", cursor: "pointer"}, className: "bd-changelog-button", onClick: () => {Utils.showChangelogModal(bbdChangelog);}},
React.createElement(History, {className: "bd-icon", size: "16px"})
)
);
let rendered = new sidebarComponents.Header({
children: React.createElement("span", null, "Lightcord BD", changelogButton),
className: "ui-tab-bar-header"
})
return rendered
}
}
let isClearingCache = false
export default new class V2_SettingsPanel {
constructor() {
this.onChange = this.onChange.bind(this);
this.updateSettings = this.updateSettings.bind(this);
this.sidebar = new V2_SettingsPanel_Sidebar();
this.registerComponents()
}
registerComponents(){
/** Lightcord */
this.sidebar.register("lightcord", makeComponent(this.lightcordComponent.bind(this)))
this.sidebar.register("status", makeComponent(this.PresenceComponent.bind(this)))
this.sidebar.register("accountinfo", makeComponent(this.AccountInfosComponent.bind(this)))
this.sidebar.register("lcapipreview", makeComponent(this.ApiPreviewComponent.bind(this)))
/* Bandaged BD */
this.sidebar.register("BDChangelogTitle", makeComponent(() => {
return new BDSidebarHeader().render()
}))
this.sidebar.register("core", makeComponent(this.coreComponent.bind(this)))
this.sidebar.register("customcss", makeComponent(this.customCssComponent.bind(this)))
this.sidebar.register("plugins", makeComponent(this.renderAddonPane("plugins")))
this.sidebar.register("themes", makeComponent(this.renderAddonPane("themes")))
}
get coreSettings() {
const settings = this.getSettings("core");
const categories = [...new Set(settings.map(s => s.category))];
const sections = categories.map(c => {return {title: c, settings: settings.filter(s => s.category == c)};});
return sections;
}
get lightcordSettings() {
const settings = this.getSettings("lightcord");
const categories = [...new Set(settings.map(s => s.category))];
const sections = categories.map(c => {return {title: c, settings: settings.filter(s => s.category == c)};});
return sections;
}
get PresenceSettings() {
return this.getSettings("status")
}
getSettings(category) {
return Object.keys(settings).reduce((arr, key) => {
const setting = settings[key];
if (setting.cat === category && setting.implemented && !setting.hidden) {
setting.text = key;
arr.push(setting);
}
return arr;
}, []);
}
onChange(id, checked, sidebar) {
this.updateSettings(id, checked, sidebar);
}
updateSettings(id, enabled, sidebar) {
if(!["lightcord-8", "no_window_bound", "enable_glasstron", "lightcord-10", "lightcord-11"].includes(id))settingsCookie[id] = enabled;
if (id == "bda-gs-2") {
if (enabled) DOM.addClass(document.body, "bd-minimal");
else DOM.removeClass(document.body, "bd-minimal");
}
if (id == "bda-gs-3") {
if (enabled) DOM.addClass(document.body, "bd-minimal-chan");
else DOM.removeClass(document.body, "bd-minimal-chan");
}
if (id == "bda-gs-1") {
if (enabled) publicServersModule.addButton();
else publicServersModule.removeButton();
}
if (id == "bda-gs-4") {
if (enabled) voiceMode.start();
else voiceMode.stop();
}
if (id == "bda-gs-5") {
if (enabled) DOM.addClass(DOM.query("#app-mount"), "bda-dark");
else DOM.removeClass(DOM.query("#app-mount"), "bda-dark");
}
if (enabled && id == "bda-gs-6") tfHour.inject24Hour();
if (id == "bda-gs-7") {
if (enabled) coloredText.injectColoredText();
else coloredText.removeColoredText();
}
if (id == "fork-ps-4") {
if (enabled) ClassNormalizer.start();
else ClassNormalizer.stop();
}
if (id == "fork-ps-5") {
if (enabled) {
ContentManager.watchContent("plugin");
ContentManager.watchContent("theme");
}
else {
ContentManager.unwatchContent("plugin");
ContentManager.unwatchContent("theme");
}
}
if (id == "fork-wp-1") {
Utils.setWindowPreference("transparent", enabled);
if (enabled) Utils.setWindowPreference("backgroundColor", null);
else Utils.setWindowPreference("backgroundColor", "#2f3136");
}
if (id == "bda-gs-8") {
if (enabled) dMode.startDebugListener();
else dMode.stopDebugListener();
}
if (id == "fork-dm-1") {
if (enabled) dMode.startCopySelector();
else dMode.stopCopySelector();
}
if (id === "lightcord-1") {
if (enabled) window.Lightcord.Settings.devMode = true
else window.Lightcord.Settings.devMode = false
sidebar.forceUpdate()
}
if (id === "lightcord-2") {
if (enabled) window.Lightcord.Settings.callRingingBeat = true
else window.Lightcord.Settings.callRingingBeat = false
}
if (id === "lightcord-presence-1") {
if (enabled) {
CustomRichPresence.enable()
const settingsStore = BDModules.get(e => e.default && typeof e.default === "object" && "showCurrentGame" in e.default)[0]
if(settingsStore && !settingsStore.default.showCurrentGame){
BDModules.get(e => e.default && e.default.updateRemoteSettings)[0].default.updateRemoteSettings({
showCurrentGame: true
})
}
}
else CustomRichPresence.disable()
}
if (id === "lightcord-3") {
ipcRenderer.sendSync("LIGHTCORD_SET_ALWAYS_ON_TOP", enabled)
}
if (id === "lightcord-4") {
if(enabled){
AntiAdDM.enable()
}else{
AntiAdDM.disable()
}
}
if (id === "lightcord-6") {
if(enabled){
blurPrivate.enable()
}else{
blurPrivate.disable()
}
}
if (id === "lightcord-7") {
if(enabled){
disableTyping.enable()
}else{
disableTyping.disable()
}
}
if (id === "lightcord-8"){
let appSettings = window.Lightcord.Api.settings
appSettings.set("isTabs", enabled)
appSettings.save()
DiscordNative.app.relaunch()
}
if (id === "lightcord-9") {
popoutWindow[enabled ? "enable" : "disable"]()
}
if (id === "lightcord-10"){
core.methods.NotificationsUseShim(enabled)
return
}
if (id === "no_window_bound"){
let appSettings = window.Lightcord.Api.settings
appSettings.set("NO_WINDOWS_BOUND", enabled)
appSettings.delete("IS_MAXIMIZED")
appSettings.delete("IS_MINIMIZED")
appSettings.delete("WINDOW_BOUNDS")
appSettings.save()
DiscordNative.app.relaunch()
}
if (id === "enable_glasstron"){
let appSettings = window.Lightcord.Api.settings
appSettings.set("GLASSTRON", enabled)
appSettings.save()
DiscordNative.app.relaunch()
}
if(id === "lightcord-11"){
let appSettings = window.Lightcord.Api.settings
if(!enabled){
appSettings.delete("BD_"+id)
appSettings.save()
return
}
appSettings.set("BD_"+id, enabled)
appSettings.save()
return
}
this.saveSettings();
}
async initializeSettings() {
if (settingsCookie["bda-gs-2"]) DOM.addClass(document.body, "bd-minimal");
if (settingsCookie["bda-gs-3"]) DOM.addClass(document.body, "bd-minimal-chan");
if (settingsCookie["bda-gs-1"]) publicServersModule.addButton();
if (settingsCookie["bda-gs-4"]) voiceMode.start();
if (settingsCookie["bda-gs-5"]) DOM.addClass(DOM.query("#app-mount"), "bda-dark");
if (settingsCookie["bda-gs-6"]) tfHour.inject24Hour();
if (settingsCookie["bda-gs-7"]) coloredText.injectColoredText();
if (settingsCookie["fork-ps-4"]) ClassNormalizer.start();
if (settingsCookie["lightcord-1"]) window.Lightcord.Settings.devMode = true
if (settingsCookie["lightcord-2"]) window.Lightcord.Settings.callRingingBeat = true
if (settingsCookie["lightcord-presence-1"]) CustomRichPresence.enable()
if (settingsCookie["lightcord-3"]) ipcRenderer.sendSync("LIGHTCORD_SET_ALWAYS_ON_TOP", true)
if (settingsCookie["lightcord-4"]) AntiAdDM.enable()
if (settingsCookie["lightcord-6"]) blurPrivate.enable()
if (settingsCookie["lightcord-7"]) disableTyping.enable()
if (settingsCookie["lightcord-9"]) popoutWindow.enable()
if (settingsCookie["fork-ps-5"]) {
ContentManager.watchContent("plugin");
ContentManager.watchContent("theme");
}
if (settingsCookie["bda-gs-8"]) dMode.startDebugListener();
if (settingsCookie["fork-dm-1"]) dMode.startCopySelector();
this.saveSettings();
}
saveSettings() {
DataStore.setSettingGroup("settings", settingsCookie);
DataStore.setSettingGroup("rpc", settingsRPC);
}
loadSettings() {
Object.assign(settingsCookie, DataStore.getSettingGroup("settings"));
Object.assign(settingsRPC, DataStore.getSettingGroup("rpc"));
}
renderSidebar(sidebar) {
return this.sidebar.render(sidebar);
}
coreComponent() {
return BDV2.react.createElement(SectionedSettingsPanel, {key: "cspanel", onChange: this.onChange, sections: this.coreSettings})
}
lightcordComponent(sidebar, forceUpdate) {
// this code is shit, I'm gonna rewritte everything in the next version
let appSettings = window.Lightcord.Api.settings
return [
this.lightcordSettings.map((section, i) => {
return [
(i === 0 ? null : BDV2.react.createElement(MarginTop)),
BDV2.react.createElement("h2", {className: "ui-form-title h2 margin-reset margin-bottom-20"}, section.title),
section.settings.map(setting => {
return React.createElement(() => {
const forceUpdate = useForceUpdate()
let isChecked = settingsCookie[setting.id]
if(setting.id === "lightcord-8")isChecked = appSettings.get("isTabs", false);
if(setting.id === "no_window_bound")isChecked = appSettings.get("NO_WINDOWS_BOUND", false)
if(setting.id === "enable_glasstron")isChecked = appSettings.get("GLASSTRON", true)
if(setting.id === "lightcord-10")isChecked = !appSettings.get("DEFAULT_NOTIFICATIONS", true)
let returnValue
if(["lightcord-11"].includes(setting.id)){
let value = appSettings.get("BD_"+setting.id, setting.default || "")
returnValue = BDV2.react.createElement(TextInputSetting, {id: setting.id, key: setting.id, data: setting, value, placeholder: setting.default || null, onChange: (id, value) => {
this.onChange(id, value, sidebar);
}})
}else{
returnValue = BDV2.react.createElement(Switch, {id: setting.id, key: setting.id, data: setting, checked: isChecked, onChange: (id, checked) => {
this.onChange(id, checked, sidebar);
forceUpdate()
}})
}
if(setting.id == "lightcord-8" && isChecked){
return [
returnValue,
React.createElement(Lightcord.Api.Components.inputs.Button, {
color: "green",
look: "outlined",
size: "small",
hoverColor: "brand",
onClick: () => {
DiscordNative.ipc.send("NEW_TAB")
},
wrapper: false,
disabled: false
}, "Open a new Tab")
]
}
if(setting.id === "enable_glasstron" && isChecked){
if(process.platform !== "linux"){
let choices = []
let actual = null
if(process.platform === "win32"){
choices.push("blurbehind", "acrylic", "transparent")
actual = appSettings.get("GLASSTRON_BLUR", "blurbehind")
}else if(process.platform === "darwin"){
choices.push("titlebar",
"selection",
"menu",
"popover",
"sidebar",
"header",
"sheet",
"window",
"hud",
"fullscreen-ui",
"tooltip",
"content",
"under-window",
"under-page",
"none"
)
actual = appSettings.get("GLASSTRON_VIBRANCY", "fullscreen-ui")
}
return [
returnValue,
React.createElement(Lightcord.Api.Components.general.SettingSubTitle, {}, "Glasstron Blur"),
React.createElement(Lightcord.Api.Components.inputs.Dropdown, {
options: choices.map(e => {
return {
value: e,
label: e
}
}),
value: actual,
disabled: false,
searchable: true,
clearable: false,
onChange: (value) => {
if(process.platform === "win32"){
ipcRenderer.invoke("LIGHTCORD_SET_BLUR_TYPE", value)
}else{
ipcRenderer.invoke("LIGHTCORD_SET_VIBRANCY", value)
}
}
}, null)
]
}
}
return returnValue
})
})
]
}),
BDV2.react.createElement(window.Lightcord.Api.Components.inputs.Button, {
color: "yellow",
look: "ghost",
size: "medium",
hoverColor: "red",
onClick(){
ipcRenderer.sendSync("LIGHTCORD_RELAUNCH_APP", {
args: remote.process.argv.slice(1).concat(["--disable-betterdiscord"])
})
},
wrapper: true
}, "Relaunch without BetterDiscord"),
React.createElement(Lightcord.Api.Components.inputs.Button, {
color: "yellow",
look: "ghost",
size: "medium",
hoverColor: "red",
onClick: () => {
if(isClearingCache)return
isClearingCache = true
Utils.showToast("Clearing cache...", {
type: "info"
})
forceUpdate()
remote.getCurrentWebContents().session.clearCache()
.then(() => {
Utils.showToast("Cache is cleared !", {
type: "success"
})
isClearingCache = false
forceUpdate()
}).catch(err => {
console.error(err)
Utils.showToast("An error occured. Check console for more informations.", {
type: "error"
})
isClearingCache = false
forceUpdate()
})
},
wrapper: true,
disabled: isClearingCache
}, "Clear cache"),
React.createElement(Lightcord.Api.Components.inputs.Button, {
color: "yellow",
look: "ghost",
size: "medium",
hoverColor: "red",
onClick: () => {
clearCaches()
ContentManager.resetAddonCache()
Utils.showToast("Cache is cleared !", {
type: "success"
})
},
wrapper: true,
disabled: false
}, "Clear Plugin Scan Cache")
]
}
PresenceComponent() {
return BDV2.react.createElement(V2C_PresenceSettings, {
key: "lppannel",
onChange: this.onChange,
settings: this.PresenceSettings
})
}
AccountInfosComponent() {
return BDV2.react.createElement(V2C_AccountInfos, {
key: "lapannel"
})
}
ApiPreviewComponent() {
return BDV2.react.createElement(ApiPreview, {
key: "lapipannel"
})
}
customCssComponent() {
return BDV2.react.createElement(CssEditor, {key: "csseditor"})
}
renderAddonPane(type) {
// I know this shouldn't be here, but when it isn't,
// React refuses to change the button when going
// between plugins and themes page... something
// to debug later.
class ContentList extends BDV2.react.Component {
constructor(props) {
super(props);
this.prefix = this.props.type.replace("s", "");
}
onChange() {
this.props.onChange(this.props.type);
}
render() {return this.props.children;}
}
const originalRender = ContentList.prototype.render;
Object.defineProperty(ContentList.prototype, "render", {
enumerable: false,
configurable: false,
set: function() {console.warn("Addon policy for plugins #5 https://github.com/rauenzi/BetterDiscordApp/wiki/Addon-Policies#plugins");},
get: () => originalRender
});
return function(){
return BDV2.react.createElement(ContentList, {type}, BDV2.react.createElement(CardList, {type}))
}
}
};
/**
* No need to export settingsPanel on window
*/
function makeComponent(children){
class SettingComponent extends React.Component {
render(){
return children(sidebar, () => this.forceUpdate())
}
}
let sidebar
return (s) => {
sidebar = s
return SettingComponent
}
}