mirror of
https://github.com/Lightcord/Lightcord.git
synced 2025-04-12 00:55:40 +02:00
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 {
|
||||
|
2
BetterDiscordApp/css/main.min.css
vendored
2
BetterDiscordApp/css/main.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
BetterDiscordApp/js/main.min.js
vendored
2
BetterDiscordApp/js/main.min.js
vendored
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
2
LightcordApi/js/main.min.js
vendored
2
LightcordApi/js/main.min.js
vendored
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…
x
Reference in New Issue
Block a user