sltsv dsl
|
@ -563,7 +563,7 @@
|
|||
font-weight: 500;
|
||||
}
|
||||
|
||||
#pubslayer #bd-settings-sidebar .ui-tab-bar-separator {
|
||||
#pubslayer .ui-tab-bar-separator {
|
||||
background-color: hsla(218,5%,47%,.3);
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
|
@ -899,7 +899,7 @@ body .ace_closeButton:active {
|
|||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#bd-settings-sidebar .ui-tab-bar-item {
|
||||
.ui-tab-bar-item {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
|
@ -912,33 +912,33 @@ body .ace_closeButton:active {
|
|||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
#bd-settings-sidebar .ui-tab-bar-item.selected {
|
||||
.ui-tab-bar-item.selected {
|
||||
cursor: default;
|
||||
}
|
||||
.theme-dark #bd-settings-sidebar .ui-tab-bar-item {
|
||||
.theme-dark .ui-tab-bar-item {
|
||||
color: #b9bbbe;
|
||||
}
|
||||
.theme-dark #bd-settings-sidebar .ui-tab-bar-item:hover {
|
||||
.theme-dark .ui-tab-bar-item:hover {
|
||||
background-color: var(--background-modifier-hover);
|
||||
color: var(--interactive-hover);
|
||||
}
|
||||
.theme-dark #bd-settings-sidebar .ui-tab-bar-item.selected {
|
||||
.theme-dark .ui-tab-bar-item.selected {
|
||||
background-color: var(--background-modifier-selected);
|
||||
color: #fff;
|
||||
}
|
||||
.theme-light #bd-settings-sidebar .ui-tab-bar-item {
|
||||
.theme-light .ui-tab-bar-item {
|
||||
color: #72767d;
|
||||
}
|
||||
.theme-light #bd-settings-sidebar .ui-tab-bar-item:hover {
|
||||
.theme-light .ui-tab-bar-item:hover {
|
||||
background-color: var(--background-modifier-hover);
|
||||
color: var(--interactive-hover);
|
||||
}
|
||||
.theme-light #bd-settings-sidebar .ui-tab-bar-item.selected {
|
||||
.theme-light .ui-tab-bar-item.selected {
|
||||
background-color: var(--background-modifier-selected);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#bd-settings-sidebar .ui-tab-bar-header {
|
||||
.ui-tab-bar-header {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
line-height: 16px;
|
||||
|
@ -949,37 +949,33 @@ body .ace_closeButton:active {
|
|||
padding: 6px 10px;
|
||||
overflow: hidden;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.theme-dark #bd-settings-sidebar .ui-tab-bar-header {
|
||||
|
||||
.theme-dark .ui-tab-bar-header .bd-changelog-button {
|
||||
color: #72767d;
|
||||
}
|
||||
.theme-light #bd-settings-sidebar .ui-tab-bar-header {
|
||||
.theme-light .ui-tab-bar-header .bd-changelog-button {
|
||||
color: #b9bbbe;
|
||||
}
|
||||
|
||||
#bd-settings-sidebar .ui-tab-bar-header .bd-changelog-button {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
#bd-settings-sidebar .ui-tab-bar-header .bd-icon {
|
||||
.ui-tab-bar-header .bd-icon {
|
||||
cursor: pointer;
|
||||
fill: #72767d;
|
||||
}
|
||||
|
||||
#bd-settings-sidebar .ui-tab-bar-header .bd-icon:hover {
|
||||
.ui-tab-bar-header .bd-icon:hover {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
#bd-settings-sidebar .ui-tab-bar-separator {
|
||||
.ui-tab-bar-separator {
|
||||
height: 1px;
|
||||
margin: 8px 10px;
|
||||
}
|
||||
.theme-dark #bd-settings-sidebar .ui-tab-bar-separator {
|
||||
.theme-dark .ui-tab-bar-separator {
|
||||
background-color: rgba(114,118,125,.3);
|
||||
}
|
||||
.theme-light #bd-settings-sidebar .ui-tab-bar-separator {
|
||||
.theme-light .ui-tab-bar-separator {
|
||||
background-color: rgba(185,187,190,.3);
|
||||
}
|
||||
|
||||
|
|
|
@ -250,3 +250,5 @@ BdApi.Plugins = makeAddonAPI(pluginCookie, bdplugins, pluginModule);
|
|||
BdApi.Themes = makeAddonAPI(themeCookie, bdthemes, themeModule);
|
||||
|
||||
export default BdApi;
|
||||
|
||||
window.Lightcord.BetterDiscord.BdApi = BdApi
|
|
@ -1,6 +1,10 @@
|
|||
/* 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);}
|
||||
};
|
|
@ -4,7 +4,9 @@ const normalizedPrefix = "da";
|
|||
const randClass = new RegExp(`^(?!${normalizedPrefix}-)((?:[A-Za-z]|[0-9]|-)+)-(?:[A-Za-z]|[0-9]|-|_){6}$`);
|
||||
|
||||
export default new class ClassNormalizer {
|
||||
|
||||
constructor(){
|
||||
window.Lightcord.BetterDiscord.BDEvents = this
|
||||
}
|
||||
stop() {
|
||||
if (!this.hasPatched) return;
|
||||
this.unpatchClassModules(WebpackModules.findAll(this.moduleFilter.bind(this)));
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import {bdConfig, bdplugins, bdthemes} from "../0globals";
|
||||
import {bdConfig, bdplugins, bdthemes, settingsCookie} from "../0globals";
|
||||
import pluginModule from "./pluginModule";
|
||||
import themeModule from "./themeModule";
|
||||
import Utils from "./utils";
|
||||
import * as crypto from "crypto"
|
||||
import dataStore from "./dataStore";
|
||||
import pluginCertifier, { encryptSettingsCache, decryptSettingsCache, processFile } from "./pluginCertifier";
|
||||
import { captureRejectionSymbol } from "events";
|
||||
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
@ -19,6 +22,7 @@ const originalCSSRequire = Module._extensions[".css"] ? Module._extensions[".css
|
|||
const splitRegex = /[^\S\r\n]*?(?:\r\n|\n)[^\S\r\n]*?\*[^\S\r\n]?/;
|
||||
const escapedAtRegex = /^\\@/;
|
||||
|
||||
export let addonCache = {}
|
||||
|
||||
export default new class ContentManager {
|
||||
|
||||
|
@ -32,6 +36,50 @@ export default new class ContentManager {
|
|||
get pluginsFolder() {return this._pluginsFolder || (this._pluginsFolder = fs.realpathSync(path.resolve(bdConfig.dataPath + "plugins/")));}
|
||||
get themesFolder() {return this._themesFolder || (this._themesFolder = fs.realpathSync(path.resolve(bdConfig.dataPath + "themes/")));}
|
||||
|
||||
loadAddonCertifierCache(){
|
||||
if(typeof dataStore.getSettingGroup("PluginCertifierHashes") !== "string"){
|
||||
dataStore.setSettingGroup("PluginCertifierHashes", encryptSettingsCache("{}"))
|
||||
}else{
|
||||
try{
|
||||
addonCache = JSON.parse(decryptSettingsCache(dataStore.getSettingGroup("PluginCertifierHashes")))
|
||||
}catch(e){
|
||||
dataStore.setSettingGroup("PluginCertifierHashes", encryptSettingsCache("{}"))
|
||||
addonCache = {}
|
||||
}
|
||||
}
|
||||
Object.keys(addonCache)
|
||||
.forEach(key => {
|
||||
let value = addonCache[key]
|
||||
if(!value || typeof value !== "object" || Array.isArray(value))return delete addonCache[key]
|
||||
|
||||
let props = [{
|
||||
key: "timestamp",
|
||||
type: "number"
|
||||
}, {
|
||||
key: "result",
|
||||
type: "object"
|
||||
}, {
|
||||
key: "hash",
|
||||
type: "string"
|
||||
}]
|
||||
for(let prop of props){
|
||||
if(!(prop.key in value) || typeof value[prop.key] !== prop.type){
|
||||
delete addonCache[key]
|
||||
return
|
||||
}
|
||||
}
|
||||
if(value.hash !== key){
|
||||
delete addonCache[key]
|
||||
return
|
||||
}
|
||||
})
|
||||
this.saveAddonCache()
|
||||
}
|
||||
|
||||
saveAddonCache(){
|
||||
dataStore.setSettingGroup("PluginCertifierHashes", encryptSettingsCache(JSON.stringify(addonCache)))
|
||||
}
|
||||
|
||||
watchContent(contentType) {
|
||||
if (this.watchers[contentType]) return;
|
||||
const isPlugin = contentType === "plugin";
|
||||
|
@ -171,6 +219,39 @@ export default new class ContentManager {
|
|||
if (typeof(filename) === "undefined" || typeof(type) === "undefined") return;
|
||||
const isPlugin = type === "plugin";
|
||||
const baseFolder = isPlugin ? this.pluginsFolder : this.themesFolder;
|
||||
|
||||
if(settingsCookie["fork-ps-6"]){
|
||||
let result = await new Promise(resolve => {
|
||||
processFile(path.resolve(baseFolder, filename), (result) => {
|
||||
console.log(result)
|
||||
resolve(result)
|
||||
}, (hash) => {
|
||||
resolve({
|
||||
suspect: false,
|
||||
hash: hash,
|
||||
filename: filename,
|
||||
name: filename
|
||||
})
|
||||
}, true)
|
||||
})
|
||||
if(result){
|
||||
addonCache[result.hash] = {
|
||||
timestamp: Date.now(),
|
||||
hash: result.hash,
|
||||
result: result
|
||||
}
|
||||
this.saveAddonCache()
|
||||
if(result.suspect){
|
||||
return {
|
||||
name: filename,
|
||||
file: filename,
|
||||
message: "This plugin might be dangerous ("+result.harm+").",
|
||||
error: new Error("This plugin might be dangerous ("+result.harm+").")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {window.require(path.resolve(baseFolder, filename));}
|
||||
catch (error) {return {name: filename, file: filename, message: "Could not be compiled.", error: {message: error.message, stack: error.stack}};}
|
||||
const content = window.require(path.resolve(baseFolder, filename));
|
||||
|
@ -245,3 +326,7 @@ export default new class ContentManager {
|
|||
loadPlugins() {return this.loadAllContent("plugin");}
|
||||
loadThemes() {return this.loadAllContent("theme");}
|
||||
};
|
||||
|
||||
/**
|
||||
* Don't expose contentManager - could be dangerous for now
|
||||
*/
|
|
@ -18,6 +18,7 @@ import EmojiModule from "./emojiModule"
|
|||
import {remote as electron} from "electron"
|
||||
import v2 from "./v2";
|
||||
import webpackModules from "./webpackModules";
|
||||
import contentManager from "./contentManager";
|
||||
|
||||
function Core() {
|
||||
// Object.assign(bdConfig, __non_webpack_require__(DataStore.configFile));
|
||||
|
@ -81,6 +82,9 @@ Core.prototype.init = async function() {
|
|||
Utils.log("Startup", "Updating Settings");
|
||||
settingsPanel.initializeSettings();
|
||||
|
||||
Utils.log("Startup", "Loading Addons Cache")
|
||||
await contentManager.loadAddonCertifierCache()
|
||||
|
||||
Utils.log("Startup", "Loading Plugins");
|
||||
await pluginModule.loadPlugins();
|
||||
|
||||
|
@ -147,16 +151,61 @@ Core.prototype.patchAttributes = async function() {
|
|||
|
||||
while(!v2.MessageComponent)await new Promise(resolve => setTimeout(resolve, 100))
|
||||
|
||||
window.Lightcord.Api.ensureExported(e => e.default && e.default.displayName && e.default.displayName.includes("UserPopout"))
|
||||
.then(UserPopout => {
|
||||
console.log(UserPopout)
|
||||
const render = UserPopout.default.prototype.render
|
||||
UserPopout.default.prototype.render = function(){
|
||||
const returnValue = render.call(this, ...arguments)
|
||||
console.log(returnValue, this.props)
|
||||
return returnValue
|
||||
// TODO: try to patch correctly the user popout on a next update
|
||||
const Anchor = WebpackModules.find(m => m.displayName == "Anchor");
|
||||
ensureExported(e => e.default && e.default.displayName === "DiscordTag")
|
||||
.then(DiscordTag => {
|
||||
let DiscordTagComp = DiscordTag.default
|
||||
DiscordTag.default = function(props){
|
||||
let returnValue = DiscordTagComp(props)
|
||||
|
||||
let id = uuidv4()
|
||||
|
||||
let badgeDiv = BDV2.React.createElement("div", {
|
||||
style: {
|
||||
display: "inline",
|
||||
marginTop: "5px"
|
||||
}
|
||||
}, BDV2.React.createElement("span", {
|
||||
id: "badges-"+id,
|
||||
key: "badges-"+id,
|
||||
style: {
|
||||
display: "inherit"
|
||||
}
|
||||
}))
|
||||
|
||||
let children = [returnValue]
|
||||
|
||||
if (props.user.id === "249746236008169473") { // Rauenzi: BandagedBD Developer
|
||||
children.push(
|
||||
BDV2.React.createElement(TooltipWrap, {color: "black", side: "top", text: "BandagedBD Developer"},
|
||||
BDV2.React.createElement(Anchor, {className: "bd-chat-badge", href: "https://github.com/rauenzi/BetterDiscordApp", title: "BandagedBD", target: "_blank"},
|
||||
BDV2.React.createElement(BDLogo, {size: "16px", className: "bd-logo"})
|
||||
)
|
||||
)
|
||||
);
|
||||
} else if (props.user.id === "696481194443014174" || props.user.id === "696003456611385396"){ // Not Thomiz: Lightcord Developer, Phorcys: Lightcord Developer
|
||||
children.push(
|
||||
BDV2.React.createElement(TooltipWrap, {color: "black", side: "top", text: "Lightcord Developer"},
|
||||
BDV2.React.createElement(Anchor, {className: "bd-chat-badge", href: "https://github.com/Lightcord/Lightcord", title: "Lightcord", target: "_blank"},
|
||||
BDV2.React.createElement(LightcordLogo, {size: "16px", className: "bd-logo"})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
children.push(badgeDiv)
|
||||
let div = BDV2.React.createElement("div", {
|
||||
style: {
|
||||
display: "block"
|
||||
}
|
||||
}, children)
|
||||
applyBadges(id, props.user, false)
|
||||
|
||||
return div
|
||||
}
|
||||
})
|
||||
|
||||
attribsPatchs.push(Utils.monkeyPatch(v2.MessageComponent, "default", {after: (data) => {
|
||||
if(data.methodArguments[0].childrenMessageContent.props.message){ // this can be a blocked message (not opened)
|
||||
data.returnValue.props["data-message-id"] = data.methodArguments[0].childrenMessageContent.props.message.id
|
||||
|
@ -414,6 +463,7 @@ Core.prototype.patchAttachment = function() {
|
|||
const Anchor = WebpackModules.find(m => m.displayName == "Anchor");
|
||||
if (!Anchor || !Attachment || !Attachment.default) return;
|
||||
this.AttachmentPatch = Utils.monkeyPatch(Attachment, "default", {after: (data) => {
|
||||
if(!settingsCookie["fork-ps-6"])return
|
||||
const attachment = data.methodArguments[0] || null
|
||||
const children = Utils.getNestedProp(data.returnValue, "props.children");
|
||||
|
||||
|
@ -421,7 +471,7 @@ Core.prototype.patchAttachment = function() {
|
|||
if (!Array.isArray(children)) return;
|
||||
|
||||
const id = uuidv4()
|
||||
children.push(BDV2.react.createElement("div", {
|
||||
children.push(BDV2.react.createElement("span", {
|
||||
id: "certified-"+id
|
||||
}))
|
||||
PluginCertifier.patch(attachment, "certified-"+id)
|
||||
|
@ -645,3 +695,7 @@ Core.prototype.updateInjector = async function() {
|
|||
};
|
||||
|
||||
export default new Core();
|
||||
|
||||
/**
|
||||
* Don't expose core - could be dangerous for now
|
||||
*/
|
|
@ -12,6 +12,7 @@ export default new class DataStore {
|
|||
constructor() {
|
||||
this.data = {settings: {stable: {}, canary: {}, ptb: {}}};
|
||||
this.pluginData = {};
|
||||
window.Lightcord.BetterDiscord.DataStore = this
|
||||
}
|
||||
|
||||
initialize() {
|
||||
|
|
|
@ -13,6 +13,7 @@ export default new class DisableTyping {
|
|||
}
|
||||
this.disabled = true
|
||||
})
|
||||
window.Lightcord.BetterDiscord.DisableTyping = this
|
||||
}
|
||||
|
||||
disable(){
|
||||
|
|
|
@ -21,6 +21,7 @@ export default new class DistantServer {
|
|||
|
||||
}
|
||||
}
|
||||
window.Lightcord.BetterDiscord.DistantServer = this
|
||||
}
|
||||
|
||||
get cache(){
|
||||
|
@ -140,7 +141,7 @@ class LightcordError extends Error {
|
|||
}
|
||||
|
||||
export const Constants = {
|
||||
SERVER_URL: "http://127.0.0.1",
|
||||
SERVER_URL: "https://lightcord.deroku.xyz/",
|
||||
badges: [ // TODO:
|
||||
/*{
|
||||
name: "Lightcord User",
|
||||
|
@ -159,22 +160,22 @@ export const Constants = {
|
|||
],
|
||||
scopes: [],
|
||||
component: BugHunterBadge,
|
||||
href: "https://github.com/lightcord/lightcord/wiki/badges/bug_hunter"
|
||||
href: "https://github.com/lightcord/lightcord/wiki/badges#bug_hunter"
|
||||
}, {
|
||||
name: "Buffoon",
|
||||
id: "06904d31-65b4-41ec-a50c-8658bbd1af96",
|
||||
defaultUsers: [
|
||||
"389016895543705602",
|
||||
"664600134528663565"
|
||||
"664600134528663565",
|
||||
"625350657829896224"
|
||||
],
|
||||
scopes: [],
|
||||
component: Circus,
|
||||
href: "https://www.youtube.com/watch?v=EJtb6z-dlT8"
|
||||
href: "https://youtu.be/EJtb6z-dlT8?t=145"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export const Routes = {
|
||||
badges: `/users/badges`,
|
||||
delete: `/delete`
|
||||
badges: `/users/badges`
|
||||
}
|
|
@ -1,8 +1,5 @@
|
|||
import {bdConfig, settingsCookie} from "../0globals";
|
||||
import DataStore from "./dataStore";
|
||||
import BDV2 from "./v2";
|
||||
import Utils from "./utils";
|
||||
//import DiscordCrypt from "./DiscordCrypt";
|
||||
|
||||
const Constants = {
|
||||
EmojiRegex: /<a?\.(\w+)\.(\d+)>/g
|
||||
|
@ -19,7 +16,7 @@ let emojiSearch = BDModules.get(e => e.default && e.default.getDisambiguatedEmoj
|
|||
|
||||
export default new class EmojiModule {
|
||||
constructor(){
|
||||
this.init()
|
||||
this.init().catch(err => Utils.err("EmojiModule", "An error occured", err)) // better logging
|
||||
}
|
||||
|
||||
async init(){
|
||||
|
@ -30,6 +27,7 @@ export default new class EmojiModule {
|
|||
if(!Messages)Messages = await window.Lightcord.Api.ensureExported(e => e.default && e.default.Messages && e.default.Messages.EMOJI_MATCHING)
|
||||
if(!guildModule)guildModule = await window.Lightcord.Api.ensureExported(e => e.default && e.default.getGuild && e.default.getGuilds && !e.default.isFetching)
|
||||
if(!emojiSearch)emojiSearch = await window.Lightcord.Api.ensureExported(e => e.default && e.default.getDisambiguatedEmojiContext)
|
||||
|
||||
if(AutocompleteModule && AutoCompletionTemplates && EmojiModuleQuery && Messages && guildModule && emojiSearch){
|
||||
console.log(`Patching getAutocompleteOptions of AutoCompletionTemplates`, AutoCompletionTemplates)
|
||||
const getAutocompleteOptions = AutoCompletionTemplates.getAutocompleteOptions
|
||||
|
@ -80,15 +78,14 @@ export default new class EmojiModule {
|
|||
|
||||
/** Emoji display */
|
||||
while (!BDV2.MessageComponent) await new Promise(resolve => setTimeout(resolve, 100));
|
||||
if (!this.cancelEmojiRender){
|
||||
|
||||
if (!this.cancelEmojiRender){ // TODO: Proper emoji formatting / rendering
|
||||
this.cancelEmoteRender = Utils.monkeyPatch(BDV2.MessageComponent, "default", {before: (data) => {
|
||||
const message = Utils.getNestedProp(data.methodArguments[0], "childrenMessageContent.props.message")
|
||||
if(!message)return
|
||||
const content = Utils.getNestedProp(data.methodArguments[0], "childrenMessageContent.props.content")
|
||||
if(!content || !content.length)return
|
||||
|
||||
// content = DiscordCrypt.decryptContent(content)
|
||||
|
||||
/**
|
||||
* @type {{
|
||||
* raw: string,
|
||||
|
|
|
@ -4,14 +4,18 @@ import * as crypto from "crypto"
|
|||
import BDV2 from "./v2"
|
||||
import tooltipWrap from "../ui/tooltipWrap"
|
||||
import Utils from "./utils"
|
||||
import { createReadStream } from "fs"
|
||||
import { basename } from "path"
|
||||
import { createReadStream, writeFileSync } from "fs"
|
||||
import { basename, join } from "path"
|
||||
import contentManager from "./contentManager"
|
||||
import { addonCache } from "./contentManager"
|
||||
|
||||
const cache = {}
|
||||
const cache2 = {}
|
||||
|
||||
export default new class PluginCertifier {
|
||||
constructor(){}
|
||||
constructor(){
|
||||
window.Lightcord.BetterDiscord.PluginCertifier = this
|
||||
}
|
||||
|
||||
patch(attachment, id){
|
||||
process.nextTick(() => {
|
||||
|
@ -28,7 +32,7 @@ export default new class PluginCertifier {
|
|||
}
|
||||
}
|
||||
|
||||
export function checkViruses(hash, data, resultCallback, removeCallback){
|
||||
export function checkViruses(hash, data, resultCallback, removeCallback, filename){
|
||||
data = data.toString("utf8")
|
||||
let isHarmful = false
|
||||
for(let keyword of data.split(/[^\w\d]+/g)){
|
||||
|
@ -78,12 +82,14 @@ export function checkViruses(hash, data, resultCallback, removeCallback){
|
|||
}
|
||||
}
|
||||
|
||||
if(!isHarmful)return removeCallback()
|
||||
if(!isHarmful)return removeCallback(hash)
|
||||
cache[hash] = {
|
||||
suspect: true,
|
||||
name: hashToUrl[hash].split("/").pop(),
|
||||
type: hashToUrl[hash].endsWith(".js") ? "Plugin" : "Theme",
|
||||
harm: isHarmful
|
||||
harm: isHarmful,
|
||||
hash: hash,
|
||||
filename
|
||||
}
|
||||
|
||||
console.log(`Found potentially dangerous ${cache[hash].type.toLowerCase()}: ${cache[hash].name}`)
|
||||
|
@ -102,11 +108,13 @@ export function checkHash(hash, data, filename, resultCallback, removeCallback){
|
|||
}
|
||||
}).then(async res => {
|
||||
if(res.status !== 200){
|
||||
if(filename.endsWith(".theme.css"))return removeCallback()
|
||||
checkViruses(hash, data, resultCallback, removeCallback)
|
||||
if(filename.endsWith(".theme.css"))return removeCallback(hash)
|
||||
checkViruses(hash, data, resultCallback, removeCallback, filename)
|
||||
return
|
||||
}
|
||||
const result = await res.json()
|
||||
result.hash = hash
|
||||
result.filename = filename
|
||||
|
||||
cache[hash] = result
|
||||
|
||||
|
@ -119,7 +127,7 @@ export function checkHash(hash, data, filename, resultCallback, removeCallback){
|
|||
}
|
||||
}
|
||||
|
||||
export function processFile(__path, resultCallback, removeCallback = () => {}){
|
||||
export function processFile(__path, resultCallback, removeCallback = (hash) => {}, isFromLoader = false){
|
||||
const hash = crypto.createHash("sha256")
|
||||
let data = Buffer.alloc(0)
|
||||
|
||||
|
@ -131,7 +139,16 @@ export function processFile(__path, resultCallback, removeCallback = () => {}){
|
|||
|
||||
hashToUrl[hashResult] = __path
|
||||
|
||||
console.log(arguments)
|
||||
if(isFromLoader && addonCache[hashResult]){
|
||||
let value = addonCache[hashResult]
|
||||
if(value.timestamp < (Date.now() - 6.048e+8)){
|
||||
delete addonCache[hashResult]
|
||||
contentManager.saveAddonCache()
|
||||
}else{
|
||||
resultCallback(value.result)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
checkHash(hashResult, data, basename(__path), resultCallback, removeCallback)
|
||||
})
|
||||
|
@ -185,7 +202,6 @@ function renderToElements(id, result, filename){
|
|||
if(!flowerStarModule)flowerStarModule = BDModules.get(e => e.flowerStarContainer)[0]
|
||||
if(!childModule)childModule = BDModules.get(e => e.childContainer)[0]
|
||||
|
||||
console.log(result)
|
||||
if(result.suspect){
|
||||
try{
|
||||
div.parentNode.style.borderColor = "rgb(240, 71, 71)"
|
||||
|
@ -224,8 +240,8 @@ function renderToElements(id, result, filename){
|
|||
console.error(e)
|
||||
}
|
||||
BDV2.reactDom.render(BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" is potentially dangerous."},
|
||||
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "16px", height: "16px"}},
|
||||
BDV2.react.createElement("svg", {className: BDModules.get(e => e.svg)[0].svg, "aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 40 32"},
|
||||
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "20px", height: "20px"}},
|
||||
BDV2.react.createElement("svg", {className: BDModules.get(e => e.svg)[0].svg, "aria-hidden":"false",width:"20px",height:"20px",viewBox:"0 0 40 32"},
|
||||
BDV2.react.createElement("rect", {
|
||||
x:"0",
|
||||
y:"0",
|
||||
|
@ -241,31 +257,186 @@ function renderToElements(id, result, filename){
|
|||
), div)
|
||||
}else if(!result.official){
|
||||
div.parentNode.style.borderColor = "#4087ed"
|
||||
BDV2.reactDom.render(BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" is certified by Lightcord."},
|
||||
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "16px", height: "16px"}},
|
||||
BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 16 15.2"},
|
||||
let span = BDV2.react.createElement("span", {style: {display: "inherit"}}, [
|
||||
BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" is certified by Lightcord."},
|
||||
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "20px", height: "20px", float: "left"}},
|
||||
BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"20px",height:"20px",viewBox:"0 0 16 15.2"},
|
||||
BDV2.react.createElement("path", {fill:"#4f545c", "fill-rule":"evenodd",d:"m16 7.6c0 .79-1.28 1.38-1.52 2.09s.44 2 0 2.59-1.84.35-2.46.8-.79 1.84-1.54 2.09-1.67-.8-2.47-.8-1.75 1-2.47.8-.92-1.64-1.54-2.09-2-.18-2.46-.8.23-1.84 0-2.59-1.54-1.3-1.54-2.09 1.28-1.38 1.52-2.09-.44-2 0-2.59 1.85-.35 2.48-.8.78-1.84 1.53-2.12 1.67.83 2.47.83 1.75-1 2.47-.8.91 1.64 1.53 2.09 2 .18 2.46.8-.23 1.84 0 2.59 1.54 1.3 1.54 2.09z"})
|
||||
),
|
||||
BDV2.react.createElement("div", {className: childModule.childContainer},
|
||||
BDV2.react.createElement("svg", {"aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 16 15.2"},
|
||||
BDV2.react.createElement("svg", {"aria-hidden":"false",width:"20px",height:"20px",viewBox:"0 0 16 15.2"},
|
||||
BDV2.react.createElement("path", {fill:"#ffffff",d:"M7.4,11.17,4,8.62,5,7.26l2,1.53L10.64,4l1.36,1Z"})
|
||||
)
|
||||
)
|
||||
)
|
||||
), div)
|
||||
),
|
||||
BDV2.react.createElement(tooltipWrap, {text: "Install this "+result.type.toLowerCase()+" on Lightcord."},
|
||||
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "20px", height: "20px"}, onClick(){
|
||||
Utils.showConfirmationModal(
|
||||
"Are you sure you want to download this "+result.type.toLowerCase()+" ?",
|
||||
"Lightcord will automatically install and launch this "+result.type.toLowerCase()+". You don't have anything to do.",
|
||||
{
|
||||
confirmText: "Download and Install",
|
||||
cancelText: "I've changed my mind",
|
||||
danger: false,
|
||||
onCancel: () => {},
|
||||
onConfirm: () => {
|
||||
let link = getKeyedArray(cache2).find(e => e[1] === result.hash)[0]
|
||||
console.log(link)
|
||||
nodeFetch(link)
|
||||
.then(async res => {
|
||||
if(res.status !== 200)throw new Error("Status was not 200")
|
||||
let content = await res.buffer()
|
||||
let installPath = join(result.type === "Plugin" ? contentManager._pluginsFolder : contentManager._themesFolder, result.filename)
|
||||
console.log(installPath)
|
||||
writeFileSync(installPath, content)
|
||||
Utils.showToast(result.type+" succesfully installed.")
|
||||
}).catch(err => {
|
||||
err = err instanceof Error ? err : new Error(err)
|
||||
Utils.showToast(err.message, {
|
||||
type: "error"
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
}},
|
||||
BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"20px",height:"20px",viewBox:"0 0 24 24",style:{
|
||||
color: "rgb(67, 181, 129)",
|
||||
cursor: "pointer"
|
||||
}},
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path d="M0 0h24v24H0z"></path>
|
||||
<path class="fill" fill="currentColor" d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path>
|
||||
</g>
|
||||
)
|
||||
)
|
||||
)
|
||||
])
|
||||
BDV2.reactDom.render(span, div)
|
||||
}else{
|
||||
div.parentNode.style.borderColor = "#4087ed"
|
||||
BDV2.reactDom.render(BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" was made by the developers of Lightcord.",style:"brand"},
|
||||
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "16px", height: "16px"}},
|
||||
BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 16 15.2",stroke:"#36393f",style:{color:"#4087ed"}},
|
||||
let span = BDV2.react.createElement("span", {style: {display: "inherit"}}, [
|
||||
BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" was made by the developers of Lightcord.", style:"brand"},
|
||||
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "20px", height: "20px", float: "left"}},
|
||||
BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"20px",height:"20px",viewBox:"0 0 16 15.2",stroke:"#36393f",style:{color:"#4087ed"}},
|
||||
BDV2.react.createElement("path", {fill:"currentColor", "fill-rule":"evenodd",d:"m16 7.6c0 .79-1.28 1.38-1.52 2.09s.44 2 0 2.59-1.84.35-2.46.8-.79 1.84-1.54 2.09-1.67-.8-2.47-.8-1.75 1-2.47.8-.92-1.64-1.54-2.09-2-.18-2.46-.8.23-1.84 0-2.59-1.54-1.3-1.54-2.09 1.28-1.38 1.52-2.09-.44-2 0-2.59 1.85-.35 2.48-.8.78-1.84 1.53-2.12 1.67.83 2.47.83 1.75-1 2.47-.8.91 1.64 1.53 2.09 2 .18 2.46.8-.23 1.84 0 2.59 1.54 1.3 1.54 2.09z"})
|
||||
),
|
||||
BDV2.react.createElement("div", {className: childModule.childContainer},
|
||||
BDV2.react.createElement("svg", {"aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 16 15.2"},
|
||||
BDV2.react.createElement("svg", {"aria-hidden":"false",width:"20px",height:"20px",viewBox:"0 0 16 15.2"},
|
||||
BDV2.react.createElement("path", {fill:"#ffffff",d:"M10.7,5.28a2.9,2.9,0,0,0-2.11.86.11.11,0,0,0,0,.16l1.05.94a.11.11,0,0,0,.15,0,1.27,1.27,0,0,1,.9-.33c.65,0,.65.73.65.73a.64.64,0,0,1-.65.65,1.73,1.73,0,0,1-1.18-.54c-.31-.26-.36-.32-.73-.66S7.06,5.28,5.65,5.28A2.26,2.26,0,0,0,3.37,7.56,2.59,2.59,0,0,0,3.82,9a2.18,2.18,0,0,0,1.83.89,2.94,2.94,0,0,0,2.1-.81.11.11,0,0,0,0-.16L6.74,8A.11.11,0,0,0,6.6,8a1.58,1.58,0,0,1-.94.29h0A.71.71,0,0,1,5,7.56H5a.63.63,0,0,1,.65-.64c.71,0,1.42.75,1.94,1.27.75.76,1.66,1.79,3.11,1.74A2.28,2.28,0,0,0,13,7.64a2.59,2.59,0,0,0-.45-1.47A2.14,2.14,0,0,0,10.7,5.28Z"})
|
||||
)
|
||||
)
|
||||
)
|
||||
), div)
|
||||
),
|
||||
BDV2.react.createElement(tooltipWrap, {text: "Install this "+result.type.toLowerCase()+" on Lightcord."},
|
||||
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "20px", height: "20px"}, onClick(){
|
||||
Utils.showConfirmationModal(
|
||||
"Are you sure you want to download this "+result.type.toLowerCase()+" ?",
|
||||
"Lightcord will automatically download and load this "+result.type.toLowerCase()+". You must enable it in the settings.",
|
||||
{
|
||||
confirmText: "Download and Install",
|
||||
cancelText: "I've changed my mind",
|
||||
danger: false,
|
||||
onCancel: () => {},
|
||||
onConfirm: () => {
|
||||
let link = getKeyedArray(cache2).find(e => e[1] === result.hash)[0]
|
||||
|
||||
nodeFetch(link)
|
||||
.then(async res => {
|
||||
if(res.status !== 200)throw new Error("Status was not 200")
|
||||
let content = await res.buffer()
|
||||
let installPath = join(result.type === "Plugin" ? contentManager._pluginsFolder : contentManager._themesFolder, result.filename)
|
||||
|
||||
writeFileSync(installPath, content)
|
||||
Utils.showToast(result.type+" succesfully installed.")
|
||||
}).catch(err => {
|
||||
err = err instanceof Error ? err : new Error(err)
|
||||
Utils.showToast(err.message, {
|
||||
type: "error"
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
}},
|
||||
BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"20px",height:"20px",viewBox:"0 0 24 24",style:{
|
||||
color: "rgb(67, 181, 129)",
|
||||
cursor: "pointer"
|
||||
}},
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path d="M0 0h24v24H0z"></path>
|
||||
<path class="fill" fill="currentColor" d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path>
|
||||
</g>
|
||||
)
|
||||
)
|
||||
)
|
||||
])
|
||||
BDV2.reactDom.render(span, div)
|
||||
}
|
||||
}
|
||||
|
||||
function getKeyedArray(obj){
|
||||
let arr = []
|
||||
Object.keys(obj).forEach(k => {
|
||||
arr.push([k, obj[k]])
|
||||
})
|
||||
return arr
|
||||
}
|
||||
|
||||
let key = null
|
||||
let save = null
|
||||
|
||||
window.Lightcord.Api.ensureExported(m=>m.ObjectStorage)
|
||||
.then(localStorageModule => {
|
||||
let localStorage = localStorageModule.impl
|
||||
save = function(){
|
||||
localStorage.set("PluginCertifierKeyEncryption__", btoa(JSON.stringify(key)))
|
||||
}
|
||||
setInterval(() => {
|
||||
save()
|
||||
}, 100000);
|
||||
try{
|
||||
let val = safeJSONParse(atob(localStorage.get("PluginCertifierKeyEncryption__")))
|
||||
if(val instanceof Error || !Array.isArray(val) || val.length !== 2 || val.find(e => typeof e !== "string") || Buffer.from(val[0], "base64").length !== 16 || Buffer.from(val[1], "base64").length !== 32){
|
||||
generateKey()
|
||||
save()
|
||||
return
|
||||
}
|
||||
key = val
|
||||
}catch(e){
|
||||
generateKey()
|
||||
save()
|
||||
}
|
||||
})
|
||||
|
||||
function generateKey(){
|
||||
key = [crypto.randomBytes(16).toString("base64"), crypto.randomBytes(32).toString("base64")]
|
||||
}
|
||||
|
||||
function safeJSONParse(json){
|
||||
try{
|
||||
return JSON.parse(json)
|
||||
}catch(e){
|
||||
return e instanceof Error ? new Error(e) : e
|
||||
}
|
||||
}
|
||||
|
||||
export function decryptSettingsCache(data){
|
||||
try{
|
||||
let decipher = crypto.createDecipheriv("aes-256-cbc", Buffer.from(key[1], "base64"), Buffer.from(key[0], "base64"))
|
||||
let decrypted = decipher.update(Buffer.from(data, "base64"));
|
||||
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
||||
return decrypted.toString("utf8")
|
||||
}catch(e){
|
||||
return "{}"
|
||||
}
|
||||
}
|
||||
export function encryptSettingsCache(data){
|
||||
let args = [Buffer.from(key[1], "base64"), Buffer.from(key[0], "base64")]
|
||||
|
||||
let cipher = crypto.createCipheriv('aes-256-cbc', ...args);
|
||||
let encrypted = cipher.update(Buffer.from(data, "utf8"));
|
||||
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
||||
return encrypted.toString("base64")
|
||||
}
|
|
@ -5,6 +5,9 @@ import BDEvents from "./bdEvents";
|
|||
import Utils from "./utils";
|
||||
|
||||
class PluginModule {
|
||||
constructor(){
|
||||
window.Lightcord.BetterDiscord.PluginModule = this
|
||||
}
|
||||
get folder() {return ContentManager.pluginsFolder;}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ export default new class V2_PublicServers {
|
|||
|
||||
constructor() {
|
||||
this._appendButton = this._appendButton.bind(this);
|
||||
window.Lightcord.BetterDiscord.V2_PublicServers = this
|
||||
}
|
||||
|
||||
get component() {
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import {settings, settingsCookie, bdplugins, bdthemes, settingsRPC} from "../0globals";
|
||||
import {settings, settingsCookie, settingsRPC} from "../0globals";
|
||||
import DataStore from "./dataStore";
|
||||
import V2_SettingsPanel_Sidebar from "./settingsPanelSidebar";
|
||||
import Utils from "./utils";
|
||||
import BDV2 from "./v2";
|
||||
import ContentManager from "./contentManager";
|
||||
import BDEvents from "./bdEvents";
|
||||
import coloredText from "./coloredText";
|
||||
import tfHour from "./24hour";
|
||||
import reactDevTools from "./reactDevTools";
|
||||
import DOM from "./domtools";
|
||||
|
||||
import publicServersModule from "./publicServers";
|
||||
|
@ -15,10 +13,7 @@ import voiceMode from "./voiceMode";
|
|||
import ClassNormalizer from "./classNormalizer";
|
||||
import dMode from "./devMode";
|
||||
|
||||
import Tools from "../ui/tools";
|
||||
import Scroller from "../ui/scroller";
|
||||
import SectionedSettingsPanel from "../ui/sectionedSettingsPanel";
|
||||
import SettingsPanel from "../ui/settingsPanel";
|
||||
import CssEditor from "../ui/cssEditor";
|
||||
import CardList from "../ui/addonlist";
|
||||
import V2C_PresenceSettings from "../ui/presenceSettings";
|
||||
|
@ -29,9 +24,28 @@ import AntiAdDM from "./AntiAdDM";
|
|||
import blurPrivate from "./blurPrivate";
|
||||
import disableTyping from "./disableTyping";
|
||||
import ApiPreview from "../ui/ApiPreview";
|
||||
import V2C_SettingsTitle from "../ui/settingsTitle";
|
||||
import Switch from "../ui/switch";
|
||||
import MarginTop from "../ui/margintop";
|
||||
import webpackModules from "./webpackModules";
|
||||
import tooltipWrap from "../ui/tooltipWrap";
|
||||
import History from "../ui/icons/history";
|
||||
|
||||
class BDSidebarHeader extends React.PureComponent {
|
||||
render(){
|
||||
let sidebarComponents = webpackModules.find(e => e.Separator && e.Header && e.Item)
|
||||
|
||||
const changelogButton = React.createElement(tooltipWrap, {color: "black", side: "top", text: "Changelog"},
|
||||
React.createElement("span", {style: {float: "right", cursor: "pointer"}, className: "bd-changelog-button", onClick: () => {Utils.showChangelogModal(bbdChangelog);}},
|
||||
React.createElement(History, {className: "bd-icon", size: "16px"})
|
||||
)
|
||||
);
|
||||
let rendered = new sidebarComponents.Header({
|
||||
children: React.createElement("span", null, "Bandaged BD", changelogButton),
|
||||
className: "ui-tab-bar-header"
|
||||
})
|
||||
return rendered
|
||||
}
|
||||
}
|
||||
|
||||
export default new class V2_SettingsPanel {
|
||||
|
||||
|
@ -51,6 +65,9 @@ export default new class V2_SettingsPanel {
|
|||
this.sidebar.register("lcapipreview", makeComponent(this.ApiPreviewComponent.bind(this)))
|
||||
|
||||
/* Bandaged BD */
|
||||
this.sidebar.register("BDChangelogTitle", makeComponent(() => {
|
||||
return new BDSidebarHeader().render()
|
||||
}))
|
||||
this.sidebar.register("core", makeComponent(this.coreComponent.bind(this)))
|
||||
this.sidebar.register("customcss", makeComponent(this.customCssComponent.bind(this)))
|
||||
this.sidebar.register("plugins", makeComponent(this.renderAddonPane("plugins")))
|
||||
|
@ -192,10 +209,10 @@ export default new class V2_SettingsPanel {
|
|||
else dMode.stopCopySelector();
|
||||
}
|
||||
|
||||
if (id === "reactDevTools") {
|
||||
/*if (id === "reactDevTools") {
|
||||
if (enabled) reactDevTools.start();
|
||||
else reactDevTools.stop();
|
||||
}
|
||||
}*/
|
||||
if (id === "lightcord-1") {
|
||||
if (enabled) window.Lightcord.Settings.devMode = true
|
||||
else window.Lightcord.Settings.devMode = false
|
||||
|
@ -246,7 +263,7 @@ export default new class V2_SettingsPanel {
|
|||
}
|
||||
|
||||
async initializeSettings() {
|
||||
if (settingsCookie.reactDevTools) reactDevTools.start();
|
||||
//if (settingsCookie.reactDevTools) reactDevTools.start();
|
||||
if (settingsCookie["bda-gs-2"]) DOM.addClass(document.body, "bd-minimal");
|
||||
if (settingsCookie["bda-gs-3"]) DOM.addClass(document.body, "bd-minimal-chan");
|
||||
if (settingsCookie["bda-gs-1"]) publicServersModule.addButton();
|
||||
|
@ -305,13 +322,20 @@ export default new class V2_SettingsPanel {
|
|||
})
|
||||
]
|
||||
}),
|
||||
BDV2.react.createElement(window.Lightcord.Api.Components.inputs.Button, {color: "yellow", onClick(){
|
||||
BDV2.react.createElement(window.Lightcord.Api.Components.inputs.Button, {
|
||||
color: "yellow",
|
||||
look: "ghost",
|
||||
size: "medium",
|
||||
hoverColor: "red",
|
||||
onClick(){
|
||||
console.log("Should relaunch")
|
||||
remote.app.relaunch({
|
||||
args: remote.process.argv.slice(1).concat(["--disable-betterdiscord"])
|
||||
})
|
||||
remote.app.quit()
|
||||
}}, "Relaunch without BetterDiscord")
|
||||
},
|
||||
wrapper: true
|
||||
}, "Relaunch without BetterDiscord")
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -369,6 +393,10 @@ export default new class V2_SettingsPanel {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* No need to export settingsPanel on window
|
||||
*/
|
||||
|
||||
function makeComponent(children){
|
||||
class SettingComponent extends React.Component {
|
||||
render(){
|
||||
|
|
|
@ -1,12 +1,3 @@
|
|||
import {bbdChangelog, LCChanelog} from "../0globals";
|
||||
import Utils from "./utils";
|
||||
import BDV2 from "./v2";
|
||||
import DOM from "./domtools";
|
||||
|
||||
import SideBar from "../ui/sidebar";
|
||||
import History from "../ui/icons/history";
|
||||
import TooltipWrap from "../ui/tooltipWrap";
|
||||
|
||||
export default class V2_SettingsPanel_Sidebar {
|
||||
|
||||
constructor() {
|
||||
|
@ -50,7 +41,7 @@ export default class V2_SettingsPanel_Sidebar {
|
|||
id: "accountinfo"
|
||||
}
|
||||
]
|
||||
if(!!window.Lightcord.Settings.devMode)items.push({
|
||||
if(window.Lightcord.Settings.devMode)items.push({
|
||||
text: "Api Components Preview",
|
||||
id: "lcapipreview"
|
||||
})
|
||||
|
@ -74,8 +65,8 @@ export default class V2_SettingsPanel_Sidebar {
|
|||
section: "DIVIDER"
|
||||
},
|
||||
{
|
||||
section: "HEADER",
|
||||
label: "Bandaged BD"
|
||||
section: "CUSTOM",
|
||||
element: this.getComponent("BDChangelogTitle")
|
||||
},
|
||||
...this.items.map(e => {
|
||||
return {
|
||||
|
@ -90,3 +81,7 @@ export default class V2_SettingsPanel_Sidebar {
|
|||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* No need to export settingsPanelSidebar on window
|
||||
*/
|
|
@ -6,6 +6,9 @@ import Utils from "./utils";
|
|||
import DOM from "./domtools";
|
||||
|
||||
class ThemeModule {
|
||||
constructor(){
|
||||
window.Lightcord.BetterDiscord.ThemeModule = this
|
||||
}
|
||||
get folder() {return ContentManager.themesFolder;}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ export default new class V2 {
|
|||
reactDom: this.WebpackModules.findByUniqueProperties(["findDOMNode"])
|
||||
};
|
||||
this.getInternalInstance = e => e[Object.keys(e).find(k => k.startsWith("__reactInternalInstance"))];
|
||||
window.Lightcord.BetterDiscord.V2 = this
|
||||
}
|
||||
|
||||
initialize() {
|
||||
|
|
|
@ -29,4 +29,7 @@ const findByProps = (...propNames) => find(module => propNames.every(prop => mod
|
|||
const findByPrototypes = (...protoNames) => find(module => module.prototype && protoNames.every(protoProp => module.prototype[protoProp] !== undefined));
|
||||
const findByDisplayName = (displayName) => find(module => module.displayName === displayName);
|
||||
|
||||
export default {find, findAll, findByProps, findByPrototypes, findByDisplayName};
|
||||
let mod = {find, findAll, findByProps, findByPrototypes, findByDisplayName};
|
||||
export default mod
|
||||
|
||||
window.Lightcord.BetterDiscord.WebpackModules = mod
|
|
@ -33,7 +33,7 @@ export default class ApiPreview extends React.PureComponent {
|
|||
</formModule.FormText>
|
||||
<MarginTop></MarginTop>
|
||||
<Lightcord.Api.Components.inputs.Button color="brand" look="outlined" size="medium" hoverColor="green" onClick={() => {
|
||||
remote.shell.openExternal("https://github.com/lightcord/lightcord/wiki/apis")
|
||||
remote.shell.openExternal("https://github.com/lightcord/lightcord/wiki/Apis")
|
||||
}} wrapper={false}>
|
||||
Documentation
|
||||
</Lightcord.Api.Components.inputs.Button>
|
||||
|
@ -71,7 +71,7 @@ export default class ApiPreview extends React.PureComponent {
|
|||
return final
|
||||
}
|
||||
let renderPreview = () => {
|
||||
return <div style={{marginTop: "20px", marginBottom: "20px"}}>
|
||||
return <div style={{margin: "20px"}}>
|
||||
<div style={{
|
||||
backgroundColor: "var(--background-primary)",
|
||||
padding: "30px 30px",
|
||||
|
@ -82,7 +82,7 @@ export default class ApiPreview extends React.PureComponent {
|
|||
</div>
|
||||
}
|
||||
let renderCode = () => {
|
||||
return <div style={{marginTop: "20px", marginBottom: "20px"}}>
|
||||
return <div style={{margin: "20px"}}>
|
||||
<div style={{
|
||||
backgroundColor: "var(--background-primary)",
|
||||
padding: "30px 30px",
|
||||
|
@ -100,7 +100,7 @@ export default class ApiPreview extends React.PureComponent {
|
|||
</div>
|
||||
</div>
|
||||
}
|
||||
let getStrForProp = (value) => {
|
||||
let getStrForProp = (value, compPath, lang) => {
|
||||
if(typeof value === "string"){
|
||||
return value
|
||||
}else if(typeof value === "boolean"){
|
||||
|
@ -109,6 +109,33 @@ export default class ApiPreview extends React.PureComponent {
|
|||
return value.toString()
|
||||
}else if(typeof value === "object"){
|
||||
if(value && value.$$typeof && (value.$$typeof === Symbol.for("react.element") || value.$$typeof === 0xeac7)){
|
||||
if(compPath === "Lightcord.Api.Components.general.Tabs"){
|
||||
if(lang === "react"){
|
||||
return `React.createElement("div", {style: {
|
||||
marginTop: "20px", marginBottom: "20px"
|
||||
}},
|
||||
React.createElement("div", {style: {
|
||||
backgroundColor: "var(--background-primary)",
|
||||
padding: "30px 30px",
|
||||
borderRadius: "8px"
|
||||
}, className: "lc-tab-box-shadow" },
|
||||
React.createElement(Lightcord.Api.Components.general.Title, null, "Preview tabs")
|
||||
)
|
||||
)`
|
||||
}else if(lang === "jsx"){
|
||||
return `<div style={{
|
||||
marginTop: "20px", marginBottom: "20px"
|
||||
}}>
|
||||
<div style={{
|
||||
backgroundColor: "var(--background-primary)",
|
||||
padding: "30px 30px",
|
||||
borderRadius: "8px"
|
||||
}} className="lc-tab-box-shadow">
|
||||
<Lightcord.Api.Components.general.Title>Preview tabs</Lightcord.Api.Components.general.Title>
|
||||
</div>
|
||||
</div>`
|
||||
}
|
||||
}
|
||||
return "Your components here."
|
||||
}
|
||||
return JSON.stringify(value, null, " ")
|
||||
|
@ -129,13 +156,13 @@ export default class ApiPreview extends React.PureComponent {
|
|||
let childrenProp = null
|
||||
Object.keys(props).forEach(key => {
|
||||
if(key == "children"){
|
||||
childrenProp = getStrForProp(props[key])
|
||||
childrenProp = getStrForProp(props[key], compPath, lang)
|
||||
}else{
|
||||
let str = key+"="
|
||||
if(typeof props[key] === "string"){
|
||||
str += JSON.stringify(props[key])
|
||||
}else{
|
||||
str += `{${getStrForProp(props[key])}}`
|
||||
str += `{${getStrForProp(props[key], compPath, lang)}}`
|
||||
}
|
||||
propStrings.push(str)
|
||||
}
|
||||
|
@ -153,7 +180,7 @@ export default class ApiPreview extends React.PureComponent {
|
|||
let children = props.children || null
|
||||
delete props.children
|
||||
if(children && children.$$typeof && (children.$$typeof === Symbol.for("react.element") || children.$$typeof === 0xeac7)){
|
||||
children = "Your components here."
|
||||
children = getStrForProp(children, compPath, lang)
|
||||
}
|
||||
let propStrings = []
|
||||
Object.keys(props).forEach(key => {
|
||||
|
@ -162,7 +189,7 @@ export default class ApiPreview extends React.PureComponent {
|
|||
if(typeof props[key] === "string"){
|
||||
str += JSON.stringify(props[key])
|
||||
}else{
|
||||
str += getStrForProp(props[key]).split("\n").map((str, i) => {
|
||||
str += getStrForProp(props[key], compPath, lang).split("\n").map((str, i) => {
|
||||
if(i === 0)return str
|
||||
return " " + str
|
||||
}).join("\n")
|
||||
|
@ -186,7 +213,8 @@ export default class ApiPreview extends React.PureComponent {
|
|||
}else{
|
||||
propObject += "}"
|
||||
}
|
||||
return `React.createElement(${compPath}, ${propObject}, ${JSON.stringify(children)})`
|
||||
let childrenData = typeof children === "string" && children.startsWith("React.createElement") ? children : JSON.stringify(children)
|
||||
return `React.createElement(${compPath}, ${propObject}, ${childrenData})`
|
||||
}
|
||||
}
|
||||
return (<div>
|
||||
|
|
|
@ -191,19 +191,26 @@ export default class V2C_PluginCard extends BDV2.reactComponent {
|
|||
const {authorId, authorLink} = this.props.addon;
|
||||
|
||||
const style = {}
|
||||
if(settingsCookie["fork-ps-6"]){
|
||||
if(!this.isScanning){
|
||||
this.isScanning = true
|
||||
processFile(resolve(this.props.addon.filename.endsWith(".plugin.js") ? contentManager.pluginsFolder : contentManager.themesFolder, this.props.addon.filename), (result) => {
|
||||
if(this.unmounted)return
|
||||
|
||||
this.setState({
|
||||
isTrusted: !result.suspect
|
||||
isTrusted: result.suspect ? "suspect" : true
|
||||
})
|
||||
}, () => {})
|
||||
}else{
|
||||
if(this.state.isTrusted){
|
||||
if(this.state.isTrusted === true){
|
||||
style.borderColor = "#4087ed"
|
||||
}
|
||||
if(this.state.isTrusted === "suspect"){
|
||||
style.borderColor = "rgb(240, 71, 71)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BDV2.react.createElement("div", {className: "bd-card bd-addon-card settings-closed ui-switch-item", style},
|
||||
BDV2.react.createElement("div", {className: "bd-addon-header bda-header"},
|
||||
BDV2.react.createElement("div", {className: "bd-card-title bda-header-title"}, this.buildTitle(this.name, this.version, {name: this.author, id: authorId, link: authorLink})),
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
/**
|
||||
* How the fuck did I do this
|
||||
*/
|
||||
|
||||
import BDV2 from "../modules/v2";
|
||||
import V2C_SettingsTitle from "./settingsTitle";
|
||||
import V2C_SettingsGroup from "./settingsGroup";
|
||||
|
@ -556,7 +552,7 @@ class Tab extends React.Component {
|
|||
}
|
||||
|
||||
let popoutModule
|
||||
class Popout extends React.Component {
|
||||
class Popout extends React.Component { // TODO: Probably use internal Components instead of making it from scratch.
|
||||
get modules(){
|
||||
return popoutModule || (popoutModule = [
|
||||
BDModules.get(e => e.userPopout)[0],
|
||||
|
@ -722,7 +718,7 @@ class Status extends React.Component {
|
|||
let timestampClass = ""
|
||||
|
||||
let ProfileModules
|
||||
class Profile extends React.Component {
|
||||
class Profile extends React.Component { // TODO: Probably use internal Components instead of making it from scratch.
|
||||
get modules(){
|
||||
return ProfileModules || (ProfileModules = [
|
||||
BDModules.get(e => e.flex && e._horizontal)[0],
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
# Lightcord's Discord.js
|
||||
|
||||
Disclaimer:
|
||||
This part of Lightcord is still in development. Features could be added/change/removed.
|
||||
|
||||
### What is this ?
|
||||
Lightcord includes a Discord.js-like api. This is written in this folder.
|
||||
|
||||
<warn>This is not for making selfbots.
|
||||
The purpose of this is only to make an easy, intuitive and object oriented api.</warn>
|
||||
|
||||
### Where can I get the documentation ?
|
||||
[Documentation here](https://discord.js.org/#/docs/main/11.6.4/general/welcome)
|
||||
Discord.js on Lightcord is following Discord.js 11.6.4 specs.
|
||||
Discord.js on Lightcord is based on Discord.js 11.6.4.
|
||||
|
||||
### How do I use it ?
|
||||
Discord.js can be accessed under the following global properties
|
||||
|
@ -18,4 +24,10 @@ Discord.js can be accessed under the following global properties
|
|||
|
||||
### Deprecations
|
||||
1. Any method that only bot can use (it will throw a `DiscordJSError` saying that Lightcord can't do that)
|
||||
3. Any method
|
||||
2. Original Voice Methods. They're documented below:
|
||||
3. Try to not use deprecated methods flagged on DiscordJS's website. They might be removed on Lightcord.
|
||||
|
||||
### Voice
|
||||
Lightcord can't make the client join multiple voice channels / join but the user doesn't know.
|
||||
|
||||
When joining a voice channel, The user's mic is sent. This is not for broadcasting/playing music in voice, but only to make the user join a voice channel.
|
|
@ -78,10 +78,10 @@ export default class Client extends EventEmitter {
|
|||
|
||||
/** Warnings and overrides for functions that are not compatible. */
|
||||
async login():Promise<never>{
|
||||
throw new DiscordJSError("Client#login is not supported. DiscordJS on lightcord will use the connected account.")
|
||||
throw new DiscordJSError("Client#login is not supported. DiscordJS on lightcord will use the logged in account.")
|
||||
}
|
||||
|
||||
get token():never{
|
||||
throw new DiscordJSError("Client#token is not supported. DiscordJS on lightcord will use the connected account.")
|
||||
throw new DiscordJSError("Client#token is not supported. DiscordJS on lightcord will use the logged in account.")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import GuildChannel from "./GuildChannel";
|
||||
import { DiscordChannel } from "../util/DiscordToModules";
|
||||
import { ChannelTypes } from "../util/Constants";
|
||||
|
||||
export default class CategoryChannel extends GuildChannel/* implements TextBasedChannel*/ {
|
||||
constructor(data:DiscordChannel){
|
||||
super(data)
|
||||
}
|
||||
|
||||
get type(): ChannelTypes.CATEGORY{
|
||||
return ChannelTypes.CATEGORY
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { Snowflake, Channel } from ".."
|
||||
import { DiscordGuild, channelsModule, guildModule, UserSettingsModule, ConstantsModule, CdnModule, AckModule } from "../util/DiscordToModules"
|
||||
import BaseStructure from "./BaseStructure"
|
||||
import { createChannel, createGuildMember, createRole, UserResolvable, resolveUserID } from "../util/util"
|
||||
import { createChannel, createGuildMember, createRole, UserResolvable, resolveUserID, ChannelData, ChannelCreationOverwrites, PermissionOverwrites } from "../util/util"
|
||||
import Collection from "@discordjs/collection"
|
||||
import SnowflakeUtil from "../util/Snowflake"
|
||||
import GuildMember from "./GuildMember"
|
||||
|
@ -271,16 +271,38 @@ export default class Guild extends BaseStructure {
|
|||
}).then(() => this)
|
||||
}
|
||||
|
||||
ban(user:UserResolvable, {
|
||||
async ban(user:UserResolvable, {
|
||||
days = 0,
|
||||
reason = null
|
||||
}: {
|
||||
days?: number,
|
||||
reason?: string
|
||||
}){
|
||||
} = {}):Promise<Snowflake>{ // always returning a snowflake
|
||||
let id = resolveUserID(user)
|
||||
if(!id)return Promise.reject(new DiscordJSError("Given user could not be resolved to an user ID."))
|
||||
|
||||
let result = await guildModule.banUser(this.id, id, days, reason).catch(err => err)
|
||||
if(result instanceof Error || result.status !== 204){
|
||||
let message = result.body
|
||||
if(Array.isArray(message)){
|
||||
message = message[0]
|
||||
}else{
|
||||
if(message.user_id){
|
||||
message = "User: "+ message.user_id[0]
|
||||
}else if(message.delete_message_days){
|
||||
message = "Days: "+ message.delete_message_days[0]
|
||||
}else if(message.reason){
|
||||
message = "Reason: "+ message.reason[0]
|
||||
}else{
|
||||
message = result.text
|
||||
}
|
||||
}
|
||||
throw new DiscordJSError(message)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
createChannel(name:string, typeOrOptions:string|ChannelData = 'text', permissionOverwrites?: ChannelCreationOverwrites[] | Collection<Snowflake, PermissionOverwrites>, reason?: string){
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import GuildChannel from "./GuildChannel";
|
|||
import { DiscordChannel } from "../util/DiscordToModules";
|
||||
import { ChannelTypes } from "../util/Constants";
|
||||
|
||||
export class TextChannel extends GuildChannel/* implements TextBasedChannel*/ {
|
||||
export default class TextChannel extends GuildChannel/* implements TextBasedChannel*/ {
|
||||
constructor(data:DiscordChannel){
|
||||
super(data)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/**
|
||||
* Data structure that makes it easy to interact with a bitfield.
|
||||
*/
|
||||
export default class BitField {
|
||||
/**
|
||||
* @param {BitFieldResolvable} [bits=0] Bits(s) to read from
|
||||
*/
|
||||
constructor(bits: BitFieldResolvable) {
|
||||
this.bitfield = (this.constructor as any).resolve(bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitfield of the packed bits
|
||||
* @type {number}
|
||||
*/
|
||||
bitfield:number
|
||||
|
||||
/**
|
||||
* Checks whether the bitfield has a bit, or any of multiple bits.
|
||||
* @param {BitFieldResolvable} bit Bit(s) to check for
|
||||
* @returns {boolean}
|
||||
*/
|
||||
any(bit: BitFieldResolvable): boolean {
|
||||
return (this.bitfield & (this.constructor as any).resolve(bit)) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this bitfield equals another
|
||||
* @param {BitFieldResolvable} bit Bit(s) to check for
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(bit: BitFieldResolvable): boolean {
|
||||
return this.bitfield === (this.constructor as any).resolve(bit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the bitfield has a bit, or multiple bits.
|
||||
* @param {BitFieldResolvable} bit Bit(s) to check for
|
||||
* @returns {boolean}
|
||||
*/
|
||||
has(bit: BitFieldResolvable, ...hasParams: any[]): boolean {
|
||||
if (Array.isArray(bit)) return bit.every((p) => this.has(p));
|
||||
bit = (this.constructor as any).resolve(bit) as number;
|
||||
return (this.bitfield & bit) === bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all given bits that are missing from the bitfield.
|
||||
* @param {BitFieldResolvable} bits Bits(s) to check for
|
||||
* @param {...*} hasParams Additional parameters for the has method, if any
|
||||
* @returns {string[]}
|
||||
*/
|
||||
missing(bits: BitFieldResolvable, ...hasParams: any[]): string[] {
|
||||
if (!Array.isArray(bits))
|
||||
bits = new (this.constructor as any)(bits).toArray(false)
|
||||
return (bits as string[]).filter((p) => !this.has(p, ...hasParams));
|
||||
}
|
||||
|
||||
/**
|
||||
* Freezes these bits, making them immutable.
|
||||
* @returns {Readonly<BitField>} These bits
|
||||
*/
|
||||
freeze(): Readonly<BitField> {
|
||||
return Object.freeze(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds bits to these ones.
|
||||
* @param {...BitFieldResolvable} [bits] Bits to add
|
||||
* @returns {BitField} These bits or new BitField if the instance is frozen.
|
||||
*/
|
||||
add(...bits: BitFieldResolvable[]): BitField {
|
||||
let total = 0;
|
||||
for (const bit of bits) {
|
||||
total |= (this.constructor as any).resolve(bit);
|
||||
}
|
||||
if (Object.isFrozen(this))
|
||||
return new (this.constructor as any)(this.bitfield | total);
|
||||
this.bitfield |= total;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes bits from these.
|
||||
* @param {...BitFieldResolvable} [bits] Bits to remove
|
||||
* @returns {BitField} These bits or new BitField if the instance is frozen.
|
||||
*/
|
||||
remove(...bits: BitFieldResolvable[]): BitField {
|
||||
let total = 0;
|
||||
for (const bit of bits) {
|
||||
total |= (this.constructor as any).resolve(bit);
|
||||
}
|
||||
if (Object.isFrozen(this))
|
||||
return new (this.constructor as any)(this.bitfield & ~total);
|
||||
this.bitfield &= ~total;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object mapping field names to a {@link boolean} indicating whether the
|
||||
* bit is available.
|
||||
* @param {...*} hasParams Additional parameters for the has method, if any
|
||||
* @returns {Object}
|
||||
*/
|
||||
serialize(...hasParams: any[]): object {
|
||||
const serialized = {};
|
||||
for (const flag of Object.keys((this.constructor as any).FLAGS)) {
|
||||
serialized[flag] = this.has(
|
||||
(this.constructor as any).FLAGS[flag],
|
||||
...hasParams
|
||||
);
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link Array} of bitfield names based on the bits available.
|
||||
* @param {...*} hasParams Additional parameters for the has method, if any
|
||||
* @returns {string[]}
|
||||
*/
|
||||
toArray(...hasParams: any[]): string[] {
|
||||
return Object.keys((this.constructor as any).FLAGS).filter((bit) =>
|
||||
this.has(bit, ...hasParams)
|
||||
);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return this.bitfield;
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.bitfield;
|
||||
}
|
||||
|
||||
*[Symbol.iterator]() {
|
||||
yield* this.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves bitfields to their numeric form.
|
||||
* @param {BitFieldResolvable} [bit=0] - bit(s) to resolve
|
||||
* @returns {number}
|
||||
*/
|
||||
static resolve(bit: BitFieldResolvable = 0): number {
|
||||
if (typeof bit === "number" && bit >= 0) return bit;
|
||||
if (bit instanceof BitField) return bit.bitfield;
|
||||
if (Array.isArray(bit))
|
||||
return bit
|
||||
.map((p) => this.resolve(p))
|
||||
.reduce((prev, p) => prev | p, 0);
|
||||
if (typeof bit === "string" && typeof this.FLAGS[bit] !== "undefined")
|
||||
return this.FLAGS[bit];
|
||||
throw new RangeError("Invalid bitfield flag or number.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Numeric bitfield flags.
|
||||
* <info>Defined in extension classes</info>
|
||||
* @type {Object}
|
||||
* @abstract
|
||||
*/
|
||||
static FLAGS: object = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a bitfield. This can be:
|
||||
* * A string (see {@link BitField.FLAGS})
|
||||
* * A bit number
|
||||
* * An instance of BitField
|
||||
* * An Array of BitFieldResolvable
|
||||
*/
|
||||
export type BitFieldResolvable = string|number|BitField|BitFieldResolvable[]
|
|
@ -0,0 +1,210 @@
|
|||
import BitField from "./BitField";
|
||||
import * as util from "util";
|
||||
|
||||
/**
|
||||
* Data structure that makes it easy to interact with a permission bitfield. All {@link GuildMember}s have a set of
|
||||
* permissions in their guild, and each channel in the guild may also have {@link PermissionOverwrites} for the member
|
||||
* that override their default permissions.
|
||||
* @extends {BitField}
|
||||
*/
|
||||
export default class Permissions extends BitField {
|
||||
/**
|
||||
* @param {number|PermissionResolvable} permissions Permissions or bitfield to read from
|
||||
*/
|
||||
constructor(permissions: number | PermissionResolvable) {
|
||||
super(permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitfield of the packed permissions
|
||||
* @type {number}
|
||||
* @see {@link Permissions#bitfield}
|
||||
* @deprecated
|
||||
* @readonly
|
||||
*/
|
||||
get raw() {
|
||||
return this.bitfield;
|
||||
}
|
||||
|
||||
set raw(raw) {
|
||||
this.bitfield = raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the bitfield has a permission, or any of multiple permissions.
|
||||
* @param {PermissionResolvable} permission Permission(s) to check for
|
||||
* @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
|
||||
* @returns {boolean}
|
||||
*/
|
||||
any(permission: PermissionResolvable, checkAdmin: boolean = true): boolean {
|
||||
return (
|
||||
(checkAdmin && super.has((this.constructor as any).FLAGS.ADMINISTRATOR)) ||
|
||||
super.any(permission)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the bitfield has a permission, or multiple permissions.
|
||||
* @param {PermissionResolvable} permission Permission(s) to check for
|
||||
* @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
|
||||
* @returns {boolean}
|
||||
*/
|
||||
has(permission: PermissionResolvable, checkAdmin: boolean = true): boolean {
|
||||
return (
|
||||
(checkAdmin && super.has((this.constructor as any).FLAGS.ADMINISTRATOR)) ||
|
||||
super.has(permission)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Numeric permission flags. All available properties:
|
||||
* - `ADMINISTRATOR` (implicitly has *all* permissions, and bypasses all channel overwrites)
|
||||
* - `CREATE_INSTANT_INVITE` (create invitations to the guild)
|
||||
* - `KICK_MEMBERS`
|
||||
* - `BAN_MEMBERS`
|
||||
* - `MANAGE_CHANNELS` (edit and reorder channels)
|
||||
* - `MANAGE_GUILD` (edit the guild information, region, etc.)
|
||||
* - `ADD_REACTIONS` (add new reactions to messages)
|
||||
* - `VIEW_AUDIT_LOG`
|
||||
* - `PRIORITY_SPEAKER`
|
||||
* - `STREAM`
|
||||
* - `VIEW_CHANNEL`
|
||||
* - `READ_MESSAGES` **(deprecated)**
|
||||
* - `SEND_MESSAGES`
|
||||
* - `SEND_TTS_MESSAGES`
|
||||
* - `MANAGE_MESSAGES` (delete messages and reactions)
|
||||
* - `EMBED_LINKS` (links posted will have a preview embedded)
|
||||
* - `ATTACH_FILES`
|
||||
* - `READ_MESSAGE_HISTORY` (view messages that were posted prior to opening Discord)
|
||||
* - `MENTION_EVERYONE`
|
||||
* - `USE_EXTERNAL_EMOJIS` (use emojis from different guilds)
|
||||
* - `EXTERNAL_EMOJIS` **(deprecated)**
|
||||
* - `CONNECT` (connect to a voice channel)
|
||||
* - `SPEAK` (speak in a voice channel)
|
||||
* - `MUTE_MEMBERS` (mute members across all voice channels)
|
||||
* - `DEAFEN_MEMBERS` (deafen members across all voice channels)
|
||||
* - `MOVE_MEMBERS` (move members between voice channels)
|
||||
* - `USE_VAD` (use voice activity detection)
|
||||
* - `CHANGE_NICKNAME`
|
||||
* - `MANAGE_NICKNAMES` (change other members' nicknames)
|
||||
* - `MANAGE_ROLES`
|
||||
* - `MANAGE_ROLES_OR_PERMISSIONS` **(deprecated)**
|
||||
* - `MANAGE_WEBHOOKS`
|
||||
* - `MANAGE_EMOJIS`
|
||||
* @type {Object}
|
||||
* @see {@link https://discordapp.com/developers/docs/topics/permissions}
|
||||
*/
|
||||
static FLAGS:{
|
||||
CREATE_INSTANT_INVITE: number,
|
||||
KICK_MEMBERS: number,
|
||||
BAN_MEMBERS: number,
|
||||
ADMINISTRATOR: number,
|
||||
MANAGE_CHANNELS: number,
|
||||
MANAGE_GUILD: number,
|
||||
ADD_REACTIONS: number,
|
||||
VIEW_AUDIT_LOG: number,
|
||||
PRIORITY_SPEAKER: number,
|
||||
STREAM: number,
|
||||
|
||||
VIEW_CHANNEL: number,
|
||||
READ_MESSAGES: number,
|
||||
SEND_MESSAGES: number,
|
||||
SEND_TTS_MESSAGES: number,
|
||||
MANAGE_MESSAGES: number,
|
||||
EMBED_LINKS: number,
|
||||
ATTACH_FILES: number,
|
||||
READ_MESSAGE_HISTORY: number,
|
||||
MENTION_EVERYONE: number,
|
||||
EXTERNAL_EMOJIS: number,
|
||||
USE_EXTERNAL_EMOJIS: number,
|
||||
|
||||
CONNECT: number,
|
||||
SPEAK: number,
|
||||
MUTE_MEMBERS: number,
|
||||
DEAFEN_MEMBERS: number,
|
||||
MOVE_MEMBERS: number,
|
||||
USE_VAD: number,
|
||||
|
||||
CHANGE_NICKNAME: number,
|
||||
MANAGE_NICKNAMES: number,
|
||||
MANAGE_ROLES: number,
|
||||
MANAGE_ROLES_OR_PERMISSIONS: number,
|
||||
MANAGE_WEBHOOKS: number,
|
||||
MANAGE_EMOJIS: number,
|
||||
} = {
|
||||
CREATE_INSTANT_INVITE: 1 << 0,
|
||||
KICK_MEMBERS: 1 << 1,
|
||||
BAN_MEMBERS: 1 << 2,
|
||||
ADMINISTRATOR: 1 << 3,
|
||||
MANAGE_CHANNELS: 1 << 4,
|
||||
MANAGE_GUILD: 1 << 5,
|
||||
ADD_REACTIONS: 1 << 6,
|
||||
VIEW_AUDIT_LOG: 1 << 7,
|
||||
PRIORITY_SPEAKER: 1 << 8,
|
||||
STREAM: 1 << 9,
|
||||
|
||||
VIEW_CHANNEL: 1 << 10,
|
||||
READ_MESSAGES: 1 << 10,
|
||||
SEND_MESSAGES: 1 << 11,
|
||||
SEND_TTS_MESSAGES: 1 << 12,
|
||||
MANAGE_MESSAGES: 1 << 13,
|
||||
EMBED_LINKS: 1 << 14,
|
||||
ATTACH_FILES: 1 << 15,
|
||||
READ_MESSAGE_HISTORY: 1 << 16,
|
||||
MENTION_EVERYONE: 1 << 17,
|
||||
EXTERNAL_EMOJIS: 1 << 18,
|
||||
USE_EXTERNAL_EMOJIS: 1 << 18,
|
||||
|
||||
CONNECT: 1 << 20,
|
||||
SPEAK: 1 << 21,
|
||||
MUTE_MEMBERS: 1 << 22,
|
||||
DEAFEN_MEMBERS: 1 << 23,
|
||||
MOVE_MEMBERS: 1 << 24,
|
||||
USE_VAD: 1 << 25,
|
||||
|
||||
CHANGE_NICKNAME: 1 << 26,
|
||||
MANAGE_NICKNAMES: 1 << 27,
|
||||
MANAGE_ROLES: 1 << 28,
|
||||
MANAGE_ROLES_OR_PERMISSIONS: 1 << 28,
|
||||
MANAGE_WEBHOOKS: 1 << 29,
|
||||
MANAGE_EMOJIS: 1 << 30,
|
||||
};
|
||||
|
||||
/**
|
||||
* Bitfield representing every permission combined
|
||||
* @type {number}
|
||||
*/
|
||||
static ALL: number = Object.keys(Permissions.FLAGS).reduce(
|
||||
(all, p) => all | Permissions.FLAGS[p],
|
||||
0
|
||||
);
|
||||
|
||||
/**
|
||||
* Bitfield representing the default permissions for users
|
||||
* @type {number}
|
||||
*/
|
||||
static DEFAULT: number = 104324673;
|
||||
}
|
||||
|
||||
Object.defineProperty(Permissions.prototype, "raw", {
|
||||
get: util.deprecate(
|
||||
Object.getOwnPropertyDescriptor(Permissions.prototype, "raw").get,
|
||||
"EvaluatedPermissions#raw is deprecated use Permissions#bitfield instead"
|
||||
),
|
||||
set: util.deprecate(
|
||||
Object.getOwnPropertyDescriptor(Permissions.prototype, "raw").set,
|
||||
"EvaluatedPermissions#raw is deprecated use Permissions#bitfield instead"
|
||||
),
|
||||
});
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a permission number. This can be:
|
||||
* * A string (see {@link Permissions.FLAGS})
|
||||
* * A permission number
|
||||
* @typedef {string|number|Permissions|PermissionResolvable[]} PermissionResolvable
|
||||
*/
|
||||
export type PermissionResolvable =
|
||||
| string
|
||||
| number
|
||||
| Permissions
|
||||
| PermissionResolvable[];
|
|
@ -2,11 +2,15 @@ import { DiscordChannel, DiscordGuild, DiscordGuildMember, DiscordRole, DiscordM
|
|||
import { Channel, Snowflake } from "..";
|
||||
import BaseChannel from "../structures/BaseChannel";
|
||||
import Guild from "../structures/Guild";
|
||||
import { TextChannel } from "../structures/TextChannel";
|
||||
import TextChannel from "../structures/TextChannel";
|
||||
import GuildMember from "../structures/GuildMember";
|
||||
import Role from "../structures/Role";
|
||||
import User from "../structures/User";
|
||||
import Message from "../structures/Message";
|
||||
import { ChannelTypes } from "./Constants";
|
||||
import CategoryChannel from "../structures/CategoryChannel";
|
||||
import Collection from "@discordjs/collection";
|
||||
import Permissions, { PermissionResolvable } from "./Permissions";
|
||||
|
||||
export function createChannel(channel:DiscordChannel):Channel{
|
||||
let constructor = channels[channel.type] || BaseChannel
|
||||
|
@ -109,3 +113,38 @@ export function resolveUserID(user:UserResolvable){
|
|||
if(user instanceof GuildMember)return user.id // GuildMember
|
||||
return null
|
||||
}
|
||||
|
||||
export type ChannelData = {
|
||||
type?: ChannelTypes,
|
||||
name?: string,
|
||||
position?: number,
|
||||
topic?: string,
|
||||
nsfw?: boolean,
|
||||
bitrate?: number,
|
||||
userLimit?: number,
|
||||
parent?: CategoryChannel|Snowflake,
|
||||
permissionOverwrites?: ChannelCreationOverwrites[] | Collection<Snowflake, PermissionOverwrites>,
|
||||
rateLimitPerUser?: number
|
||||
}
|
||||
|
||||
export type ChannelCreationOverwrites = {
|
||||
allow?: PermissionResolvable,
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
allowed?: PermissionResolvable,
|
||||
deny?: PermissionResolvable,
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
denied?: PermissionResolvable,
|
||||
id?: GuildMemberResolvable | RoleResolvable
|
||||
}
|
||||
|
||||
export type PermissionOverwrites = keyof typeof Permissions.FLAGS | number | Permissions | PermissionResolvable[]
|
||||
|
||||
export {BitFieldResolvable} from "./BitField"
|
||||
|
||||
export type GuildMemberResolvable = GuildMember | User
|
||||
|
||||
export type RoleResolvable = Role | Snowflake
|
|
@ -0,0 +1,7 @@
|
|||
# LightcordApi
|
||||
|
||||
Welcome to LightcordApi's Documentation !
|
||||
|
||||
The api is mainly written here.
|
||||
|
||||
The main's module documentation can be found [here](./interfaces/_index_.lightcordglobal.html)
|
|
@ -2867,6 +2867,27 @@
|
|||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
|
||||
"dev": true
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.7.6",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz",
|
||||
"integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5",
|
||||
"neo-async": "^2.6.0",
|
||||
"source-map": "^0.6.1",
|
||||
"uglify-js": "^3.1.4",
|
||||
"wordwrap": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
|
@ -2971,6 +2992,12 @@
|
|||
"minimalistic-assert": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"highlight.js": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.1.1.tgz",
|
||||
"integrity": "sha512-b4L09127uVa+9vkMgPpdUQP78ickGbHEQTWeBrQFTJZ4/n2aihWOGS0ZoUqAwjVmfjhq/C76HRzkqwZhK4sBbg==",
|
||||
"dev": true
|
||||
},
|
||||
"hmac-drbg": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||
|
@ -3372,6 +3399,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"lunr": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz",
|
||||
"integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==",
|
||||
"dev": true
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
|
||||
|
@ -3397,6 +3430,12 @@
|
|||
"object-visit": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"marked": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz",
|
||||
"integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng==",
|
||||
"dev": true
|
||||
},
|
||||
"md5.js": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||
|
@ -4015,6 +4054,12 @@
|
|||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"dev": true
|
||||
},
|
||||
"progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||
"dev": true
|
||||
},
|
||||
"promise-inflight": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
|
||||
|
@ -4144,6 +4189,15 @@
|
|||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"rechoir": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
|
||||
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"resolve": "^1.1.6"
|
||||
}
|
||||
},
|
||||
"regenerate": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
|
||||
|
@ -4441,6 +4495,17 @@
|
|||
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
|
||||
"dev": true
|
||||
},
|
||||
"shelljs": {
|
||||
"version": "0.8.4",
|
||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
|
||||
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.0.0",
|
||||
"interpret": "^1.0.0",
|
||||
"rechoir": "^0.6.2"
|
||||
}
|
||||
},
|
||||
"snapdragon": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
|
||||
|
@ -5006,12 +5071,74 @@
|
|||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
||||
"dev": true
|
||||
},
|
||||
"typedoc": {
|
||||
"version": "0.17.8",
|
||||
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.17.8.tgz",
|
||||
"integrity": "sha512-/OyrHCJ8jtzu+QZ+771YaxQ9s4g5Z3XsQE3Ma7q+BL392xxBn4UMvvCdVnqKC2T/dz03/VXSLVKOP3lHmDdc/w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs-extra": "^8.1.0",
|
||||
"handlebars": "^4.7.6",
|
||||
"highlight.js": "^10.0.0",
|
||||
"lodash": "^4.17.15",
|
||||
"lunr": "^2.3.8",
|
||||
"marked": "1.0.0",
|
||||
"minimatch": "^3.0.0",
|
||||
"progress": "^2.0.3",
|
||||
"shelljs": "^0.8.4",
|
||||
"typedoc-default-themes": "^0.10.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"typedoc-default-themes": {
|
||||
"version": "0.10.2",
|
||||
"resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.10.2.tgz",
|
||||
"integrity": "sha512-zo09yRj+xwLFE3hyhJeVHWRSPuKEIAsFK5r2u47KL/HBKqpwdUSanoaz5L34IKiSATFrjG5ywmIu98hPVMfxZg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lunr": "^2.3.8"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
|
||||
"integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.0.tgz",
|
||||
"integrity": "sha512-Esj5HG5WAyrLIdYU74Z3JdG2PxdIusvj6IWHMtlyESxc7kcDz7zYlYjpnSokn1UbpV0d/QX9fan7gkCNd/9BQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"unicode-canonical-property-names-ecmascript": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
|
||||
|
@ -5734,6 +5861,12 @@
|
|||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
|
||||
"dev": true
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
|
||||
"dev": true
|
||||
},
|
||||
"worker-farm": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
"build": "webpack --progress --colors",
|
||||
"watch": "webpack --progress --colors --watch",
|
||||
"build-prod": "webpack --progress --colors --mode production -o js/main.min.js --devtool none",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"watch-prod": "webpack --progress --colors --watch --mode production -o js/main.min.js --devtool none",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"docs": "typedoc --plugin ./node_modules/typedoc-plugin-markdown --out ../../LightcordApiDocs ./src"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
|
@ -22,6 +24,7 @@
|
|||
"babel-loader": "^8.0.6",
|
||||
"terser-webpack-plugin": "^3.0.6",
|
||||
"ts-loader": "^7.0.5",
|
||||
"typedoc": "^0.17.8",
|
||||
"typescript": "^3.9.5",
|
||||
"uuid": "^8.1.0",
|
||||
"webpack": "^4.43.0",
|
||||
|
|
|
@ -9,9 +9,11 @@ import SettingsTitle from "./general/SettingsTitle"
|
|||
import Tabs, { Tab } from "./general/Tabs"
|
||||
import SettingSubTitle from "./general/SettingSubTitle"
|
||||
import CodeBlock from "./general/CodeBlock"
|
||||
import cloneNullProto from "../modules/cloneNullProto"
|
||||
import Tooltip from "./general/Tooltip"
|
||||
|
||||
export default {
|
||||
inputs: {
|
||||
export default cloneNullProto({
|
||||
inputs: cloneNullProto({
|
||||
Button: DiscordButton,
|
||||
Switch: Switch,
|
||||
Choices: RadioGroup,
|
||||
|
@ -19,12 +21,13 @@ export default {
|
|||
TextArea: TextArea,
|
||||
TextInput: TextInput,
|
||||
Dropdown: Dropdown
|
||||
},
|
||||
general: {
|
||||
}),
|
||||
general: cloneNullProto({
|
||||
Title: Title,
|
||||
SettingsTitle: SettingsTitle,
|
||||
SettingSubTitle: SettingSubTitle,
|
||||
Tabs: Tabs,
|
||||
CodeBlock: CodeBlock
|
||||
}
|
||||
}
|
||||
CodeBlock: CodeBlock,
|
||||
Tooltip: Tooltip
|
||||
})
|
||||
})
|
|
@ -1,24 +1,27 @@
|
|||
import { ReactNode } from "react"
|
||||
import { ReactNode, CSSProperties } from "react"
|
||||
import NOOP from "../../modules/noop"
|
||||
import Title from "./Title"
|
||||
|
||||
|
||||
export default class Tabs extends React.Component<{
|
||||
type TabsProps = {
|
||||
children?: ReactNode,
|
||||
tabs: {label: string, id: string}[],
|
||||
active?: string
|
||||
onChange?: (tab: string) => void
|
||||
}, {
|
||||
active: string
|
||||
}> {
|
||||
static defaultProps = {
|
||||
children: null,
|
||||
tabs: {label: "No tabs was passed to <Tabs>.", id: "none"},
|
||||
active: null,
|
||||
onChange: NOOP
|
||||
onChange?: (tab: string) => void,
|
||||
style?: CSSProperties
|
||||
}
|
||||
|
||||
constructor(props){
|
||||
export default class Tabs extends React.Component<TabsProps, {
|
||||
active: string
|
||||
}> {
|
||||
static defaultProps:TabsProps = {
|
||||
children: null,
|
||||
tabs: [{label: "No tabs was passed to <Tabs>.", id: "none"}],
|
||||
active: null,
|
||||
onChange: NOOP,
|
||||
style: {}
|
||||
}
|
||||
|
||||
constructor(props:TabsProps){
|
||||
super(props)
|
||||
this.state = {
|
||||
active: this.props.active || null
|
||||
|
@ -41,7 +44,7 @@ export default class Tabs extends React.Component<{
|
|||
}
|
||||
|
||||
render(){
|
||||
return (<div className="lc-tabWrapper">
|
||||
return (<div className="lc-tabWrapper" style={this.props.style}>
|
||||
<div className="lc-tabnav" style={{flex: "0 1 auto"}}>
|
||||
{this.tabs.map(tab => {
|
||||
return React.createElement(Tab, {TabContainer: this, title: tab.label, id: tab.id, key: btoa(tab.label+":"+tab.id)})
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import WebpackLoader from "../../modules/WebpackLoader"
|
||||
import { ReactNode } from "react"
|
||||
import uuid from "../../modules/uuid"
|
||||
import Utils from "../../modules/Utils"
|
||||
|
||||
type TitleProps = {
|
||||
children?: ReactNode,
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
import WebpackLoader from "../../modules/WebpackLoader"
|
||||
import { ReactNode } from "react"
|
||||
import excludeProperties from "../../modules/excludeProperties"
|
||||
|
||||
type TooltipData = {
|
||||
onClick():void
|
||||
onMouseEnter():void
|
||||
onMouseLeave():void
|
||||
onContextMenu():void
|
||||
"aria-label": string
|
||||
}
|
||||
type TooltipProps = {
|
||||
children:ReactNode,
|
||||
text: string,
|
||||
position?: TooltipPosition,
|
||||
color?: TooltipColor
|
||||
}
|
||||
|
||||
let TooltipModules
|
||||
export default class Tooltip extends React.Component<TooltipProps> {
|
||||
constructor(props: TooltipProps){
|
||||
super(props)
|
||||
}
|
||||
|
||||
get modules(){
|
||||
return TooltipModules || (TooltipModules = [
|
||||
WebpackLoader.find(e => e.default && e.default.displayName === "Tooltip")
|
||||
])
|
||||
}
|
||||
|
||||
render(){
|
||||
let [
|
||||
Tooltip
|
||||
] = this.modules
|
||||
|
||||
let props = excludeProperties(this.props, ["children"])
|
||||
|
||||
return React.createElement(Tooltip.default, props, (data:TooltipData) => {
|
||||
return React.createElement("div", {
|
||||
...data,
|
||||
style: {
|
||||
width: "fit-content",
|
||||
height: "fit-content"
|
||||
}
|
||||
}, this.props.children)
|
||||
})
|
||||
}
|
||||
|
||||
static defaultProps:TooltipProps = {
|
||||
children: null,
|
||||
text: "No text was passed to Tooltip",
|
||||
position: "top",
|
||||
color: "brand"
|
||||
}
|
||||
|
||||
static get AllPreviews(){
|
||||
return AllPreviews || (() => {
|
||||
AllPreviews = []
|
||||
AllPreviews.push([
|
||||
{
|
||||
children: React.createElement(window.Lightcord.Api.Components.inputs.Button, {
|
||||
color: "green",
|
||||
look: "ghost",
|
||||
size: "small",
|
||||
hoverColor: "yellow",
|
||||
onClick: () => { },
|
||||
wrapper: false
|
||||
}, "Hover this button to see the tooltip")
|
||||
}
|
||||
])
|
||||
AllPreviews.push([
|
||||
{
|
||||
text: "Example Tooltip Text"
|
||||
}
|
||||
])
|
||||
let colors = []
|
||||
Tooltip.Colors.forEach(color => {
|
||||
colors.push({
|
||||
color: color
|
||||
})
|
||||
})
|
||||
AllPreviews.push(colors)
|
||||
let positions = []
|
||||
Tooltip.Positions.forEach(p => {
|
||||
positions.push({
|
||||
position: p
|
||||
})
|
||||
})
|
||||
AllPreviews.push(positions)
|
||||
return AllPreviews
|
||||
})()
|
||||
}
|
||||
|
||||
static Positions:TooltipPosition[] = ["top", "left", "right", "bottom"]
|
||||
static Colors:TooltipColor[] = ["black", "grey", "brand", "green", "yellow", "red"]
|
||||
}
|
||||
let AllPreviews
|
||||
|
||||
export type TooltipPosition = "top" | "left" | "right" | "bottom"
|
||||
export type TooltipColor = "black" | "grey" | "brand" | "green" | "yellow" | "red"
|
|
@ -10,7 +10,8 @@ type ButtonProps = {
|
|||
wrapper?: boolean,
|
||||
look?: ButtonLook,
|
||||
size?: ButtonSize,
|
||||
hoverColor?: ButtonHovers
|
||||
hoverColor?: ButtonHovers,
|
||||
disabled?: boolean
|
||||
}
|
||||
export default class Button extends React.Component<ButtonProps, {hover: boolean}> {
|
||||
constructor(props:ButtonProps){
|
||||
|
@ -66,6 +67,11 @@ export default class Button extends React.Component<ButtonProps, {hover: boolean
|
|||
if("hoverColor" in this.props){
|
||||
props.hoverColor = this.props.hoverColor
|
||||
}
|
||||
if("disabled" in this.props){
|
||||
props.disabled = this.props.disabled
|
||||
}else{
|
||||
props.disabled = false
|
||||
}
|
||||
}
|
||||
|
||||
if(props.color){
|
||||
|
@ -124,9 +130,10 @@ export default class Button extends React.Component<ButtonProps, {hover: boolean
|
|||
}} onMouseLeave={(ev) => {
|
||||
if(!hoverColor)return
|
||||
this.setState({hover: false})
|
||||
}}>
|
||||
}} disabled={props.disabled}>
|
||||
<div className={euhModule1.contents}>{props.children}</div>
|
||||
</button>
|
||||
|
||||
if(props.wrapper){
|
||||
return <div className={buttonModule.buttonWrapper}>
|
||||
{button}
|
||||
|
@ -169,6 +176,7 @@ export default class Button extends React.Component<ButtonProps, {hover: boolean
|
|||
AllPreviews.push([{children: "Test Button"}])
|
||||
AllPreviews.push([{onClick: () => {}}])
|
||||
AllPreviews.push([{wrapper: false}])
|
||||
AllPreviews.push([{disabled: false}, {disabled: true}])
|
||||
return AllPreviews
|
||||
})()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import WebpackLoader from "./modules/WebpackLoader"
|
||||
import Components from "./components/components"
|
||||
import uuid from "./modules/uuid"
|
||||
import PluginUtilities from "./modules/PluginUtilities"
|
||||
import Utils from "./modules/Utils"
|
||||
|
||||
const LightcordApi = {
|
||||
|
@ -14,75 +13,7 @@ const LightcordApi = {
|
|||
declare global {
|
||||
var React:typeof import("react")
|
||||
interface Window {
|
||||
Lightcord: {
|
||||
DiscordModules: {
|
||||
/**
|
||||
* Internal Discord's dispatcher - can be used to subscribe to gateway events / client events.
|
||||
*/
|
||||
dispatcher: {
|
||||
_subscriptions: any,
|
||||
_waitQueue: (() => void)[],
|
||||
_processingWaitQueue: boolean,
|
||||
_currentDispatchActionType: string | null,
|
||||
_orderedActionHandlers: any,
|
||||
_orderedCallbackTokens: any,
|
||||
_lastID: number,
|
||||
_dependencyGraph: any
|
||||
|
||||
isDispatching():boolean,
|
||||
/**
|
||||
* If the dispatcher isn't dispatching, then dispatch
|
||||
*/
|
||||
maybeDispatch(event: {type: string, [k: string]:any}):void,
|
||||
/**
|
||||
* Wait until the dispatcher finished dispatching, then dispatch
|
||||
*/
|
||||
dirtyDispatch(event: {type: string, [k: string]:any}):void,
|
||||
/**
|
||||
* dispatch
|
||||
*/
|
||||
dispatch(event: {type: string, [k: string]:any}):void,
|
||||
/** Same as dispatcher.dispatch */
|
||||
_dispatch(event: {type: string, [k: string]:any}):void,
|
||||
/**
|
||||
* Intercept events before they happens, if returning true, then the event will be blocked from dispatching.
|
||||
*/
|
||||
setInterceptor(interceptor: (event) => boolean):void,
|
||||
/**
|
||||
* Wait until the dispatcher has finished dispatching
|
||||
*/
|
||||
wait(waiting: () => void):void,
|
||||
/** Subscribe to an event */
|
||||
subscribe(event: string, listener: (event: {type: string, [k: string]:any}) => void):void,
|
||||
/**
|
||||
* Unsubscribe from the event.
|
||||
*/
|
||||
unsubscribe(event: string, listener: (event: {type: string, [k: string]:any}) => void):void,
|
||||
register(name: string, actionHandler: any, storeDidChange: any):void
|
||||
addDependencies,
|
||||
_invalidateCaches,
|
||||
_processWaitQueue,
|
||||
_computeOrderedActionHandlers,
|
||||
_computeOrderedCallbackTokens
|
||||
},
|
||||
constants: import("./types/DiscordConstantsTypes").default
|
||||
},
|
||||
Settings: {
|
||||
devMode: boolean,
|
||||
callRingingBeat: boolean
|
||||
},
|
||||
Api: {
|
||||
/**
|
||||
* Lightcord's autorization for lightcord's servers
|
||||
*/
|
||||
Authorization: string,
|
||||
/**
|
||||
* Waits until the first module that match the filter gets exported
|
||||
* @param filter The filter that specifies the module to match.
|
||||
*/
|
||||
ensureExported(filter: (mod:any) => boolean):Promise<any>
|
||||
} & typeof LightcordApi
|
||||
},
|
||||
Lightcord: LightcordGlobal,
|
||||
BDModules: {
|
||||
modules:any[],
|
||||
get(filter:(mod:any)=>boolean, modules?:any[]):any[],
|
||||
|
@ -90,8 +21,45 @@ declare global {
|
|||
get(ids: [number|((mod:any)=>boolean)], modules?:any[]):any
|
||||
}
|
||||
}
|
||||
var Lightcord:LightcordGlobal
|
||||
}
|
||||
|
||||
export default LightcordApi
|
||||
|
||||
Object.assign(window.Lightcord.Api, LightcordApi)
|
||||
|
||||
/**
|
||||
* The main Lightcord exports. Can be accessed with `window.Lightcord`
|
||||
*/
|
||||
export interface LightcordGlobal {
|
||||
DiscordModules: {
|
||||
/**
|
||||
* Internal Discord's dispatcher - can be used to subscribe to gateway events / client events.
|
||||
*/
|
||||
dispatcher: import("./types/DiscordDispatcherTypes").default,
|
||||
constants: import("./types/DiscordConstantsTypes").default
|
||||
},
|
||||
Settings: {
|
||||
devMode: boolean,
|
||||
callRingingBeat: boolean
|
||||
},
|
||||
Api: LightcordApiGlobal
|
||||
}
|
||||
|
||||
/**
|
||||
* The main Api. Can be accessed with `window.Lightcord.Api`
|
||||
*/
|
||||
type LightcordApiGlobal = lightcordApiMainExports & typeof LightcordApi
|
||||
|
||||
type lightcordApiMainExports = {
|
||||
/**
|
||||
* Waits until the first module that match the filter gets exported
|
||||
* @param filter The filter that specifies the module to match.
|
||||
*/
|
||||
ensureExported(filter: (mod:any) => boolean):Promise<any>,
|
||||
/**
|
||||
* Recreate the object without the `__proto__` and `prototype` properties - usefull for better formatting in console.
|
||||
* @param obj The object to recreate
|
||||
*/
|
||||
cloneNullProto<Obj = any>(obj:Obj):Obj
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
export default function cloneNullProto<Obj=any>(obj:Obj):Obj{ // recreate object without __proto__
|
||||
let o = Object.create(null)
|
||||
Object.keys(obj).forEach(k => {
|
||||
o[k] = obj[k]
|
||||
})
|
||||
return o
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
export default function excludeProperties<Obj = any>(obj:Obj, props:(keyof Obj)[]):Partial<Obj>{
|
||||
let newObj = {}
|
||||
|
||||
Object.keys(obj).forEach((k) => {
|
||||
if(props.includes(k as keyof Obj))return
|
||||
newObj[k] = obj[k]
|
||||
})
|
||||
|
||||
return newObj
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
export default interface DispatcherTypes {
|
||||
_subscriptions: any,
|
||||
_waitQueue: (() => void)[],
|
||||
_processingWaitQueue: boolean,
|
||||
_currentDispatchActionType: string | null,
|
||||
_orderedActionHandlers: any,
|
||||
_orderedCallbackTokens: any,
|
||||
_lastID: number,
|
||||
_dependencyGraph: any
|
||||
|
||||
isDispatching():boolean,
|
||||
/**
|
||||
* If the dispatcher isn't dispatching, then dispatch
|
||||
*/
|
||||
maybeDispatch(event: {type: string, [k: string]:any}):void,
|
||||
/**
|
||||
* Wait until the dispatcher finished dispatching, then dispatch
|
||||
*/
|
||||
dirtyDispatch(event: {type: string, [k: string]:any}):void,
|
||||
/**
|
||||
* dispatch
|
||||
*/
|
||||
dispatch(event: {type: string, [k: string]:any}):void,
|
||||
/** Same as dispatcher.dispatch */
|
||||
_dispatch(event: {type: string, [k: string]:any}):void,
|
||||
/**
|
||||
* Intercept events before they happens, if returning true, then the event will be blocked from dispatching.
|
||||
*/
|
||||
setInterceptor(interceptor: (event) => boolean):void,
|
||||
/**
|
||||
* Wait until the dispatcher has finished dispatching
|
||||
*/
|
||||
wait(waiting: () => void):void,
|
||||
/** Subscribe to an event */
|
||||
subscribe(event: string, listener: (event: {type: string, [k: string]:any}) => void):void,
|
||||
/**
|
||||
* Unsubscribe from the event.
|
||||
*/
|
||||
unsubscribe(event: string, listener: (event: {type: string, [k: string]:any}) => void):void,
|
||||
register(name: string, actionHandler: any, storeDidChange: any):void
|
||||
addDependencies,
|
||||
_invalidateCaches,
|
||||
_processWaitQueue,
|
||||
_computeOrderedActionHandlers,
|
||||
_computeOrderedCallbackTokens
|
||||
}
|
|
@ -60,7 +60,7 @@ module.exports = {
|
|||
parallel: true,
|
||||
sourceMap: true,
|
||||
terserOptions: {
|
||||
mangle: true,
|
||||
mangle: false,
|
||||
keep_classnames: true,
|
||||
keep_fnames: true
|
||||
}
|
||||
|
|
20
build.js
|
@ -4,7 +4,7 @@ const terser = require("terser")
|
|||
const util = require("util")
|
||||
|
||||
/** Super noisy if production is on. */
|
||||
const production = false
|
||||
const production = true
|
||||
|
||||
let fs = require("fs")
|
||||
|
||||
|
@ -23,7 +23,7 @@ async function main(){
|
|||
await fs.promises.mkdir(__dirname+"/distApp/dist", {"recursive": true})
|
||||
|
||||
console.info("Executing command `npm run compile`")
|
||||
console.log(child_process.execSync("npm run compile", {encoding: "binary"}))
|
||||
//console.log(child_process.execSync("npm run compile", {encoding: "binary"}))
|
||||
|
||||
let startDir = path.join(__dirname, "./dist")
|
||||
let newDir = path.join(__dirname, "./distApp/dist")
|
||||
|
@ -34,7 +34,7 @@ async function main(){
|
|||
for(let file of fs.readdirSync(folder, {withFileTypes: true})){
|
||||
if(file.isFile()){
|
||||
let filepath = path.join(folder, file.name)
|
||||
if(predicate(filepath)){
|
||||
if(predicate(filepath) && filepath.split(/[\\/]+/).reverse()[1] !== "js"){
|
||||
await compile(filepath, path.join(filepath.replace(folders.startDir, folders.newDir)), "..")
|
||||
}else{
|
||||
await fs.promises.copyFile(filepath, filepath.replace(folders.startDir, folders.newDir))
|
||||
|
@ -86,6 +86,20 @@ async function main(){
|
|||
await fs.promises.unlink(path.join(__dirname, "distApp", "LightcordApi", "webpack.config.js"))
|
||||
await fs.promises.unlink(path.join(__dirname, "distApp", "LightcordApi", "tsconfig.json"))
|
||||
|
||||
await processNextDir(path.join(__dirname, "DiscordJS"), {
|
||||
startDir: path.join(__dirname, "DiscordJS"),
|
||||
newDir: path.join(__dirname, "distApp", "DiscordJS")
|
||||
}, ((filepath) => filepath.endsWith(".js") && (!production ? !filepath.includes("node_modules") : true)), async (filepath, newpath) => {
|
||||
console.info(`Minifying ${filepath} to ${newpath}`)
|
||||
await fs.promises.writeFile(newpath, terser.minify(await fs.promises.readFile(filepath, "utf8")).code, "utf8")
|
||||
}).then(() => {
|
||||
console.info(`Copied files and minified them from ${path.join(__dirname, "DiscordJS")}.`)
|
||||
})
|
||||
|
||||
await fs.promises.rmdir(path.join(__dirname, "distApp", "DiscordJS", "src"), {"recursive": true})
|
||||
await fs.promises.unlink(path.join(__dirname, "distApp", "DiscordJS", "webpack.config.js"))
|
||||
await fs.promises.unlink(path.join(__dirname, "distApp", "DiscordJS", "tsconfig.json"))
|
||||
|
||||
fs.mkdirSync(path.join(__dirname, "distApp", "BetterDiscordApp", "js"), {recursive: true})
|
||||
fs.mkdirSync(path.join(__dirname, "distApp", "BetterDiscordApp", "css"), {recursive: true})
|
||||
const BDPackageJSON = require("./BetterDiscordApp/package.json")
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
"use strict";
|
||||
|
||||
|
||||
// This is a copy from LightcordApi/dist/components/inputs/Button.js
|
||||
// Source code: LightcordApi/src/components/inputs/Button.ts
|
||||
|
||||
const ModuleLoader = require("./loaders/modules");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const WebpackLoader_1 = {
|
||||
default: {
|
||||
findByUniqueProperties: (props) => {
|
||||
return ModuleLoader.get((mod) => {
|
||||
if(mod.__esModule && ("default" in mod)){
|
||||
let doesMatch = true
|
||||
for(let prop of props){
|
||||
if(!Object.prototype.hasOwnProperty.call(mod.default, prop))doesMatch = false
|
||||
}
|
||||
if(doesMatch)return true
|
||||
}
|
||||
for(let prop of props){
|
||||
if(!Object.prototype.hasOwnProperty.call(mod, prop))return false
|
||||
}
|
||||
return true
|
||||
})[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
let ButtonModules;
|
||||
let Button = /** @class */ (() => {
|
||||
class Button extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
hover: false
|
||||
};
|
||||
}
|
||||
get modules() {
|
||||
return ButtonModules || (ButtonModules = [
|
||||
WebpackLoader_1.default.findByUniqueProperties(["_horizontal"]),
|
||||
WebpackLoader_1.default.findByUniqueProperties(["colorTransparent"]),
|
||||
WebpackLoader_1.default.findByUniqueProperties(["buttonWrapper"]),
|
||||
WebpackLoader_1.default.findByUniqueProperties(["ButtonColors"]),
|
||||
]);
|
||||
}
|
||||
render() {
|
||||
let [flexModule, euhModule1, buttonModule, colorsModule] = this.modules;
|
||||
let props = {};
|
||||
if (this.props) {
|
||||
if ("color" in this.props) {
|
||||
props.color = this.props.color;
|
||||
}
|
||||
if ("children" in this.props) {
|
||||
props.children = this.props.children;
|
||||
}
|
||||
if ("onClick" in this.props) {
|
||||
props.onClick = this.props.onClick;
|
||||
}
|
||||
if ("wrapper" in this.props) {
|
||||
props.wrapper = !!this.props.wrapper;
|
||||
}
|
||||
if ("look" in this.props) {
|
||||
props.look = this.props.look;
|
||||
}
|
||||
if ("size" in this.props) {
|
||||
props.size = this.props.size;
|
||||
}
|
||||
if ("hoverColor" in this.props) {
|
||||
props.hoverColor = this.props.hoverColor;
|
||||
}
|
||||
}
|
||||
if (props.color) {
|
||||
props.color = props.color.toLowerCase();
|
||||
if (!Button.Colors.includes(props.color)) {
|
||||
props.color = Button.Colors[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
props.color = Button.Colors[0];
|
||||
}
|
||||
if (props.look) {
|
||||
props.look = props.look.toLowerCase();
|
||||
if (!Button.Looks.includes(props.look)) {
|
||||
props.look = Button.Looks[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
props.look = Button.Looks[0];
|
||||
}
|
||||
if (props.size) {
|
||||
props.size = props.size.toLowerCase();
|
||||
if (!Button.Sizes.includes(props.size)) {
|
||||
props.size = Button.Sizes[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
props.size = Button.Sizes[0];
|
||||
}
|
||||
if (props.hoverColor) {
|
||||
props.hoverColor = props.hoverColor.toLowerCase();
|
||||
if (!Button.HoverColors.includes(props.hoverColor)) {
|
||||
props.hoverColor = Button.HoverColors[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
props.hoverColor = Button.HoverColors[0];
|
||||
}
|
||||
let buttonSize = props.size ? colorsModule.ButtonSizes[props.size.toUpperCase()] || "" : "";
|
||||
if (buttonSize)
|
||||
buttonSize = " " + buttonSize;
|
||||
let hoverColor = props.hoverColor ? colorsModule.ButtonHovers[props.hoverColor.toUpperCase()] || "" : "";
|
||||
if (hoverColor)
|
||||
hoverColor = " " + hoverColor;
|
||||
props.onClick = typeof props.onClick === "function" ? props.onClick : () => { };
|
||||
if (typeof props.wrapper !== "boolean")
|
||||
props.wrapper = true;
|
||||
let hover = this.state.hover ? euhModule1.hasHover : "";
|
||||
if (hover)
|
||||
hover = " " + hover;
|
||||
let button = React.createElement("button", { type: "button", className: `${flexModule.flexChild} ${euhModule1.button} ${colorsModule.ButtonLooks[props.look.toUpperCase()]} ${colorsModule.ButtonColors[props.color.toUpperCase()]}${buttonSize}${hoverColor}${hover} ${euhModule1.grow}`, style: { flex: "0 1 auto" }, onClick: this.props.onClick, onMouseEnter: (ev) => {
|
||||
if (!hoverColor)
|
||||
return;
|
||||
this.setState({ hover: true });
|
||||
}, onMouseLeave: (ev) => {
|
||||
if (!hoverColor)
|
||||
return;
|
||||
this.setState({ hover: false });
|
||||
} },
|
||||
React.createElement("div", { className: euhModule1.contents }, props.children));
|
||||
if (props.wrapper) {
|
||||
return React.createElement("div", { className: buttonModule.buttonWrapper }, button);
|
||||
}
|
||||
return button;
|
||||
}
|
||||
}
|
||||
Button.Colors = ["brand", "grey", "red", "green", "yellow", "primary", "link", "white", "black", "transparent"];
|
||||
Button.Looks = ["filled", "inverted", "outlined", "ghost", "link", "blank"];
|
||||
Button.Sizes = ["small", "medium", "large", "xlarge", "min", "max", "icon", "none"];
|
||||
Button.HoverColors = ["default", ...Button.Colors];
|
||||
return Button;
|
||||
})();
|
||||
exports.default = Button;
|
||||
//# sourceMappingURL=Button.js.map
|
|
@ -7,4 +7,6 @@
|
|||
720388515329998869 # fall
|
||||
347721410082242572 # oafu
|
||||
695254385432854588 # oafu
|
||||
625350657829896224 # oafu
|
||||
652189358048411648 # mir
|
||||
703675553890435153 # blacklight more like black list :yoj:
|
|
@ -68,49 +68,32 @@ async function privateInit(){
|
|||
if(electron.remote.process.argv.includes("--disable-betterdiscord")){
|
||||
let formComponents
|
||||
let margins
|
||||
let ButtonModules
|
||||
class LightcordSettings extends React.Component {
|
||||
render(){
|
||||
if(!formComponents)formComponents = ModuleLoader.get(e => e.FormSection)[0]
|
||||
if(!margins)margins = ModuleLoader.get(e => e.marginTop60)[0]
|
||||
|
||||
let [
|
||||
flexModule,
|
||||
euhModule1,
|
||||
buttonModule,
|
||||
colorsModule,
|
||||
] = this.ButtonModules
|
||||
let button = require("./Button").default
|
||||
|
||||
return React.createElement("div", {}, [
|
||||
React.createElement(formComponents.FormSection, {
|
||||
className: "",
|
||||
tag: "h2",
|
||||
title: "Lightcord's Settings"
|
||||
}, [
|
||||
React.createElement("div", { className: buttonModule.buttonWrapper }, [
|
||||
React.createElement("button", {
|
||||
type: "button",
|
||||
className: `${flexModule.flexChild} ${euhModule1.button} ${euhModule1.lookFilled} ${colorsModule.ButtonColors.YELLOW} ${euhModule1.sizeSmall} ${euhModule1.grow}`,
|
||||
style: { flex: "0 1 auto" },
|
||||
}, React.createElement(button, {
|
||||
color: "yellow",
|
||||
look: "ghost",
|
||||
size: "medium",
|
||||
hoverColor: "red",
|
||||
onClick: () => {
|
||||
console.log("Should relaunch")
|
||||
electron.remote.app.relaunch({
|
||||
args: electron.remote.process.argv.slice(1).filter(e => e !== "--disable-betterdiscord")
|
||||
})
|
||||
electron.remote.app.quit()
|
||||
}
|
||||
},
|
||||
React.createElement("div", { className: euhModule1.contents }, "Relaunch with BetterDiscord"))
|
||||
])
|
||||
])
|
||||
])
|
||||
}
|
||||
|
||||
get ButtonModules(){ // caching modules
|
||||
return ButtonModules || (ButtonModules = [
|
||||
ModuleLoader.get(e => e["_horizontal"])[0],
|
||||
ModuleLoader.get(e => e["colorTransparent"])[0],
|
||||
ModuleLoader.get(e => e["buttonWrapper"])[0],
|
||||
ModuleLoader.get(e => e["ButtonColors"])[0]
|
||||
wrapper: true
|
||||
}, "Relaunch with BetterDiscord"))
|
||||
])
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +115,6 @@ async function privateInit(){
|
|||
let getPredicateSections = settingModule.default.prototype.getPredicateSections
|
||||
settingModule.default.prototype.getPredicateSections = function(){
|
||||
let result = getPredicateSections.call(this, ...arguments)
|
||||
console.log(result)
|
||||
if(result[1].section === "My Account"){ // user settings, not guild settings
|
||||
let poped = []
|
||||
|
||||
|
@ -261,25 +243,33 @@ async function privateInit(){
|
|||
}
|
||||
|
||||
const appSettings = electron.remote.getGlobal("appSettings")
|
||||
let Authorization = appSettings.get("LIGHTCORD_AUTH", false)
|
||||
/*let Authorization = appSettings.get("LIGHTCORD_AUTH", false)
|
||||
let shouldShowPrompt = Authorization === false
|
||||
|
||||
if(typeof Authorization !== "string"){
|
||||
Authorization = null
|
||||
appSettings.set("LIGHTCORD_AUTH", null)
|
||||
appSettings.save()
|
||||
}*/
|
||||
|
||||
let cloneNullProto = (obj) => { // recreate object without __proto__
|
||||
let o = Object.create(null)
|
||||
Object.keys(obj).forEach(k => {
|
||||
o[k] = obj[k]
|
||||
})
|
||||
return o
|
||||
}
|
||||
|
||||
window.Lightcord = {
|
||||
DiscordModules: {
|
||||
window.Lightcord = cloneNullProto({
|
||||
DiscordModules: cloneNullProto({
|
||||
dispatcher,
|
||||
constants
|
||||
},
|
||||
Settings: {
|
||||
}),
|
||||
Settings: cloneNullProto({
|
||||
devMode: false,
|
||||
callRingingBeat: true
|
||||
},
|
||||
Api: {
|
||||
}),
|
||||
Api: cloneNullProto({/*
|
||||
get Authorization(){
|
||||
return Authorization
|
||||
},
|
||||
|
@ -287,19 +277,21 @@ async function privateInit(){
|
|||
if(typeof data !== "string" && data !== null)return Authorization
|
||||
appSettings.set("LIGHTCORD_AUTH", Authorization = data)
|
||||
appSettings.save()
|
||||
},
|
||||
ensureExported
|
||||
},
|
||||
BetterDiscord: { // Global BetterDiscord's exported modules / only for exporting to Lightcord's main script, not for using in plugins
|
||||
},*/
|
||||
Authorization: null,
|
||||
ensureExported,
|
||||
cloneNullProto
|
||||
}),
|
||||
BetterDiscord: cloneNullProto({ // Global BetterDiscord's exported modules
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
dispatcher.subscribe("USER_SETTINGS_UPDATE", (data) => {
|
||||
DiscordNative.ipc.send("UPDATE_THEME", data.settings.theme)
|
||||
})
|
||||
|
||||
require("../../../../../LightcordApi/js/main")
|
||||
require("../../../../../LightcordApi/js/main.js")
|
||||
|
||||
/*
|
||||
if(shouldShowPrompt){
|
||||
|
@ -377,10 +369,6 @@ async function privateInit(){
|
|||
const Utils = window.Lightcord.BetterDiscord.Utils
|
||||
const DOMTools = window.Lightcord.BetterDiscord.DOM
|
||||
|
||||
// delete
|
||||
delete window.Lightcord.BetterDiscord.Utils
|
||||
delete window.Lightcord.BetterDiscord.DOM
|
||||
|
||||
let isBot = false
|
||||
;(async function(){
|
||||
const gatewayModule = await ensureExported(e => e.default && e.default.prototype && e.default.prototype._handleDispatch)
|
||||
|
@ -478,6 +466,9 @@ async function privateInit(){
|
|||
}
|
||||
return returnValue
|
||||
}
|
||||
dispatcher.subscribe("LOGOUT", () => {
|
||||
isBot = false
|
||||
})
|
||||
function cancelGatewayPrototype(methodName){
|
||||
if(gatewayModule.default.prototype[methodName]){
|
||||
const original = gatewayModule.default.prototype[methodName]
|
||||
|
@ -493,12 +484,18 @@ async function privateInit(){
|
|||
cancelGatewayPrototype("lobbyConnect")
|
||||
cancelGatewayPrototype("lobbyDisconnect")
|
||||
cancelGatewayPrototype("lobbyVoiceStatesUpdate")
|
||||
cancelGatewayPrototype("guildStreamCreate")
|
||||
cancelGatewayPrototype("streamCreate")
|
||||
cancelGatewayPrototype("streamWatch")
|
||||
cancelGatewayPrototype("streamPing")
|
||||
cancelGatewayPrototype("streamDelete")
|
||||
cancelGatewayPrototype("streamSetPaused")
|
||||
|
||||
const requestGuildMembers = gatewayModule.default.prototype.requestGuildMembers
|
||||
gatewayModule.default.prototype.requestGuildMembers = function(){ // TODO: requestGuildMembers patch for bots.
|
||||
/*if(!isBot)*/return requestGuildMembers.call(this, ...arguments)
|
||||
console.log(arguments)
|
||||
}
|
||||
|
||||
const hasUnreadModules = BDModules.get(e => e.default && e.default.hasUnread)
|
||||
hasUnreadModules.forEach((mod) => {
|
||||
const hasUnread = mod.default.hasUnread
|
||||
|
@ -1068,7 +1065,22 @@ async function privateInit(){
|
|||
}else{
|
||||
logger.warn(new Error("Couldn't find module here"))
|
||||
}
|
||||
})().catch(() => {})
|
||||
const inviteModule = BDModules.get(e => e.default && e.default.acceptInvite)[0]
|
||||
if(inviteModule){
|
||||
const acceptInvite = inviteModule.default.acceptInvite
|
||||
inviteModule.default.acceptInvite = function(code, location, extraOptions){
|
||||
if(!isBot)return acceptInvite.call(this, ...arguments)
|
||||
dispatcher.dispatch({
|
||||
type: "INVITE_ACCEPT_FAILURE",
|
||||
code
|
||||
})
|
||||
Utils.showToast("Lightcord Bot Emulation cannot join guilds.", {type: "error"})
|
||||
return Promise.reject("Lightcord Bot Emulation cannot join guilds.")
|
||||
}
|
||||
}else{
|
||||
logger.warn(new Error("Couldn't find module here"))
|
||||
}
|
||||
})().catch(console.error.bind(console, `%c[Error Bot shit]`, "color:red"))
|
||||
|
||||
|
||||
let usedWebhooks = {}
|
||||
|
@ -1169,7 +1181,7 @@ async function privateInit(){
|
|||
] = [
|
||||
BDModules.get(e => e.authBoxExpanded && typeof e.authBoxExpanded === "string")[0]
|
||||
]
|
||||
DOMTools.addStyle("tokenLoginPatch", `.${authBoxExpanded ? authBoxExpanded.authBoxExpanded.split(" ")[0] : "authBoxExpanded-2jqaBe"} {
|
||||
DOMTools.addStyle("tokenLoginPatch", `.${authBoxExpanded ? Utils.removeDa(authBoxExpanded.authBoxExpanded) : "authBoxExpanded-2jqaBe"} {
|
||||
width: 900px;
|
||||
}`)
|
||||
|
||||
|
@ -1177,6 +1189,36 @@ async function privateInit(){
|
|||
BetterDiscord.init()
|
||||
|
||||
events.emit("ready")
|
||||
|
||||
|
||||
let reactDevToolsPath = "";
|
||||
if (process.platform === "win32") reactDevToolsPath = path.resolve(process.env.LOCALAPPDATA, "Google/Chrome/User Data");
|
||||
else if (process.platform === "linux") reactDevToolsPath = path.resolve(process.env.HOME, ".config/google-chrome");
|
||||
else if (process.platform === "darwin") reactDevToolsPath = path.resolve(process.env.HOME, "Library/Application Support/Google/Chrome");
|
||||
else reactDevToolsPath = path.resolve(process.env.HOME, ".config/chromium");
|
||||
reactDevToolsPath += "/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/";
|
||||
if (fs.existsSync(reactDevToolsPath)) {
|
||||
const versions = fs.readdirSync(reactDevToolsPath);
|
||||
reactDevToolsPath = path.resolve(reactDevToolsPath, versions[versions.length - 1]);
|
||||
}
|
||||
if (!fs.existsSync(reactDevToolsPath), true){
|
||||
reactDevToolsPath = path.join(__dirname, "../../../../react_devtools")
|
||||
}
|
||||
if(fs.existsSync(reactDevToolsPath)){
|
||||
const webContents = remote.getCurrentWebContents()
|
||||
const BrowserWindow = remote.BrowserWindow
|
||||
setImmediate(() => webContents.on("devtools-opened", devToolsListener));
|
||||
if (webContents.isDevToolsOpened()) devToolsListener();
|
||||
|
||||
function devToolsListener(){
|
||||
if (!this.isExtensionInstalled) return;
|
||||
BrowserWindow.removeDevToolsExtension("React Developer Tools");
|
||||
const didInstall = BrowserWindow.addDevToolsExtension(reactDevToolsPath);
|
||||
|
||||
if (didInstall) Utils.log("React DevTools", "Successfully installed react devtools.");
|
||||
else Utils.err("React DevTools", "Couldn't find react devtools.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require.extensions[".css"] = (m, filename) => {
|
||||
|
@ -1196,6 +1238,7 @@ require.extensions[".css"] = (m, filename) => {
|
|||
|
||||
let zlib = require("zlib")
|
||||
let tmp = require("tmp")
|
||||
const { remote } = require("electron")
|
||||
|
||||
require.extensions[".jsbr"] = (m, filename) => {
|
||||
if(!zlib)zlib = require("zlib")
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
background: #18191c;
|
||||
border: 1px solid #040405;
|
||||
background: var(--background-floating);
|
||||
border: 1px solid var(--deprecated-text-input-border-hover);
|
||||
border-radius: 5px;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
|
@ -17,7 +17,7 @@
|
|||
|
||||
.lc-tabnav {
|
||||
top: 0;
|
||||
border-bottom: 1px solid #040405;
|
||||
border-bottom: 1px solid var(--deprecated-text-input-border-hover);
|
||||
padding: 0 4px;
|
||||
width: 100%;
|
||||
-ms-flex-item-align: start;
|
||||
|
@ -50,14 +50,10 @@
|
|||
overflow: hidden;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
width: 600px;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
-webkit-transform: scale(.85);
|
||||
transform: scale(.85);
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
|
@ -71,11 +67,16 @@
|
|||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
padding: 40px;
|
||||
}
|
||||
.lc-tab-box-shadow {
|
||||
.theme-dark .lc-tab-box-shadow {
|
||||
-webkit-box-shadow: 0 0 20px 2px rgba(4,4,5,.3);
|
||||
box-shadow: 0 0 20px 2px rgba(4,4,5,.3);
|
||||
}
|
||||
.theme-light .lc-tab-box-shadow {
|
||||
-webkit-box-shadow: 0 0 5px 2px rgba(4,4,5,.1);
|
||||
box-shadow: 0 0 5px 2px rgba(4,4,5,.1);
|
||||
}
|
||||
.lc-navItem {
|
||||
padding: 14px 20px;
|
||||
position: relative;
|
||||
|
@ -101,14 +102,17 @@
|
|||
transition: transform .125s,-webkit-transform .125s;
|
||||
}
|
||||
.lc-navItemActive {
|
||||
color: #fff;
|
||||
color: var(--interactive-active);
|
||||
}
|
||||
.lc-navItemActive::after {
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
}
|
||||
.lc-navItemInactive {
|
||||
color: #b9bbbe;
|
||||
color: var(--interactive-normal);
|
||||
}
|
||||
.lc-navItemInactive:hover {
|
||||
color: var(--interactive-hover)
|
||||
}
|
||||
.lc-navItemInactive::after {
|
||||
-webkit-transform: translateY(16px);
|
||||
|
|
|
@ -110,7 +110,7 @@ function startup(bootstrapModules) {
|
|||
console.log("Checking if version "+version+" is outdated...")
|
||||
bootstrapModules.splashScreen.initSplash()
|
||||
bootstrapModules.splashScreen.events.on("SPLASH_SCREEN_READY", () => {
|
||||
fetch("https://haste.deroku.xyz/raw/oqigetomog", {
|
||||
fetch("https://raw.githubusercontent.com/Lightcord/Lightcord/master/package.json", {
|
||||
headers: {
|
||||
"User-Agent": "Lightcord-Updater/1.0"
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ function setMainWindowVisible(visible) {
|
|||
|
||||
function updateApp(version){
|
||||
const bootstrapModules = require('./bootstrapModules')
|
||||
const updateLink = "https://github.com/Lightcord/Lightcord/archive/master.zip"
|
||||
//const updateLink = "https://github.com/Lightcord/Lightcord/archive/master.zip"
|
||||
|
||||
bootstrapModules.splashScreen.setSplashState({
|
||||
status: "downloading-updates",
|
||||
|
|
|
@ -7,6 +7,7 @@ process.on("uncaughtException", console.error)
|
|||
|
||||
const ipcRenderer = require('./discord_native/ipc');
|
||||
const electron = require("electron")
|
||||
electron.remote.getCurrentWindow().setBackgroundColor("#2f3136")
|
||||
|
||||
const TRACK_ANALYTICS_EVENT = 'TRACK_ANALYTICS_EVENT';
|
||||
const TRACK_ANALYTICS_EVENT_COMMIT = 'TRACK_ANALYTICS_EVENT_COMMIT';
|
||||
|
@ -82,7 +83,6 @@ process.once('loaded', () => {
|
|||
}catch(e){}
|
||||
setTimeout(() => {
|
||||
electron.remote.getCurrentWindow().setBackgroundColor("#00000000")
|
||||
electron.remote.getCurrentWindow().center()
|
||||
}, 500);
|
||||
})
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
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.
|
|
@ -0,0 +1,6 @@
|
|||
# Disclaimer
|
||||
This folder is only a copy of react devtools.
|
||||
|
||||
The files in this folder are under the right of Facebook.
|
||||
|
||||
https://github.com/facebook/react/tree/master/packages/react-devtools
|
|
@ -0,0 +1 @@
|
|||
!function(e){var n={};function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:o})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(t.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)t.d(o,r,function(n){return e[n]}.bind(null,r));return o},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=89)}({89:function(e,n,t){"use strict";var o={},r=navigator.userAgent.indexOf("Firefox")>=0;function i(e,n){chrome.browserAction.setIcon({tabId:n,path:{16:"icons/16-"+e+".png",32:"icons/32-"+e+".png",48:"icons/48-"+e+".png",128:"icons/128-"+e+".png"}}),chrome.browserAction.setPopup({tabId:n,popup:"popups/"+e+".html"})}chrome.runtime.onConnect.addListener((function(e){var n,t,r=null,i=null;+(t=e.name)+""===t?(r=e.name,i="devtools",n=+e.name,chrome.tabs.executeScript(n,{file:"/build/contentScript.js"},(function(){}))):(r=e.sender.tab.id,i="content-script"),o[r]||(o[r]={devtools:null,"content-script":null}),o[r][i]=e,o[r].devtools&&o[r]["content-script"]&&function(e,n){function t(e){n.postMessage(e)}function o(n){e.postMessage(n)}function r(){e.onMessage.removeListener(t),n.onMessage.removeListener(o),e.disconnect(),n.disconnect()}e.onMessage.addListener(t),n.onMessage.addListener(o),e.onDisconnect.addListener(r),n.onDisconnect.addListener(r)}(o[r].devtools,o[r]["content-script"])})),r&&chrome.tabs.onUpdated.addListener((function(e,n,t){t.active&&"loading"===n.status&&i("disabled",e)})),chrome.runtime.onMessage.addListener((function(e,n){if(n.tab&&e.hasDetectedReact){var t=e.reactBuildType;-1!==n.url.indexOf("facebook.github.io/react")&&(t="production"),i(t,n.tab.id)}}))}});
|
|
@ -0,0 +1 @@
|
|||
!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=90)}({90:function(e,t,n){"use strict";var o=!1,r=!1;function a(){window.postMessage({source:"react-devtools-content-script",hello:!0},"*")}function c(e){e.source===window&&e.data&&"react-devtools-bridge"===e.data.source&&(r=!0,s.postMessage(e.data.payload))}var s=chrome.runtime.connect({name:"content-script"});if(s.onMessage.addListener((function(e){window.postMessage({source:"react-devtools-content-script",payload:e},"*")})),s.onDisconnect.addListener((function(){o=!0,window.removeEventListener("message",c),window.postMessage({source:"react-devtools-content-script",payload:{type:"event",event:"shutdown"}},"*")})),window.addEventListener("message",c),a(),!r)var i=setInterval((function(){r||o?clearInterval(i):a()}),500)}});
|
|
@ -0,0 +1 @@
|
|||
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=158)}({158:function(e,t){window.container=document.getElementById("container");var n=!1;window.injectStyles=function(e){if(!n){n=!0;var t=e(),r=!0,o=!1,u=void 0;try{for(var i,l=t[Symbol.iterator]();!(r=(i=l.next()).done);r=!0){var a=i.value;document.head.appendChild(a)}}catch(e){o=!0,u=e}finally{try{r||null==l.return||l.return()}finally{if(o)throw u}}}}}});
|
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 638 B |
After Width: | Height: | Size: 638 B |
After Width: | Height: | Size: 522 B |
After Width: | Height: | Size: 558 B |
After Width: | Height: | Size: 594 B |
After Width: | Height: | Size: 638 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.0 KiB |
|
@ -0,0 +1 @@
|
|||
<svg id="Development" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><defs><style>.cls-1{fill:#d94a38;}.cls-2{fill:#fff;}.cls-3{fill:#231f20;}.cls-4{font-size:12px;font-family:MyriadPro-Regular, Myriad Pro;}</style></defs><title>development</title><g id="Background"><rect class="cls-1" width="1024" height="1024" rx="96" ry="96"/></g><g id="Rings"><g id="Ring-2" data-name="Ring"><path class="cls-2" d="M959,509c0-62-74-117-189-150,27-115,17-207-37-238s-139,6-224,88c-86-81-171-118-224-87s-64,123-36,239C135,394,61,449,61,511s74,117,189,150c-27,115-17,207,37,238s139-6,224-88c86,81,171,118,224,87s64-123,36-239C885,626,959,571,959,509ZM713,157c40,23,45,97,21,193a900,900,0,0,0-121-19,900,900,0,0,0-78-94C606,166,673,133,713,157ZM635,583c-14,24-28,47-43,69-27,2-54,3-83,3l-81-3c-15-22-30-46-44-70s-27-48-38-72c12-24,24-49,39-73s28-47,43-69c27-2,54-3,83-3l81,3c15,22,30,46,44,70s27,48,38,72C662,534,649,558,635,583Zm60-27c11,26,21,52,29,77-25,6-52,10-81,14l26-44ZM511,757c-17-19-35-40-52-63H563C546,716,528,738,511,757ZM378,647c-29-3-56-8-81-13,8-25,17-50,28-77l25,45ZM325,464c-11-26-21-52-29-77,25-6,52-10,81-14l-26,44ZM509,263c17,19,35,40,52,63H457C474,304,492,282,509,263ZM670,418l-28-45c29,3,56,8,81,13-8,25-17,50-28,77ZM305,158c40-23,106,9,177,78a900,900,0,0,0-77,95,900,900,0,0,0-120,20C260,255,265,181,305,158ZM102,511c0-46,61-88,156-114a900,900,0,0,0,44,114,900,900,0,0,0-43,114C164,599,102,558,102,511ZM307,863c-40-23-45-97-21-193a900,900,0,0,0,121,19,900,900,0,0,0,78,94C414,854,347,887,307,863Zm408-1c-40,23-106-9-177-78a900,900,0,0,0,77-95,900,900,0,0,0,120-20C760,765,755,839,715,862Zm46-239a900,900,0,0,0-44-114,900,900,0,0,0,43-114c96,26,157,67,157,114S856,597,761,623Z"/></g></g><g id="Ring_Blockers" data-name="Ring Blockers"><circle class="cls-1" cx="417" cy="672" r="45"/><circle class="cls-1" cx="699" cy="513" r="45"/><circle class="cls-1" cx="797" cy="634" r="45"/><circle class="cls-1" cx="479" cy="818" r="45"/><g id="Layer_14" data-name="Layer 14"><rect class="cls-1" x="420" y="621" width="377" height="188"/><rect class="cls-1" x="500" y="530" width="312" height="405"/></g></g><g id="Bug"><g id="Legs"><path class="cls-3" d="M702,496a17,17,0,0,0-21,13l-19,78,34,8,19-78A17,17,0,0,0,702,496Z"/><text class="cls-4" transform="translate(512 512)">780</text><text class="cls-4" transform="translate(512 512)">780</text><path class="cls-3" d="M813,626a17,17,0,0,0-23-9l-73,32,14,32,73-32A17,17,0,0,0,813,626Z"/><path class="cls-3" d="M834,756l-77-20-9,34,77,20a18,18,0,0,0,9-34Z"/><path class="cls-3" d="M425,656a17,17,0,1,0-10,33l76,23,10-33Z"/><path class="cls-3" d="M532,756l-64,48a18,18,0,1,0,21,28l64-48Z"/><path class="cls-3" d="M584,836l-21,77a17,17,0,1,0,34,9l21-77Z"/></g><g id="Body"><path class="cls-3" d="M762,690h0l-51-92h0A125,125,0,0,0,492,721h0l51,92h0A125,125,0,0,0,762,690Z"/></g><g id="Line"><path class="cls-1" d="M613,649h0a17,17,0,0,0-30,18h0L711,887l30-18Z"/></g><g id="Head_Ring" data-name="Head Ring"><circle class="cls-1" cx="511" cy="509" r="113"/></g><g id="Head"><circle class="cls-3" cx="512" cy="512" r="80"/></g></g></svg>
|
After Width: | Height: | Size: 3.0 KiB |
|
@ -0,0 +1 @@
|
|||
<svg id="Development" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><defs><style>.cls-1{fill:#d94a38;}.cls-2{fill:#fff;}.cls-3{fill:#231f20;}.cls-4{font-size:12px;font-family:MyriadPro-Regular, Myriad Pro;}</style></defs><title>development</title><g id="Background"><rect class="cls-1" width="1024" height="1024" rx="96" ry="96"/></g><g id="Rings"><g id="Ring-2" data-name="Ring"><path class="cls-2" d="M959,509c0-62-74-117-189-150,27-115,17-207-37-238s-139,6-224,88c-86-81-171-118-224-87s-64,123-36,239C135,394,61,449,61,511s74,117,189,150c-27,115-17,207,37,238s139-6,224-88c86,81,171,118,224,87s64-123,36-239C885,626,959,571,959,509ZM713,157c40,23,45,97,21,193a900,900,0,0,0-121-19,900,900,0,0,0-78-94C606,166,673,133,713,157ZM635,583c-14,24-28,47-43,69-27,2-54,3-83,3l-81-3c-15-22-30-46-44-70s-27-48-38-72c12-24,24-49,39-73s28-47,43-69c27-2,54-3,83-3l81,3c15,22,30,46,44,70s27,48,38,72C662,534,649,558,635,583Zm60-27c11,26,21,52,29,77-25,6-52,10-81,14l26-44ZM511,757c-17-19-35-40-52-63H563C546,716,528,738,511,757ZM378,647c-29-3-56-8-81-13,8-25,17-50,28-77l25,45ZM325,464c-11-26-21-52-29-77,25-6,52-10,81-14l-26,44ZM509,263c17,19,35,40,52,63H457C474,304,492,282,509,263ZM670,418l-28-45c29,3,56,8,81,13-8,25-17,50-28,77ZM305,158c40-23,106,9,177,78a900,900,0,0,0-77,95,900,900,0,0,0-120,20C260,255,265,181,305,158ZM102,511c0-46,61-88,156-114a900,900,0,0,0,44,114,900,900,0,0,0-43,114C164,599,102,558,102,511ZM307,863c-40-23-45-97-21-193a900,900,0,0,0,121,19,900,900,0,0,0,78,94C414,854,347,887,307,863Zm408-1c-40,23-106-9-177-78a900,900,0,0,0,77-95,900,900,0,0,0,120-20C760,765,755,839,715,862Zm46-239a900,900,0,0,0-44-114,900,900,0,0,0,43-114c96,26,157,67,157,114S856,597,761,623Z"/></g></g><g id="Ring_Blockers" data-name="Ring Blockers"><circle class="cls-1" cx="417" cy="672" r="45"/><circle class="cls-1" cx="699" cy="513" r="45"/><circle class="cls-1" cx="797" cy="634" r="45"/><circle class="cls-1" cx="479" cy="818" r="45"/><g id="Layer_14" data-name="Layer 14"><rect class="cls-1" x="420" y="621" width="377" height="188"/><rect class="cls-1" x="500" y="530" width="312" height="405"/></g></g><g id="Bug"><g id="Legs"><path class="cls-3" d="M702,496a17,17,0,0,0-21,13l-19,78,34,8,19-78A17,17,0,0,0,702,496Z"/><text class="cls-4" transform="translate(512 512)">780</text><text class="cls-4" transform="translate(512 512)">780</text><path class="cls-3" d="M813,626a17,17,0,0,0-23-9l-73,32,14,32,73-32A17,17,0,0,0,813,626Z"/><path class="cls-3" d="M834,756l-77-20-9,34,77,20a18,18,0,0,0,9-34Z"/><path class="cls-3" d="M425,656a17,17,0,1,0-10,33l76,23,10-33Z"/><path class="cls-3" d="M532,756l-64,48a18,18,0,1,0,21,28l64-48Z"/><path class="cls-3" d="M584,836l-21,77a17,17,0,1,0,34,9l21-77Z"/></g><g id="Body"><path class="cls-3" d="M762,690h0l-51-92h0A125,125,0,0,0,492,721h0l51,92h0A125,125,0,0,0,762,690Z"/></g><g id="Line"><path class="cls-1" d="M613,649h0a17,17,0,0,0-30,18h0L711,887l30-18Z"/></g><g id="Head_Ring" data-name="Head Ring"><circle class="cls-1" cx="511" cy="509" r="113"/></g><g id="Head"><circle class="cls-3" cx="512" cy="512" r="80"/></g></g></svg>
|
After Width: | Height: | Size: 3.0 KiB |
|
@ -0,0 +1 @@
|
|||
<svg id="Disabled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><defs><style>.cls-1{fill:#aaa;}.cls-2{fill:#fff;}</style></defs><title>disabled</title><g id="Background"><rect class="cls-1" width="1024" height="1024" rx="96" ry="96"/></g><g id="Rings"><path class="cls-2" d="M959,509c0-62-74-117-189-150,27-115,17-207-37-238s-139,6-224,88c-86-81-171-118-224-87s-64,123-36,239C135,394,61,449,61,511s74,117,189,150c-27,115-17,207,37,238s139-6,224-88c86,81,171,118,224,87s64-123,36-239C885,626,959,571,959,509ZM713,157c40,23,45,97,21,193a900,900,0,0,0-121-19,900,900,0,0,0-78-94C606,166,673,133,713,157ZM635,583c-14,24-28,47-43,69-27,2-54,3-83,3l-81-3c-15-22-30-46-44-70s-27-48-38-72c12-24,24-49,39-73s28-47,43-69c27-2,54-3,83-3l81,3c15,22,30,46,44,70s27,48,38,72C662,534,649,558,635,583Zm60-27c11,26,21,52,29,77-25,6-52,10-81,14l26-44ZM511,757c-17-19-35-40-52-63H563C546,716,528,738,511,757ZM378,647c-29-3-56-8-81-13,8-25,17-50,28-77l25,45ZM325,464c-11-26-21-52-29-77,25-6,52-10,81-14l-26,44ZM509,263c17,19,35,40,52,63H457C474,304,492,282,509,263ZM670,418l-28-45c29,3,56,8,81,13-8,25-17,50-28,77ZM305,158c40-23,106,9,177,78a900,900,0,0,0-77,95,900,900,0,0,0-120,20C260,255,265,181,305,158ZM102,511c0-46,61-88,156-114a900,900,0,0,0,44,114,900,900,0,0,0-43,114C164,599,102,558,102,511ZM307,863c-40-23-45-97-21-193a900,900,0,0,0,121,19,900,900,0,0,0,78,94C414,854,347,887,307,863Zm408-1c-40,23-106-9-177-78a900,900,0,0,0,77-95,900,900,0,0,0,120-20C760,765,755,839,715,862Zm46-239a900,900,0,0,0-44-114,900,900,0,0,0,43-114c96,26,157,67,157,114S856,597,761,623Z"/></g><g id="Circle"><circle class="cls-2" cx="510" cy="510" r="80"/></g></svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1 @@
|
|||
<svg id="Outdated" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><defs><style>.cls-1{fill:#202020;}.cls-2{fill:#fff;}.cls-3{fill:#f9f453;}</style></defs><title>outdated</title><g id="Background"><rect class="cls-1" width="1024" height="1024" rx="96" ry="96"/></g><g id="Rings"><path class="cls-2" d="M510,325C261,325,60,408,60,510S261,695,510,695s450-83,450-185S759,325,510,325Zm0,330c-225,0-407-65-407-145S285,365,510,365s408,65,408,145S735,655,510,655Z"/><path class="cls-2" d="M670,417C546,202,373,69,285,120s-59,267,65,482S647,951,735,900,794,633,670,417ZM384,583C272,388,237,197,306,157s217,86,329,280,148,385,78,425S497,777,384,583Z"/><g id="BLOCKER"><rect class="cls-1" x="564" y="572" width="315" height="397.12" transform="translate(652 -283) rotate(39)"/><rect class="cls-1" x="685" y="369" width="283" height="360.81" transform="translate(255 -262) rotate(21)"/></g><path class="cls-2" d="M670,603c124-215,153-431,65-482S474,202,350,417,197,849,285,900,546,818,670,603ZM384,437C497,243,644,117,714,157s34,231-78,425S376,903,306,863,272,632,384,437Z"/></g><g id="Circle"><circle class="cls-2" cx="512" cy="512" r="80"/></g><g id="Shield"><path class="cls-3" d="M960,887a24,24,0,0,0-5-15h0L807,605h0v-2h0a25,25,0,0,0-43,3h0L613,876h0a24,24,0,0,0-3,11,25,25,0,0,0,24,25H936A25,25,0,0,0,960,887ZM810,848a15,15,0,0,1-15,15H775a15,15,0,0,1-15-15V828a15,15,0,0,1,15-15h20a15,15,0,0,1,15,15Zm0-74a15,15,0,0,1-15,15H775a15,15,0,0,1-15-15V705a15,15,0,0,1,15-15h20a15,15,0,0,1,15,15Z"/></g></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1 @@
|
|||
<svg id="Production" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><defs><style>.cls-1{fill:#202020;}.cls-2{fill:#59c9f1;}</style></defs><title>production</title><g id="Background"><rect class="cls-1" width="1024" height="1024" rx="96" ry="96"/></g><g id="Rings"><path class="cls-2" d="M959,509c0-62-74-117-189-150,27-115,17-207-37-238s-139,6-224,88c-86-81-171-118-224-87s-64,123-36,239C135,394,61,449,61,511s74,117,189,150c-27,115-17,207,37,238s139-6,224-88c86,81,171,118,224,87s64-123,36-239C885,626,959,571,959,509ZM713,157c40,23,45,97,21,193a900,900,0,0,0-121-19,900,900,0,0,0-78-94C606,166,673,133,713,157ZM635,583c-14,24-28,47-43,69-27,2-54,3-83,3l-81-3c-15-22-30-46-44-70s-27-48-38-72c12-24,24-49,39-73s28-47,43-69c27-2,54-3,83-3l81,3c15,22,30,46,44,70s27,48,38,72C662,534,649,558,635,583Zm60-27c11,26,21,52,29,77-25,6-52,10-81,14l26-44ZM511,757c-17-19-35-40-52-63H563C546,716,528,738,511,757ZM378,647c-29-3-56-8-81-13,8-25,17-50,28-77l25,45ZM325,464c-11-26-21-52-29-77,25-6,52-10,81-14l-26,44ZM509,263c17,19,35,40,52,63H457C474,304,492,282,509,263ZM670,418l-28-45c29,3,56,8,81,13-8,25-17,50-28,77ZM305,158c40-23,106,9,177,78a900,900,0,0,0-77,95,900,900,0,0,0-120,20C260,255,265,181,305,158ZM102,511c0-46,61-88,156-114a900,900,0,0,0,44,114,900,900,0,0,0-43,114C164,599,102,558,102,511ZM307,863c-40-23-45-97-21-193a900,900,0,0,0,121,19,900,900,0,0,0,78,94C414,854,347,887,307,863Zm408-1c-40,23-106-9-177-78a900,900,0,0,0,77-95,900,900,0,0,0,120-20C760,765,755,839,715,862Zm46-239a900,900,0,0,0-44-114,900,900,0,0,0,43-114c96,26,157,67,157,114S856,597,761,623Z"/></g><g id="Circle"><circle class="cls-2" cx="510" cy="510" r="80"/></g></svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,9 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="./build/main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"background": {
|
||||
"persistent": false,
|
||||
"scripts": [ "build/background.js" ]
|
||||
},
|
||||
"browser_action": {
|
||||
"default_icon": {
|
||||
"128": "icons/128-disabled.png",
|
||||
"16": "icons/16-disabled.png",
|
||||
"32": "icons/32-disabled.png",
|
||||
"48": "icons/48-disabled.png"
|
||||
},
|
||||
"default_popup": "popups/disabled.html"
|
||||
},
|
||||
"content_scripts": [ {
|
||||
"js": [ "build/injectGlobalHook.js" ],
|
||||
"matches": [ "\u003Call_urls>" ],
|
||||
"run_at": "document_start"
|
||||
} ],
|
||||
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
|
||||
"description": "Adds React debugging tools to the Chrome Developer Tools.\n\nCreated from revision 23309eb38 on 5/18/2020.",
|
||||
"devtools_page": "main.html",
|
||||
"icons": {
|
||||
"128": "icons/128-production.png",
|
||||
"16": "icons/16-production.png",
|
||||
"32": "icons/32-production.png",
|
||||
"48": "icons/48-production.png"
|
||||
},
|
||||
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA39Lr82J1eer+RvXeQG6HYHb2A6xU/83bcIyOcu+Wu2vYO/jbBvlD3m/xqrU4xSXJ/uAC1XY/YtlRs2X2RE1XiYMMlnqw27QdI5tVcSnKedmTFNAsnSaQ/OZT5tzH3HntLDfrFof5BC5RmFuie+kQKGTh673JW0ZdKTUsW406Fckagl9WpPL+qp3Gah3Jw02zxfQX9yUd5gJHYvv8T31DO9+HsI8lPeEjanURY59rRUfg3JKy1aPfts6eISy9kpHC+LrRSHU2Zp5AuUkOh8qEg6DoHFwBNYX20bdd6ekj0OZiIz/9xj9ceNhAr85QYB0641Tzhs3Tg96k56VNwjdN2QIDAQAB",
|
||||
"manifest_version": 2,
|
||||
"minimum_chrome_version": "49",
|
||||
"name": "React Developer Tools",
|
||||
"permissions": [ "file:///*", "http://*/*", "https://*/*" ],
|
||||
"update_url": "https://clients2.google.com/service/update2/crx",
|
||||
"version": "4.7.0",
|
||||
"version_name": "4.7.0 (5/18/2020)",
|
||||
"web_accessible_resources": [ "main.html", "panel.html", "build/react_devtools_backend.js", "build/renderer.js" ]
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<!doctype html>
|
||||
<html style="display: flex">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<style>
|
||||
html {
|
||||
display: flex;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
#container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- main react mount point -->
|
||||
<div id="container">Unable to find React on the page.</div>
|
||||
<script src="./build/panel.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,32 @@
|
|||
<script src="shared.js"></script>
|
||||
<style>
|
||||
html, body {
|
||||
font-size: 14px;
|
||||
min-width: 460px;
|
||||
min-height: 133px;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
hr {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<p>
|
||||
<b>This page includes an extra development build of React. 🚧</b>
|
||||
</p>
|
||||
<p>
|
||||
The React build on this page includes both development and production versions because dead code elimination has not been applied correctly.
|
||||
<br />
|
||||
<br />
|
||||
This makes its size larger, and causes React to run slower.
|
||||
<br />
|
||||
<br />
|
||||
Make sure to <a href="https://facebook.github.io/react/docs/optimizing-performance.html#use-the-production-build">set up dead code elimination</a> before deployment.
|
||||
</p>
|
||||
<hr />
|
||||
<p>
|
||||
Open the developer tools, and "Components" and "Profiler" tabs will appear to the right.
|
||||
</p>
|
|
@ -0,0 +1,28 @@
|
|||
<script src="shared.js"></script>
|
||||
<style>
|
||||
html, body {
|
||||
font-size: 14px;
|
||||
min-width: 460px;
|
||||
min-height: 101px;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
hr {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<p>
|
||||
<b>This page is using the development build of React. 🚧</b>
|
||||
</p>
|
||||
<p>
|
||||
Note that the development build is not suitable for production.
|
||||
<br />
|
||||
Make sure to <a href="https://facebook.github.io/react/docs/optimizing-performance.html#use-the-production-build">use the production build</a> before deployment.
|
||||
</p>
|
||||
<hr />
|
||||
<p>
|
||||
Open the developer tools, and "Components" and "Profiler" tabs will appear to the right.
|
||||
</p>
|