RichPresence fix
Light theme semi-fix LightcordApi update
This commit is contained in:
parent
c96f94b314
commit
7ec315a11f
|
@ -1,21 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2015-present Jiiks | 2017-present Zack Rauen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2015-present Jiiks | 2017-present Zack Rauen | 2020-present Lightcord
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
|
@ -952,20 +952,13 @@ body .ace_closeButton:active {
|
|||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.theme-dark .ui-tab-bar-header .bd-changelog-button {
|
||||
color: #72767d;
|
||||
}
|
||||
.theme-light .ui-tab-bar-header .bd-changelog-button {
|
||||
color: #b9bbbe;
|
||||
}
|
||||
|
||||
.ui-tab-bar-header .bd-icon {
|
||||
cursor: pointer;
|
||||
fill: #72767d;
|
||||
fill: var(--text-muted);
|
||||
}
|
||||
|
||||
.ui-tab-bar-header .bd-icon:hover {
|
||||
fill: #fff;
|
||||
fill: var(--text-normal);
|
||||
}
|
||||
|
||||
.ui-tab-bar-separator {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,10 +1,11 @@
|
|||
/* BDEvents */
|
||||
const EventEmitter = require("events");
|
||||
export default new class BDEvents extends EventEmitter {
|
||||
constructor(){
|
||||
super()
|
||||
window.Lightcord.BetterDiscord.BDEvents = this
|
||||
}
|
||||
dispatch(eventName, ...args) {this.emit(eventName, ...args);}
|
||||
off(eventName, eventAction) {this.removeListener(eventName, eventAction);}
|
||||
/* BDEvents */
|
||||
const EventEmitter = require("events");
|
||||
|
||||
export default new class BDEvents extends EventEmitter {
|
||||
constructor(){
|
||||
super()
|
||||
window.Lightcord.BetterDiscord.BDEvents = this
|
||||
}
|
||||
dispatch(eventName, ...args) {this.emit(eventName, ...args);}
|
||||
off(eventName, eventAction) {this.removeListener(eventName, eventAction);}
|
||||
};
|
|
@ -1,149 +1,149 @@
|
|||
import {bdthemeErrors, themeCookie, settingsCookie, bdthemes} from "../0globals";
|
||||
import ContentManager from "./contentManager";
|
||||
import DataStore from "./dataStore";
|
||||
import BDEvents from "./bdEvents";
|
||||
import Utils from "./utils";
|
||||
import DOM from "./domtools";
|
||||
|
||||
class ThemeModule {
|
||||
constructor(){
|
||||
window.Lightcord.BetterDiscord.ThemeModule = this
|
||||
}
|
||||
get folder() {return ContentManager.themesFolder;}
|
||||
}
|
||||
|
||||
ThemeModule.prototype.loadThemes = async function () {
|
||||
this.loadThemeData();
|
||||
bdthemeErrors.splice(0, 0, ...(await ContentManager.loadThemes()));
|
||||
const themes = Object.keys(bdthemes);
|
||||
|
||||
for (let i = 0; i < themes.length; i++) {
|
||||
const theme = bdthemes[themes[i]];
|
||||
if (!themeCookie[theme.name]) themeCookie[theme.name] = false;
|
||||
if (themeCookie[theme.name]) DOM.addStyle(DOM.escapeID(theme.id), unescape(theme.css));
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
}
|
||||
for (const theme in themeCookie) {
|
||||
if (!bdthemes[theme]) delete themeCookie[theme];
|
||||
}
|
||||
this.saveThemeData();
|
||||
// if (settingsCookie["fork-ps-5"]) ContentManager.watchContent("theme");
|
||||
};
|
||||
|
||||
ThemeModule.prototype.enableTheme = function(name, reload = false) {
|
||||
themeCookie[name] = true;
|
||||
this.saveThemeData();
|
||||
const theme = bdthemes[name];
|
||||
DOM.addStyle(DOM.escapeID(theme.id), unescape(theme.css));
|
||||
if (settingsCookie["fork-ps-2"] && !reload) Utils.showToast(`${theme.name} v${theme.version} has been applied.`);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.enable = function (name, reload = false) {
|
||||
return this.enableTheme(name, reload);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.disableTheme = function(name, reload = false) {
|
||||
themeCookie[name] = false;
|
||||
this.saveThemeData();
|
||||
const theme = bdthemes[name];
|
||||
DOM.removeStyle(DOM.escapeID(theme.id));
|
||||
if (settingsCookie["fork-ps-2"] && !reload) Utils.showToast(`${theme.name} v${theme.version} has been disabled.`);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.disable = function (name, reload = false) {
|
||||
return this.disableTheme(name, reload);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.toggleTheme = function(theme) {
|
||||
if (themeCookie[theme]) this.disableTheme(theme);
|
||||
else this.enableTheme(theme);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.toggle = function (name, reload = false) {
|
||||
return this.toggleTheme(name, reload);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.loadTheme = async function(filename) {
|
||||
const error = await ContentManager.loadContent(filename, "theme");
|
||||
if (error) {
|
||||
if (settingsCookie["fork-ps-1"]) Utils.showContentErrors({themes: [error]});
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${filename} could not be loaded. It may not have been loaded.`, {type: "error"});
|
||||
return Utils.err("ContentManager", `${filename} could not be loaded.`, error);
|
||||
}
|
||||
const theme = Object.values(bdthemes).find(p => p.filename == filename);
|
||||
Utils.log("ContentManager", `${theme.name} v${theme.version} was loaded.`);
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme.name} v${theme.version} was loaded.`, {type: "success"});
|
||||
BDEvents.dispatch("theme-loaded", theme.name);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.unloadTheme = function(filenameOrName) {
|
||||
const bdtheme = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
|
||||
if (!bdtheme) return;
|
||||
const theme = bdtheme.name;
|
||||
if (themeCookie[theme]) this.disableTheme(theme, true);
|
||||
const error = ContentManager.unloadContent(bdthemes[theme].filename, "theme");
|
||||
delete bdthemes[theme];
|
||||
if (error) {
|
||||
if (settingsCookie["fork-ps-1"]) Utils.showContentErrors({themes: [error]});
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
|
||||
return Utils.err("ContentManager", `${theme} could not be unloaded. It may have not been loaded yet.`, error);
|
||||
}
|
||||
Utils.log("ContentManager", `${theme} was unloaded.`);
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme} was unloaded.`, {type: "success"});
|
||||
BDEvents.dispatch("theme-unloaded", theme);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.delete = function(filenameOrName) {
|
||||
const bdplugin = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
|
||||
if (!bdplugin) return;
|
||||
this.unloadTheme(bdplugin.filename);
|
||||
const fullPath = require("path").resolve(ContentManager.pluginsFolder, bdplugin.filename);
|
||||
require("fs").unlinkSync(fullPath);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.reloadTheme = async function(filenameOrName) {
|
||||
const bdtheme = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
|
||||
if (!bdtheme) return this.loadTheme(filenameOrName);
|
||||
const theme = bdtheme.name;
|
||||
const error = await ContentManager.reloadContent(bdthemes[theme].filename, "theme");
|
||||
if (themeCookie[theme]) this.disableTheme(theme, true), this.enableTheme(theme, true);
|
||||
if (error) {
|
||||
if (settingsCookie["fork-ps-1"]) Utils.showContentErrors({themes: [error]});
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme} could not be reloaded.`, {type: "error"});
|
||||
return Utils.err("ContentManager", `${theme} could not be reloaded.`, error);
|
||||
}
|
||||
Utils.log("ContentManager", `${theme} v${bdthemes[theme].version} was reloaded.`);
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme} v${bdthemes[theme].version} was reloaded.`, {type: "success"});
|
||||
BDEvents.dispatch("theme-reloaded", theme);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.reload = function(name) {
|
||||
return this.reloadTheme(name);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.edit = function(filenameOrName) {
|
||||
const bdplugin = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
|
||||
if (!bdplugin) return;
|
||||
const fullPath = require("path").resolve(ContentManager.themesFolder, bdplugin.filename);
|
||||
require("electron").shell.openItem(`${fullPath}`);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.updateThemeList = function() {
|
||||
const results = ContentManager.loadNewContent("theme");
|
||||
for (const filename of results.added) this.loadTheme(filename);
|
||||
for (const name of results.removed) this.unloadTheme(name);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.loadThemeData = function() {
|
||||
const saved = DataStore.getSettingGroup("themes");
|
||||
if (saved) {
|
||||
Object.assign(themeCookie, saved);
|
||||
}
|
||||
};
|
||||
|
||||
ThemeModule.prototype.saveThemeData = function () {
|
||||
DataStore.setSettingGroup("themes", themeCookie);
|
||||
};
|
||||
|
||||
import {bdthemeErrors, themeCookie, settingsCookie, bdthemes} from "../0globals";
|
||||
import ContentManager from "./contentManager";
|
||||
import DataStore from "./dataStore";
|
||||
import BDEvents from "./bdEvents";
|
||||
import Utils from "./utils";
|
||||
import DOM from "./domtools";
|
||||
|
||||
class ThemeModule {
|
||||
constructor(){
|
||||
window.Lightcord.BetterDiscord.ThemeModule = this
|
||||
}
|
||||
get folder() {return ContentManager.themesFolder;}
|
||||
}
|
||||
|
||||
ThemeModule.prototype.loadThemes = async function () {
|
||||
this.loadThemeData();
|
||||
bdthemeErrors.splice(0, 0, ...(await ContentManager.loadThemes()));
|
||||
const themes = Object.keys(bdthemes);
|
||||
|
||||
for (let i = 0; i < themes.length; i++) {
|
||||
const theme = bdthemes[themes[i]];
|
||||
if (!themeCookie[theme.name]) themeCookie[theme.name] = false;
|
||||
if (themeCookie[theme.name]) DOM.addStyle(DOM.escapeID(theme.id), unescape(theme.css));
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
}
|
||||
for (const theme in themeCookie) {
|
||||
if (!bdthemes[theme]) delete themeCookie[theme];
|
||||
}
|
||||
this.saveThemeData();
|
||||
// if (settingsCookie["fork-ps-5"]) ContentManager.watchContent("theme");
|
||||
};
|
||||
|
||||
ThemeModule.prototype.enableTheme = function(name, reload = false) {
|
||||
themeCookie[name] = true;
|
||||
this.saveThemeData();
|
||||
const theme = bdthemes[name];
|
||||
DOM.addStyle(DOM.escapeID(theme.id), unescape(theme.css));
|
||||
if (settingsCookie["fork-ps-2"] && !reload) Utils.showToast(`${theme.name} v${theme.version} has been applied.`);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.enable = function (name, reload = false) {
|
||||
return this.enableTheme(name, reload);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.disableTheme = function(name, reload = false) {
|
||||
themeCookie[name] = false;
|
||||
this.saveThemeData();
|
||||
const theme = bdthemes[name];
|
||||
DOM.removeStyle(DOM.escapeID(theme.id));
|
||||
if (settingsCookie["fork-ps-2"] && !reload) Utils.showToast(`${theme.name} v${theme.version} has been disabled.`);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.disable = function (name, reload = false) {
|
||||
return this.disableTheme(name, reload);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.toggleTheme = function(theme) {
|
||||
if (themeCookie[theme]) this.disableTheme(theme);
|
||||
else this.enableTheme(theme);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.toggle = function (name, reload = false) {
|
||||
return this.toggleTheme(name, reload);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.loadTheme = async function(filename) {
|
||||
const error = await ContentManager.loadContent(filename, "theme");
|
||||
if (error) {
|
||||
if (settingsCookie["fork-ps-1"]) Utils.showContentErrors({themes: [error]});
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${filename} could not be loaded. It may not have been loaded.`, {type: "error"});
|
||||
return Utils.err("ContentManager", `${filename} could not be loaded.`, error);
|
||||
}
|
||||
const theme = Object.values(bdthemes).find(p => p.filename == filename);
|
||||
Utils.log("ContentManager", `${theme.name} v${theme.version} was loaded.`);
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme.name} v${theme.version} was loaded.`, {type: "success"});
|
||||
BDEvents.dispatch("theme-loaded", theme.name);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.unloadTheme = function(filenameOrName) {
|
||||
const bdtheme = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
|
||||
if (!bdtheme) return;
|
||||
const theme = bdtheme.name;
|
||||
if (themeCookie[theme]) this.disableTheme(theme, true);
|
||||
const error = ContentManager.unloadContent(bdthemes[theme].filename, "theme");
|
||||
delete bdthemes[theme];
|
||||
if (error) {
|
||||
if (settingsCookie["fork-ps-1"]) Utils.showContentErrors({themes: [error]});
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
|
||||
return Utils.err("ContentManager", `${theme} could not be unloaded. It may have not been loaded yet.`, error);
|
||||
}
|
||||
Utils.log("ContentManager", `${theme} was unloaded.`);
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme} was unloaded.`, {type: "success"});
|
||||
BDEvents.dispatch("theme-unloaded", theme);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.delete = function(filenameOrName) {
|
||||
const bdtheme = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
|
||||
if (!bdtheme) return;
|
||||
this.unloadTheme(bdtheme.filename);
|
||||
const fullPath = require("path").resolve(ContentManager.themesFolder, bdtheme.filename);
|
||||
require("fs").unlinkSync(fullPath);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.reloadTheme = async function(filenameOrName) {
|
||||
const bdtheme = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
|
||||
if (!bdtheme) return this.loadTheme(filenameOrName);
|
||||
const theme = bdtheme.name;
|
||||
const error = await ContentManager.reloadContent(bdthemes[theme].filename, "theme");
|
||||
if (themeCookie[theme]) this.disableTheme(theme, true), this.enableTheme(theme, true);
|
||||
if (error) {
|
||||
if (settingsCookie["fork-ps-1"]) Utils.showContentErrors({themes: [error]});
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme} could not be reloaded.`, {type: "error"});
|
||||
return Utils.err("ContentManager", `${theme} could not be reloaded.`, error);
|
||||
}
|
||||
Utils.log("ContentManager", `${theme} v${bdthemes[theme].version} was reloaded.`);
|
||||
if (settingsCookie["fork-ps-2"]) Utils.showToast(`${theme} v${bdthemes[theme].version} was reloaded.`, {type: "success"});
|
||||
BDEvents.dispatch("theme-reloaded", theme);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.reload = function(name) {
|
||||
return this.reloadTheme(name);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.edit = function(filenameOrName) {
|
||||
const bdplugin = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
|
||||
if (!bdplugin) return;
|
||||
const fullPath = require("path").resolve(ContentManager.themesFolder, bdplugin.filename);
|
||||
require("electron").shell.openItem(`${fullPath}`);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.updateThemeList = function() {
|
||||
const results = ContentManager.loadNewContent("theme");
|
||||
for (const filename of results.added) this.loadTheme(filename);
|
||||
for (const name of results.removed) this.unloadTheme(name);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.loadThemeData = function() {
|
||||
const saved = DataStore.getSettingGroup("themes");
|
||||
if (saved) {
|
||||
Object.assign(themeCookie, saved);
|
||||
}
|
||||
};
|
||||
|
||||
ThemeModule.prototype.saveThemeData = function () {
|
||||
DataStore.setSettingGroup("themes", themeCookie);
|
||||
};
|
||||
|
||||
export default new ThemeModule();
|
|
@ -1,9 +1,7 @@
|
|||
import ErrorBoundary from "./errorBoundary";
|
||||
import ContentColumn from "./contentColumn";
|
||||
import Tools from "./tools";
|
||||
import ReloadIcon from "./reloadIcon";
|
||||
import AddonCard from "./addoncard";
|
||||
import Scroller from "./scroller";
|
||||
import Dropdown from "./components/dropdown";
|
||||
import Search from "./components/search";
|
||||
|
||||
|
@ -15,7 +13,8 @@ import themeModule from "../modules/themeModule";
|
|||
import WebpackModules from "../modules/webpackModules";
|
||||
import BdApi from "../modules/bdApi";
|
||||
import Utils from "../modules/utils";
|
||||
import tooltipWrap from "./tooltipWrap";
|
||||
import TooltipWrap from "./tooltipWrap";
|
||||
import bdEvents from "../modules/bdEvents";
|
||||
|
||||
const Tooltip = WebpackModules.findByDisplayName("Tooltip");
|
||||
|
||||
|
@ -32,6 +31,25 @@ export default class CardList extends BDV2.reactComponent {
|
|||
this.sort = this.sort.bind(this);
|
||||
this.reverse = this.reverse.bind(this);
|
||||
this.search = this.search.bind(this);
|
||||
|
||||
this.onAddonChanges = function(){
|
||||
this.forceUpdate()
|
||||
}
|
||||
this.onAddonChanges = this.onAddonChanges.bind(this)
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
const type = (this.isPlugins ? "plugin" : "theme") + "-"
|
||||
bdEvents.on(`${type}loaded`, this.onAddonChanges)
|
||||
bdEvents.on(`${type}unloaded`, this.onAddonChanges)
|
||||
bdEvents.on(`${type}reloaded`, this.onAddonChanges)
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
const type = (this.isPlugins ? "plugin" : "theme") + "-"
|
||||
bdEvents.off(`${type}loaded`, this.onAddonChanges)
|
||||
bdEvents.off(`${type}unloaded`, this.onAddonChanges)
|
||||
bdEvents.off(`${type}reloaded`, this.onAddonChanges)
|
||||
}
|
||||
|
||||
openFolder() {
|
||||
|
@ -154,7 +172,7 @@ export default class CardList extends BDV2.reactComponent {
|
|||
if(typeof window.PluginUpdates.checkAll !== "function")return null
|
||||
if(!this.isPlugins)return null
|
||||
|
||||
return <tooltipWrap text="Checks for updates of plugins that support this feature. Right-click for a list.">
|
||||
return <TooltipWrap text="Checks for updates of plugins that support this feature. Right-click for a list.">
|
||||
<span style={{marginLeft: "10px"}}>
|
||||
<Lightcord.Api.Components.inputs.Button color="brand" look="filled" size="min" hoverColor="default" onClick={() => {
|
||||
try{
|
||||
|
@ -174,7 +192,7 @@ export default class CardList extends BDV2.reactComponent {
|
|||
Check for Updates
|
||||
</Lightcord.Api.Components.inputs.Button>
|
||||
</span>
|
||||
</tooltipWrap>
|
||||
</TooltipWrap>
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class Delete extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "24px";
|
||||
return <svg className={this.props.className || ""} fill="#FFFFFF" viewBox="0 0 24 24" style={{width: size, height: size}} onClick={this.props.onClick}>
|
||||
<path fill="none" d="M0 0h24v24H0V0z"/><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/>
|
||||
<path fill="none" d="M0 0h24v24H0z"/>
|
||||
</svg>;
|
||||
}
|
||||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class Delete extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "24px";
|
||||
return <svg className={this.props.className || ""} fill="var(--text-normal)" viewBox="0 0 24 24" style={{width: size, height: size}} onClick={this.props.onClick}>
|
||||
<path fill="none" d="M0 0h24v24H0V0z"/><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/>
|
||||
<path fill="none" d="M0 0h24v24H0z"/>
|
||||
</svg>;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class DownArrow extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "16px";
|
||||
return <svg className={this.props.className || ""} fill="#FFFFFF" viewBox="0 0 24 24" style={{width: size, height: size}}>
|
||||
<path d="M8.12 9.29L12 13.17l3.88-3.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-4.59 4.59c-.39.39-1.02.39-1.41 0L6.7 10.7c-.39-.39-.39-1.02 0-1.41.39-.38 1.03-.39 1.42 0z"/>
|
||||
</svg>;
|
||||
}
|
||||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class DownArrow extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "16px";
|
||||
return <svg className={this.props.className || ""} fill="var(--text-normal)" viewBox="0 0 24 24" style={{width: size, height: size}}>
|
||||
<path d="M8.12 9.29L12 13.17l3.88-3.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-4.59 4.59c-.39.39-1.02.39-1.41 0L6.7 10.7c-.39-.39-.39-1.02 0-1.41.39-.38 1.03-.39 1.42 0z"/>
|
||||
</svg>;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class Edit extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "24px";
|
||||
return <svg className={this.props.className || ""} viewBox="0 0 24 24" fill="#FFFFFF" style={{width: size, height: size}} onClick={this.props.onClick}>
|
||||
<path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>;
|
||||
}
|
||||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class Edit extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "24px";
|
||||
return <svg className={this.props.className || ""} viewBox="0 0 24 24" fill="var(--text-normal)" style={{width: size, height: size}} onClick={this.props.onClick}>
|
||||
<path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
</svg>;
|
||||
}
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
{/* <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/>
|
||||
</svg> */}
|
||||
|
||||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class History extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "18px";
|
||||
return <svg viewBox="0 0 24 24" fill="#FFFFFF" className={this.props.className || ""} style={{width: size, height: size}} onClick={this.props.onClick}>
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/>
|
||||
</svg>;
|
||||
}
|
||||
{/* <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/>
|
||||
</svg> */}
|
||||
|
||||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class History extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "18px";
|
||||
return <svg viewBox="0 0 24 24" fill="var(--text-normal)" className={this.props.className || ""} style={{width: size, height: size}} onClick={this.props.onClick}>
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/>
|
||||
</svg>;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class Search extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "16px";
|
||||
return <svg className={this.props.className || ""} fill="#FFFFFF" viewBox="0 0 24 24" style={{width: size, height: size}}>
|
||||
<path fill="none" d="M0 0h24v24H0V0z"/>
|
||||
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
|
||||
</svg>;
|
||||
}
|
||||
import BDV2 from "../../modules/v2";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
export default class Search extends React.Component {
|
||||
render() {
|
||||
const size = this.props.size || "16px";
|
||||
return <svg className={this.props.className || ""} fill="var(--text-normal)" viewBox="0 0 24 24" style={{width: size, height: size}}>
|
||||
<path fill="none" d="M0 0h24v24H0V0z"/>
|
||||
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
|
||||
</svg>;
|
||||
}
|
||||
}
|
|
@ -7,7 +7,8 @@ import CustomRichPresence from "../modules/CustomRichPresence"
|
|||
import timestampRender from "./timestampRender"
|
||||
import { remote } from "electron";
|
||||
import MarginTop from "./margintop";
|
||||
|
||||
import Utils from "../modules/utils";
|
||||
import { uuidv4 } from "../modules/distant";
|
||||
|
||||
const React = BDV2.React;
|
||||
|
||||
|
@ -496,16 +497,12 @@ class RpcPreview extends React.Component {
|
|||
}
|
||||
|
||||
render(){
|
||||
let preview = new this.preview({
|
||||
preview: this
|
||||
})
|
||||
preview.setState(this.state.rpc)
|
||||
return (<div className="lc-tabWrapper">
|
||||
<div className="lc-tabnav" style={{flex: "0 1 auto"}}>
|
||||
<Tab preview={this} title="Full Profile" id="profile"/>
|
||||
<Tab preview={this} title="User Popout" id="popout"/>
|
||||
</div>
|
||||
{preview.render()}
|
||||
<PresenceErrorCatcher preview={this.preview} state={this.state.rpc} props={{preview: this}} key={this.state.active} />
|
||||
</div>)
|
||||
}
|
||||
|
||||
|
@ -550,6 +547,204 @@ class Tab extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
let emptyClasses
|
||||
class PresenceErrorCatcher extends React.Component {
|
||||
componentDidCatch(err, errInfo){
|
||||
console.error(err, errInfo)
|
||||
this.setState({
|
||||
error: true
|
||||
})
|
||||
}
|
||||
render(){
|
||||
if(!this.state){
|
||||
this.state = {
|
||||
error: false
|
||||
}
|
||||
}
|
||||
if(!this.state.error){
|
||||
try{
|
||||
const preview = new this.props.preview(this.props.props)
|
||||
preview.setState(this.props.state)
|
||||
return preview.render()
|
||||
}catch(err){
|
||||
console.error(err)
|
||||
this.state.error = true
|
||||
return this.render()
|
||||
}
|
||||
}else{
|
||||
emptyClasses = emptyClasses || BDV2.WebpackModules.find(e => e.emptyStateImage)
|
||||
if(!emptyClasses){
|
||||
Utils.showToast("An error occured. Please check the console for more informations.")
|
||||
return null
|
||||
}
|
||||
return <div style={{
|
||||
margin: "20px"
|
||||
}}>
|
||||
<div style={{
|
||||
backgroundColor: "var(--background-primary)",
|
||||
padding: "30px 30px",
|
||||
borderRadius: "8px"
|
||||
}} className="lc-tab-box-shadow">
|
||||
<div className={emptyClasses.emptyStateImage} style={{
|
||||
marginTop: "20px"
|
||||
}}>
|
||||
|
||||
</div>
|
||||
<div className={emptyClasses.emptyStateHeader}>An error occured</div>
|
||||
<p className={emptyClasses.emptyStateSubtext}>
|
||||
Please check the console for more informations. Join our
|
||||
<a className={`${BDV2.anchorClasses.anchor} ${BDV2.anchorClasses.anchorUnderlineOnHover}`} role="button" tabindex={0} onClick={() => {
|
||||
BDV2.joinLC()
|
||||
}}>
|
||||
support server
|
||||
</a>
|
||||
for help.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let popoutModules
|
||||
let UserPopoutComponent
|
||||
let PopoutProps
|
||||
class Popout extends React.Component {
|
||||
get modules(){
|
||||
return popoutModules || (popoutModules = [
|
||||
BDV2.WebpackModules.find(e => e.default && e.default.displayName === "FluxContainer(ForwardRef(SubscribeGuildMembersContainer(UserPopout)))"),
|
||||
BDV2.WebpackModules.find(e => e.default && e.default.getCurrentUser)
|
||||
])
|
||||
}
|
||||
|
||||
render(){
|
||||
let [
|
||||
UserPopout,
|
||||
userModule
|
||||
] = this.modules
|
||||
|
||||
const user = userModule.default.getCurrentUser()
|
||||
if(!UserPopoutComponent){
|
||||
if(!UserPopout)throw new Error(`Couldn't find the UserPopout component.`)
|
||||
const render1 = new UserPopout.default({userId: user.id, guildId: null, channelId: null, disableUserProfileLink: true}).render()
|
||||
PopoutProps = render1.props
|
||||
const render2 = render1.type.render(PopoutProps, null)
|
||||
const render3 = new render2.type(render2.props).render()
|
||||
UserPopoutComponent = render3.type
|
||||
}
|
||||
if(!UserPopoutComponent)throw new Error(`Couldn't find the UserPopoutComponent component.`)
|
||||
|
||||
let data = Object.assign({}, defaultRPC, this.props.preview.props.settings.state.data)
|
||||
const activity = (function(){
|
||||
if(!this.game)return null
|
||||
let game = {
|
||||
name: this.game.name || defaultRPC.name,
|
||||
application_id: this.game.application_id || defaultRPC.application_id,
|
||||
details: this.game.details || undefined,
|
||||
state: this.game.state || undefined,
|
||||
timestamps: this.game["timestamps.start"] ? {
|
||||
start: this.game["timestamps.start"]
|
||||
} : undefined,
|
||||
assets: this.game["assets.large"] ? {
|
||||
large_image: this.game["assets.large"],
|
||||
small_image: this.game["assets.small"] || undefined
|
||||
} : undefined,
|
||||
type: 0
|
||||
}
|
||||
return game
|
||||
}).call({
|
||||
game: data
|
||||
})
|
||||
|
||||
PopoutProps = new UserPopout.default({userId: user.id, guildId: null, channelId: null, disableUserProfileLink: true}).render().props
|
||||
const popout = new UserPopoutComponent(Object.assign({}, PopoutProps, {
|
||||
activity: activity
|
||||
})).render().props.children // bypass tracking
|
||||
|
||||
// remove the stop propagation shit.
|
||||
const container = <div {...window.Lightcord.Api._.excludeProperties(popout.props, ["onClick", "onContextMenu"])} />
|
||||
|
||||
return <div className="lc-userPopout lc-tab-box-shadow">
|
||||
{container}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
let profileModules
|
||||
let UserProfileComponent
|
||||
let ProfileProps
|
||||
let connectedProfileStore
|
||||
class Profile extends React.Component {
|
||||
get modules(){
|
||||
return profileModules || (profileModules = [
|
||||
BDV2.WebpackModules.find(e => e.default && e.default.displayName === "UserProfile"),
|
||||
BDV2.WebpackModules.find(e => e.default && e.default.getCurrentUser)
|
||||
])
|
||||
}
|
||||
|
||||
render(){
|
||||
let [
|
||||
UserProfile,
|
||||
userModule
|
||||
] = this.modules
|
||||
|
||||
const user = userModule.default.getCurrentUser()
|
||||
if(!UserProfileComponent){
|
||||
const render1 = new UserProfile.default({
|
||||
user: user
|
||||
}).render()
|
||||
connectedProfileStore = render1.type
|
||||
const render2 = new render1.type(render1.props).render()
|
||||
const render3 = render2.type.render(render2.props, null)
|
||||
const render4 = new render3.type(render3.props).render()
|
||||
UserProfileComponent = render4.type
|
||||
}
|
||||
if(!UserProfileComponent)throw new Error(`Couldn't find the UserProfileComponent component.`)
|
||||
|
||||
let data = Object.assign({}, defaultRPC, this.props.preview.props.settings.state.data)
|
||||
const activity = (function(){
|
||||
if(!this.game)return null
|
||||
let game = {
|
||||
name: this.game.name || defaultRPC.name,
|
||||
application_id: this.game.application_id || defaultRPC.application_id,
|
||||
details: this.game.details || undefined,
|
||||
state: this.game.state || undefined,
|
||||
timestamps: this.game["timestamps.start"] ? {
|
||||
start: this.game["timestamps.start"]
|
||||
} : undefined,
|
||||
assets: this.game["assets.large"] ? {
|
||||
large_image: this.game["assets.large"],
|
||||
small_image: this.game["assets.small"] || undefined
|
||||
} : undefined,
|
||||
type: 0
|
||||
}
|
||||
return game
|
||||
}).call({
|
||||
game: data
|
||||
})
|
||||
|
||||
ProfileProps = new connectedProfileStore({
|
||||
user: user,
|
||||
close: () => {}
|
||||
}).render().props
|
||||
const profile = new UserProfileComponent(Object.assign({}, ProfileProps, {
|
||||
activity: activity
|
||||
})).render().props.children // bypass tracking
|
||||
|
||||
console.log(profile)
|
||||
profile.props.style = {
|
||||
width: "auto"
|
||||
}
|
||||
|
||||
return <div className="lc-tab lc-tab-box-shadow">
|
||||
{profile}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
let popoutModule
|
||||
class Popout extends React.Component { // TODO: Probably use internal Components instead of making it from scratch.
|
||||
get modules(){
|
||||
|
@ -979,4 +1174,4 @@ class Timestamp extends React.Component {
|
|||
{this.props.message}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}*/
|
|
@ -1,23 +1,23 @@
|
|||
import BDV2 from "../modules/v2";
|
||||
import Tooltip from "./tooltip";
|
||||
|
||||
export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const {style = "black", side = "top", text = ""} = this.props;
|
||||
this.node = BDV2.reactDom.findDOMNode(this);
|
||||
this.tooltip = new Tooltip(this.node, text, {style, side});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.tooltip.hide();
|
||||
delete this.tooltip;
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.children;
|
||||
}
|
||||
import BDV2 from "../modules/v2";
|
||||
import Tooltip from "./tooltip";
|
||||
|
||||
export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const {style = "black", side = "top", text = ""} = this.props;
|
||||
this.node = BDV2.reactDom.findDOMNode(this);
|
||||
this.tooltip = new Tooltip(this.node, text, {style, side});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.tooltip.hide();
|
||||
delete this.tooltip;
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -176,7 +176,7 @@ export default class ColorPicker extends React.PureComponent<ColorPickerProps, {
|
|||
|
||||
static help = {
|
||||
info: "To convert hex colors to decimal, you can do `Lightcord.Api.Utils.HexColorToDecimal('#yourcolor')` and go back with `Lightcord.Api.Utils.DecimalColorToHex(7506394)`",
|
||||
warn: "The component may not appear instantly. The component need to be loaded, so you could experience 50-300ms loading time depending on your internet connection."
|
||||
warn: "The component may not appear instantly. The component needs to be loaded, so you could experience 50-300ms loading time depending on your internet connection."
|
||||
}
|
||||
}
|
||||
let AllPreviews
|
|
@ -4,6 +4,10 @@ import uuid from "./modules/uuid"
|
|||
import Utils from "./modules/Utils"
|
||||
import DiscordTools from "./modules/DiscordTools"
|
||||
import * as patchers from "./modules/patchers"
|
||||
import excludeProperties from "./modules/excludeProperties"
|
||||
import cloneNullProto from "./modules/cloneNullProto"
|
||||
import NOOP from "./modules/noop"
|
||||
import unfreeze from "./modules/Unfreeze"
|
||||
patchers.patch()
|
||||
|
||||
const LightcordApi = {
|
||||
|
@ -11,7 +15,13 @@ const LightcordApi = {
|
|||
Components: Components,
|
||||
uuid: uuid,
|
||||
Utils: Utils,
|
||||
DiscordTools: DiscordTools
|
||||
DiscordTools: DiscordTools,
|
||||
_: {
|
||||
excludeProperties: excludeProperties,
|
||||
cloneNullProto: cloneNullProto,
|
||||
NOOP: NOOP,
|
||||
unfreeze: unfreeze
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@ -47,7 +57,11 @@ export interface LightcordGlobal {
|
|||
devMode: boolean,
|
||||
callRingingBeat: boolean
|
||||
},
|
||||
Api: LightcordApiGlobal
|
||||
Api: LightcordApiGlobal,
|
||||
BetterDiscord: {
|
||||
BdApi: typeof import("@bandagedbd/bdapi").BdApi,
|
||||
[mod:string]:any
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,10 +43,15 @@ export default new class DiscordTools {
|
|||
return notification
|
||||
}
|
||||
|
||||
playSound(sound:Sound){
|
||||
createSound(sound:Sound){
|
||||
soundModule = soundModule || WebpackLoader.findByUniqueProperties(["createSound"])
|
||||
if(!soundModule)throw new WebpackLoaderError("Couldn't find soundModule here.")
|
||||
const created = soundModule.createSound(sound)
|
||||
return created
|
||||
}
|
||||
|
||||
playSound(sound:Sound){
|
||||
const created = this.createSound(sound)
|
||||
created.play()
|
||||
return created
|
||||
}
|
||||
|
@ -102,6 +107,45 @@ export class Notice extends EventEmitter {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be called whem the notice is removed.
|
||||
*/
|
||||
on(event: "removed", listener: () => void):this
|
||||
/**
|
||||
* Will be called when the notice is visible or not.
|
||||
*/
|
||||
on(event: "showing", listener: (isShowing:boolean) => void):this
|
||||
/**
|
||||
* Will be called when the notice queue changes.
|
||||
*/
|
||||
on(event: "index", listener: (index:number) => void):this
|
||||
on(event: string, listener: (...args:any[]) => void){
|
||||
return super.on(event, listener)
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be called whem the notice is removed.
|
||||
*/
|
||||
once(event: "removed", listener: () => void):this
|
||||
/**
|
||||
* Will be called when the notice is visible or not.
|
||||
*/
|
||||
once(event: "showing", listener: (isShowing:boolean) => void):this
|
||||
/**
|
||||
* Will be called when the notice queue changes.
|
||||
*/
|
||||
once(event: "index", listener: (index:number) => void):this
|
||||
once(event: string, listener: (...args:any[]) => void){
|
||||
return super.once(event, listener)
|
||||
}
|
||||
|
||||
off(event: "removed", listener: () => void):this
|
||||
off(event: "showing", listener: (isShowing:boolean) => void):this
|
||||
off(event: "index", listener: (index:number) => void):this
|
||||
off(event: string, listener: (...args:any[]) => void){
|
||||
return super.off(event, listener)
|
||||
}
|
||||
|
||||
state:{
|
||||
removed:boolean,
|
||||
showing:boolean,
|
||||
|
|
|
@ -38,7 +38,7 @@ export default new class Utils {
|
|||
}
|
||||
|
||||
FindReact(dom:Element, traverseUp:number = 0):React.Component|React.PureComponent{
|
||||
/** took from https://stackoverflow.com/questions/29321742/react-getting-a-component-from-a-dom-element-for-debugging */
|
||||
// taken from https://stackoverflow.com/questions/29321742/react-getting-a-component-from-a-dom-element-for-debugging#39165137
|
||||
const key = Object.keys(dom).find(key=>key.startsWith("__reactInternalInstance$"));
|
||||
const domFiber = dom[key];
|
||||
if (domFiber == null) return null;
|
||||
|
|
|
@ -47,7 +47,9 @@ export function patch(){
|
|||
})
|
||||
/** END NOTICE */
|
||||
|
||||
|
||||
/** START IN-APP NOTIFICATIONS */
|
||||
//getModule(e => true)
|
||||
/** END IN-APP NOTIFICATIONS */
|
||||
}
|
||||
|
||||
function getModule(filter: (mod:any) => boolean):Promise<any>{
|
||||
|
|
2
build.js
2
build.js
|
@ -3,7 +3,7 @@ const path = require("path")
|
|||
const terser = require("terser")
|
||||
const util = require("util")
|
||||
|
||||
const production = true
|
||||
const production = false
|
||||
|
||||
let fs = require("fs")
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
module.exports = require("@lightcord/api")
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "@lightcord/components",
|
||||
"version": "1.0.0",
|
||||
"description": "Components that can be found inside Ligthcord Api",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Lightcord",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "lightcord",
|
||||
"version": "0.1.2",
|
||||
"description": "",
|
||||
"description": "A simple - customizable - Discord Client.",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"compile": "node compile.js",
|
||||
|
|
|
@ -1,24 +1,25 @@
|
|||
// bootstrap constants
|
||||
// after startup, these constants will be merged into core module constants
|
||||
// since they are used in both locations (see app/Constants.js)
|
||||
|
||||
import { releaseChannel } from './buildInfo';
|
||||
import appSettings from './appSettings';
|
||||
const pak = require("../package.json")
|
||||
import * as path from "path"
|
||||
|
||||
const settings = appSettings.getSettings();
|
||||
|
||||
function capitalizeFirstLetter(s) {
|
||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||
}
|
||||
|
||||
export const APP_NAME = 'Lightcord' + (releaseChannel === 'stable' ? '' : capitalizeFirstLetter(releaseChannel));
|
||||
const APP_ID_BASE = 'com.squirrel';
|
||||
export const APP_ID = `${APP_ID_BASE}.${APP_NAME}.${APP_NAME}`;
|
||||
|
||||
export const API_ENDPOINT = settings.get('API_ENDPOINT') || 'https://discord.com/api';
|
||||
export const UPDATE_ENDPOINT = settings.get('UPDATE_ENDPOINT') || API_ENDPOINT;
|
||||
export const mainAppDirname = path.join(__dirname, "..")
|
||||
|
||||
export const version:string = pak.version
|
||||
// bootstrap constants
|
||||
// after startup, these constants will be merged into core module constants
|
||||
// since they are used in both locations (see app/Constants.js)
|
||||
|
||||
import { releaseChannel } from './buildInfo';
|
||||
import appSettings from './appSettings';
|
||||
const pak = require("../package.json" as any) as any
|
||||
import * as path from "path"
|
||||
|
||||
const settings = appSettings.getSettings();
|
||||
|
||||
function capitalizeFirstLetter(s) {
|
||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||
}
|
||||
|
||||
export const APP_NAME = 'Lightcord' + (releaseChannel === 'stable' ? '' : capitalizeFirstLetter(releaseChannel));
|
||||
const APP_ID_BASE = 'com.squirrel';
|
||||
export const APP_ID = `${APP_ID_BASE}.${APP_NAME}.${APP_NAME}`;
|
||||
|
||||
export const API_ENDPOINT = settings.get('API_ENDPOINT') || 'https://discord.com/api';
|
||||
export const UPDATE_ENDPOINT = settings.get('UPDATE_ENDPOINT') || API_ENDPOINT;
|
||||
export const mainAppDirname = path.join(__dirname, "..")
|
||||
|
||||
export const version:string = pak.version
|
||||
export const packageJSON:any = pak
|
36
src/index.ts
36
src/index.ts
|
@ -19,6 +19,8 @@ import * as moduleUpdater from "./common/moduleUpdater"
|
|||
import * as paths from "./common/paths"
|
||||
import { create } from "./singleInstance";
|
||||
import * as splashScreen from "./splashScreen"
|
||||
import { join } from "path"
|
||||
import { homedir } from "os"
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
// Some people are reporting audio problems on Linux that are fixed by setting
|
||||
|
@ -55,6 +57,22 @@ function hasArgvFlag(flag) {
|
|||
//Transform main thread into async
|
||||
(async function Main(){
|
||||
await electron.app.whenReady()
|
||||
|
||||
if(process.argv.includes("--should-create-shortcut")){
|
||||
console.log(`Creating shortcuts.`)
|
||||
if(process.platform === "win32"){
|
||||
electron.shell.writeShortcutLink(join(homedir(), "Desktop", "Lightcord.lnk"), "create", {
|
||||
"appUserModelId": Constants.APP_ID,
|
||||
description: Constants.packageJSON.description,
|
||||
target: process.execPath
|
||||
})
|
||||
electron.shell.writeShortcutLink(join(electron.app.getPath("appData"), "Microsoft", "Windows", "Start Menu", "Programs", "Lightcord.lnk"), "create", {
|
||||
"appUserModelId": Constants.APP_ID,
|
||||
description: Constants.packageJSON.description,
|
||||
target: process.execPath
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Initializing Lightcord.`)
|
||||
console.log(`Version: ${buildInfo.version}
|
||||
|
@ -82,14 +100,16 @@ commit: ${buildInfo.commit}`)
|
|||
|
||||
coreModule.setMainWindowVisible(!startMinimized)
|
||||
}, (args) => {
|
||||
if (args != null && args.length > 0 && args[0] === '--squirrel-uninstall') {
|
||||
electron.app.quit();
|
||||
return;
|
||||
}
|
||||
|
||||
if(args.length === 1 && args[0] === "--overlay-host"){ // this is a patch for Lightcord that focus itself
|
||||
//console.warn("OVERLAY HOST DÉTECTÉ. EVENNEMENT IGNORÉ MAIS POURRAIT CAUSER UN PROBLÈME.")
|
||||
return
|
||||
if(args && args.length > 0){
|
||||
if(args.length > 0 && args[0] === '--squirrel-uninstall') {
|
||||
electron.app.quit();
|
||||
return;
|
||||
}
|
||||
|
||||
if(args && args.length === 1 && args[0] === "--overlay-host"){ // this is a patch for Lightcord that focus itself
|
||||
//console.warn("OVERLAY HOST DÉTECTÉ. EVENNEMENT IGNORÉ MAIS POURRAIT CAUSER UN PROBLÈME.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (coreModule) {
|
||||
|
|
|
@ -1,106 +1,106 @@
|
|||
import * as electron from "electron"
|
||||
import * as net from "net"
|
||||
import * as path from "path"
|
||||
import * as fs from "fs"
|
||||
import * as os from "os"
|
||||
import * as buildinfo from "./buildInfo"
|
||||
|
||||
function deleteSocketFile(socketPath) {
|
||||
if (process.platform === 'win32') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fs.existsSync(socketPath)) {
|
||||
try {
|
||||
fs.unlinkSync(socketPath);
|
||||
} catch (error) {
|
||||
// Ignore ENOENT errors in case the file was deleted between the exists
|
||||
// check and the call to unlink sync. This occurred occasionally on CI
|
||||
// which is why this check is here.
|
||||
if (error.code !== 'ENOENT') {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates server to listen for additional atom application launches.
|
||||
*
|
||||
* You can run the command multiple times, but after the first launch
|
||||
* the other launches will just pass their information to this server and then
|
||||
* close immediately.
|
||||
*/
|
||||
function listenForArgumentsFromNewProcess(socketPath, callback) {
|
||||
deleteSocketFile(socketPath);
|
||||
|
||||
const server = net.createServer(connection => {
|
||||
connection.on('data', data => {
|
||||
const args = JSON.parse(data.toString());
|
||||
callback(args);
|
||||
});
|
||||
});
|
||||
server.listen(socketPath);
|
||||
server.on('error', error => console.error('Application server failed', error));
|
||||
return server;
|
||||
}
|
||||
|
||||
function tryStart(socketPath, callback, otherAppFound) {
|
||||
// FIXME: Sometimes when socketPath doesn't exist, net.connect would strangely
|
||||
// take a few seconds to trigger 'error' event, it could be a bug of node
|
||||
// or atom-shell, before it's fixed we check the existence of socketPath to
|
||||
// speedup startup.
|
||||
if (process.platform !== 'win32' && !fs.existsSync(socketPath)) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
const client = net.connect({ path: socketPath }, () => {
|
||||
client.write(JSON.stringify(process.argv.slice(1)), () => {
|
||||
client.end();
|
||||
otherAppFound();
|
||||
});
|
||||
});
|
||||
client.on('error', callback);
|
||||
}
|
||||
|
||||
function makeSocketPath() {
|
||||
let name = electron.app.name ? electron.app.name : electron.app.getName();
|
||||
if (buildinfo.releaseChannel !== 'stable') {
|
||||
name += buildinfo.releaseChannel;
|
||||
}
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
return '\\\\.\\pipe\\' + name + '-sock';
|
||||
} else {
|
||||
return path.join(os.tmpdir(), name + '.sock');
|
||||
}
|
||||
}
|
||||
|
||||
export function create(startCallback, newProcessCallback) {
|
||||
const socketPath = makeSocketPath();
|
||||
|
||||
tryStart(socketPath, () => {
|
||||
const server = listenForArgumentsFromNewProcess(socketPath, newProcessCallback);
|
||||
|
||||
electron.app.on('will-quit', () => {
|
||||
server.close();
|
||||
deleteSocketFile(socketPath);
|
||||
});
|
||||
|
||||
//@ts-ignore
|
||||
electron.app.on('will-exit', () => {
|
||||
server.close();
|
||||
deleteSocketFile(socketPath);
|
||||
});
|
||||
|
||||
startCallback();
|
||||
}, () => {
|
||||
console.log('Another instance exists. Quitting.');
|
||||
electron.app.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
export function pipeCommandLineArgs(noOtherAppFoundCallback, otherAppFound) {
|
||||
tryStart(makeSocketPath(), noOtherAppFoundCallback, otherAppFound);
|
||||
import * as electron from "electron"
|
||||
import * as net from "net"
|
||||
import * as path from "path"
|
||||
import * as fs from "fs"
|
||||
import * as os from "os"
|
||||
import * as buildinfo from "./buildInfo"
|
||||
|
||||
function deleteSocketFile(socketPath) {
|
||||
if (process.platform === 'win32') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fs.existsSync(socketPath)) {
|
||||
try {
|
||||
fs.unlinkSync(socketPath);
|
||||
} catch (error) {
|
||||
// Ignore ENOENT errors in case the file was deleted between the exists
|
||||
// check and the call to unlink sync. This occurred occasionally on CI
|
||||
// which is why this check is here.
|
||||
if (error.code !== 'ENOENT') {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates server to listen for additional atom application launches.
|
||||
*
|
||||
* You can run the command multiple times, but after the first launch
|
||||
* the other launches will just pass their information to this server and then
|
||||
* close immediately.
|
||||
*/
|
||||
function listenForArgumentsFromNewProcess(socketPath, callback) {
|
||||
deleteSocketFile(socketPath);
|
||||
|
||||
const server = net.createServer(connection => {
|
||||
connection.on('data', data => {
|
||||
const args = JSON.parse(data.toString());
|
||||
callback(args);
|
||||
});
|
||||
});
|
||||
server.listen(socketPath);
|
||||
server.on('error', error => console.error('Application server failed', error));
|
||||
return server;
|
||||
}
|
||||
|
||||
function tryStart(socketPath, callback, otherAppFound) {
|
||||
// FIXME: Sometimes when socketPath doesn't exist, net.connect would strangely
|
||||
// take a few seconds to trigger 'error' event, it could be a bug of node
|
||||
// or atom-shell, before it's fixed we check the existence of socketPath to
|
||||
// speedup startup.
|
||||
if (process.platform !== 'win32' && !fs.existsSync(socketPath)) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
const client = net.connect({ path: socketPath }, () => {
|
||||
client.write(JSON.stringify(process.argv.slice(1)), () => {
|
||||
client.end();
|
||||
otherAppFound();
|
||||
});
|
||||
});
|
||||
client.on('error', callback);
|
||||
}
|
||||
|
||||
function makeSocketPath() {
|
||||
let name = electron.app.name ? electron.app.name : electron.app.getName();
|
||||
if (buildinfo.releaseChannel !== 'stable') {
|
||||
name += buildinfo.releaseChannel;
|
||||
}
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
return '\\\\.\\pipe\\' + name + '-sock';
|
||||
} else {
|
||||
return path.join(os.tmpdir(), name + '.sock');
|
||||
}
|
||||
}
|
||||
|
||||
export function create(startCallback, newProcessCallback) {
|
||||
const socketPath = makeSocketPath();
|
||||
|
||||
tryStart(socketPath, () => {
|
||||
const server = listenForArgumentsFromNewProcess(socketPath, newProcessCallback);
|
||||
|
||||
electron.app.on('will-quit', () => {
|
||||
server.close();
|
||||
deleteSocketFile(socketPath);
|
||||
});
|
||||
|
||||
//@ts-ignore
|
||||
electron.app.on('will-exit', () => {
|
||||
server.close();
|
||||
deleteSocketFile(socketPath);
|
||||
});
|
||||
|
||||
startCallback();
|
||||
}, () => {
|
||||
console.log('Another instance exists. Quitting.');
|
||||
electron.app.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
export function pipeCommandLineArgs(noOtherAppFoundCallback, otherAppFound) {
|
||||
tryStart(makeSocketPath(), noOtherAppFoundCallback, otherAppFound);
|
||||
}
|
Loading…
Reference in New Issue