mirror of
https://github.com/Lightcord/Lightcord.git
synced 2025-04-12 00:55:40 +02:00
Saving Checkpoint before I'm doing *risky* things
This commit is contained in:
parent
e47e1b0158
commit
df6c9c4203
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ['https://paypal.me/jenwina'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -110,3 +110,7 @@ builds
|
||||
dist
|
||||
|
||||
distApp
|
||||
|
||||
# discord_voice debug
|
||||
discord-last-webrtc_0
|
||||
discord-webrtc_0
|
File diff suppressed because one or more lines are too long
2
BetterDiscordApp/js/main.min.js
vendored
2
BetterDiscordApp/js/main.min.js
vendored
File diff suppressed because one or more lines are too long
6
BetterDiscordApp/package-lock.json
generated
6
BetterDiscordApp/package-lock.json
generated
@ -4186,7 +4186,7 @@
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
|
||||
"integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
|
||||
"dev": true
|
||||
},
|
||||
@ -6505,7 +6505,7 @@
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -6614,7 +6614,7 @@
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
@ -76,6 +76,7 @@ export const settings = {
|
||||
"Scroll To Settings": {id: "fork-ps-3", info: "Auto-scrolls to a plugin's settings when the button is clicked (only if out of view)", implemented: true, hidden: false, cat: "core", category: "content manager"},
|
||||
"Automatic Loading": {id: "fork-ps-5", info: "Automatically loads, reloads, and unloads plugins and themes", implemented: true, hidden: false, cat: "core", category: "content manager"},
|
||||
"Enable Edit Button": {id: "fork-ps-7", info: "Enable an Edit Button on the plugin and theme panel.", implemented: true, hidden: false, cat: "core", category: "content manager"},
|
||||
"Themes in Popout Window": {id: "lightcord-9", info: "Enable themes in Popout Window. (For example, when detaching screenshare.)", implemented: true, hidden: false, cat: "core", category: "content manager", experimental: true},
|
||||
|
||||
/* Developer */
|
||||
"Developer Mode": {id: "bda-gs-8", info: "Developer Mode Toggle", implemented: true, hidden: false, cat: "core", category: "developer settings"},
|
||||
@ -146,6 +147,7 @@ export const defaultCookie = {
|
||||
"lightcord-6": true,
|
||||
"lightcord-7": false,
|
||||
"lightcord-8": false,
|
||||
"lightcord-9": false,
|
||||
"lightcord-10": false,
|
||||
"no_window_bound": false,
|
||||
};
|
||||
|
@ -143,6 +143,7 @@ Core.prototype.init = async function() {
|
||||
Utils.suppressErrors(this.patchMessageHeader.bind(this), "BD Badge Chat Patch")();
|
||||
Utils.suppressErrors(this.patchMemberList.bind(this), "BD Badge Member List Patch")();
|
||||
Utils.suppressErrors(this.patchAttachment.bind(this), "LC Plugin Certifier Patch")();
|
||||
Utils.suppressErrors(this.patchPopoutWindow.bind(this), "BD Popout Window Patch")();
|
||||
|
||||
if(bdConfig.haveInstalledDefault){
|
||||
let alert = Utils.alert("First Installation", "As it is the first time you install Lightcord, We added two default themes and one default plugin in your plugin/theme folder. Check it in the Plugin/Theme settings.")
|
||||
@ -161,6 +162,48 @@ Core.prototype.init = async function() {
|
||||
}
|
||||
};
|
||||
|
||||
Core.prototype.patchPopoutWindow = async function() {
|
||||
let canceled = false
|
||||
this.cancelPatchPopoutWindow = () => {
|
||||
canceled = true
|
||||
}
|
||||
|
||||
window.Lightcord.Api.ensureExported(e => e.default && e.default.getWindow)
|
||||
.then(popoutModule => {
|
||||
if(canceled)return
|
||||
|
||||
// Not a good idea to do it like that.
|
||||
const interceptor = window.Lightcord.DiscordModules.dispatcher._interceptor
|
||||
window.Lightcord.DiscordModules.dispatcher.setInterceptor(function(action){
|
||||
if(action && action.type === "POPOUT_WINDOW_OPEN"){
|
||||
const render = action.render
|
||||
action.render = function(){
|
||||
const render1 = render.call(this, ...arguments)
|
||||
const type1 = render1.type
|
||||
render1.type = function(props){
|
||||
const render2 = type1(props)
|
||||
console.log(props, render2)
|
||||
return render2
|
||||
}
|
||||
console.log(render1)
|
||||
return render1
|
||||
}
|
||||
}
|
||||
return interceptor.call(this, action)
|
||||
})
|
||||
window.Lightcord.DiscordModules.dispatcher.subscribe("POPOUT_WINDOW_OPEN", (ev) => {
|
||||
if(!settingsCookie["lightcord-9"])return
|
||||
if(canceled)return
|
||||
Utils.log("POPOUT THEME", "Popout opened, Adding theme")
|
||||
setImmediate(() => {
|
||||
console.log(ev)
|
||||
const window = popoutModule.default.getWindow(ev.key)
|
||||
console.log(window)
|
||||
})
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
Core.prototype.patchAttributes = async function() {
|
||||
let attribsPatchs = []
|
||||
this.cancelPatchAttributes = function() {
|
||||
@ -171,7 +214,7 @@ Core.prototype.patchAttributes = async function() {
|
||||
|
||||
// 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")
|
||||
window.Lightcord.Api.ensureExported(e => e.default && e.default.displayName === "DiscordTag")
|
||||
.then(DiscordTag => {
|
||||
let DiscordTagComp = DiscordTag.default
|
||||
DiscordTag.default = function(props){
|
||||
@ -282,6 +325,7 @@ Core.prototype.initSettings = function () {
|
||||
settingModule.default.prototype.getPredicateSections = function(){
|
||||
let result = getPredicateSections.call(this, ...arguments)
|
||||
|
||||
if(!result[1])return result
|
||||
if(result[1].section === "My Account"){ // user settings, not guild settings
|
||||
let poped = []
|
||||
|
||||
|
@ -30,10 +30,13 @@ export default class ApiPreview extends React.PureComponent {
|
||||
<formModule.FormSection tag="h2" title="Lightcord's Api Availlable components">
|
||||
<formModule.FormText type="description" className="" selectable={false}>
|
||||
These components are here for the plugin devs. They can quickly embed any component below with this panel.
|
||||
<div style={{marginTop: "20px"}}></div>
|
||||
<Lightcord.Api.Components.general.AlertBox type="info">All these components have error handling. If you want none, add `.original` after the component path.</Lightcord.Api.Components.general.AlertBox>
|
||||
<Lightcord.Api.Components.general.AlertBox type="warn">We do not recommend modifying these component by a plugin. Only do this if you know what you are doing.</Lightcord.Api.Components.general.AlertBox>
|
||||
</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://lightcord.deroku.xyz/LightcordApi/docs")
|
||||
}} wrapper={false}>
|
||||
Documentation
|
||||
</Lightcord.Api.Components.inputs.Button>
|
||||
|
@ -572,7 +572,7 @@ class PresenceErrorCatcher extends React.Component {
|
||||
return this.render()
|
||||
}
|
||||
}else{
|
||||
emptyClasses = emptyClasses || BDV2.WebpackModules.find(e => e.emptyStateImage)
|
||||
emptyClasses = emptyClasses || BDV2.WebpackModules.find(e => e.emptyStateImage && e.emptyState)
|
||||
if(!emptyClasses){
|
||||
Utils.showToast("An error occured. Please check the console for more informations.")
|
||||
return null
|
||||
@ -584,7 +584,7 @@ class PresenceErrorCatcher extends React.Component {
|
||||
backgroundColor: "var(--background-primary)",
|
||||
padding: "30px 30px",
|
||||
borderRadius: "8px"
|
||||
}} className="lc-tab-box-shadow">
|
||||
}} className={`lc-tab-box-shadow ${emptyClasses.emptyState}`}>
|
||||
<div className={emptyClasses.emptyStateImage} style={{
|
||||
marginTop: "20px"
|
||||
}}>
|
||||
|
File diff suppressed because one or more lines are too long
2
LightcordApi/js/main.min.js
vendored
2
LightcordApi/js/main.min.js
vendored
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@
|
||||
"build-prod": "webpack --progress --colors --mode production -o js/main.min.js --devtool none",
|
||||
"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"
|
||||
"docs": "typedoc --out ../../LightcordApiDocs ./src"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
|
@ -1,2 +1,28 @@
|
||||
import { ReactDOMSelector } from "./selectors"
|
||||
|
||||
// bait typescript into thinking this is not reactDOM so no circular dependency.
|
||||
export = window["Reac"+"tDOM"] as typeof import("react-dom")
|
||||
window.ReactDOM = (window["Reac"+"tDOM"] || // If in Lightcord
|
||||
(()=>{ // If in Standard BetterDiscord
|
||||
try{
|
||||
return window.BdApi.findModule(ReactDOMSelector as any)
|
||||
}catch(e){
|
||||
return null
|
||||
}
|
||||
})() ||
|
||||
(()=>{ // If in Powercord
|
||||
try{
|
||||
const webpack = require("powercord/webpack")
|
||||
return webpack.ReactDOM
|
||||
}catch(e){
|
||||
return null
|
||||
}
|
||||
})() ||
|
||||
(()=>{ // If in EnhancedDiscord
|
||||
try{
|
||||
return window.EDApi.findModule(ReactDOMSelector as any)
|
||||
}catch(e){
|
||||
return null
|
||||
}
|
||||
})()) as typeof import("react-dom")
|
||||
|
||||
export = (window.ReactDOM as any)
|
@ -1 +1,27 @@
|
||||
import { ReactSelector } from "./selectors";
|
||||
|
||||
window.React = (window.React || // If in Lightcord
|
||||
(()=>{ // If in Standard BetterDiscord
|
||||
try{
|
||||
return window.BdApi.findModule(ReactSelector as any)
|
||||
}catch(e){
|
||||
return null
|
||||
}
|
||||
})() ||
|
||||
(()=>{ // If in Powercord
|
||||
try{
|
||||
const webpack = require("powercord/webpack")
|
||||
return webpack.React
|
||||
}catch(e){
|
||||
return null
|
||||
}
|
||||
})() ||
|
||||
(()=>{ // If in EnhancedDiscord
|
||||
try{
|
||||
return window.EDApi.findModule(ReactSelector as any)
|
||||
}catch(e){
|
||||
return null
|
||||
}
|
||||
})()) as typeof import("react")
|
||||
|
||||
export = window.React
|
2
LightcordApi/src/alias/selectors.ts
Normal file
2
LightcordApi/src/alias/selectors.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const ReactSelector = mod => !["Component", "PureComponent", "Children", "createElement", "cloneElement"].find(k => !mod[k])
|
||||
export const ReactDOMSelector = mod => mod.findDOMNode
|
@ -13,25 +13,27 @@ import cloneNullProto from "../modules/cloneNullProto"
|
||||
import Tooltip from "./general/Tooltip"
|
||||
import ColorPicker from "./inputs/ColorPicker"
|
||||
import AlertBox from "./general/AlertBox"
|
||||
import { createProxyErrorCatcherClass } from "./private/ErrorCatcher"
|
||||
|
||||
const RadioGroupProxied = createProxyErrorCatcherClass(RadioGroup)
|
||||
export default cloneNullProto({
|
||||
inputs: cloneNullProto({
|
||||
Button: DiscordButton,
|
||||
Switch: Switch,
|
||||
Choices: RadioGroup,
|
||||
RadioGroup: RadioGroup,
|
||||
TextArea: TextArea,
|
||||
TextInput: TextInput,
|
||||
Dropdown: Dropdown,
|
||||
ColorPicker: ColorPicker
|
||||
Button: createProxyErrorCatcherClass(DiscordButton),
|
||||
Switch: createProxyErrorCatcherClass(Switch),
|
||||
Choices: RadioGroupProxied,
|
||||
RadioGroup: RadioGroupProxied,
|
||||
TextArea: createProxyErrorCatcherClass(TextArea),
|
||||
TextInput: createProxyErrorCatcherClass(TextInput),
|
||||
Dropdown: createProxyErrorCatcherClass(Dropdown),
|
||||
ColorPicker: createProxyErrorCatcherClass(ColorPicker)
|
||||
}),
|
||||
general: cloneNullProto({
|
||||
Title: Title,
|
||||
SettingsTitle: SettingsTitle,
|
||||
SettingSubTitle: SettingSubTitle,
|
||||
Tabs: Tabs,
|
||||
CodeBlock: CodeBlock,
|
||||
Tooltip: Tooltip,
|
||||
AlertBox: AlertBox
|
||||
Title: createProxyErrorCatcherClass(Title),
|
||||
SettingsTitle: createProxyErrorCatcherClass(SettingsTitle),
|
||||
SettingSubTitle: createProxyErrorCatcherClass(SettingSubTitle),
|
||||
Tabs: createProxyErrorCatcherClass(Tabs),
|
||||
CodeBlock: createProxyErrorCatcherClass(CodeBlock),
|
||||
Tooltip: createProxyErrorCatcherClass(Tooltip),
|
||||
AlertBox: createProxyErrorCatcherClass(AlertBox)
|
||||
})
|
||||
})
|
@ -2,6 +2,7 @@ import NOOP from "../../modules/noop"
|
||||
import WebpackLoader from "../../modules/WebpackLoader"
|
||||
import Tooltip from "../general/Tooltip"
|
||||
import Utils from "../../modules/Utils"
|
||||
import { createProxyErrorCatcherClass } from "../private/ErrorCatcher"
|
||||
|
||||
const Constants = {
|
||||
defaultColor: 10070709,
|
||||
@ -57,9 +58,13 @@ export default class ColorPicker extends React.PureComponent<ColorPickerProps, {
|
||||
|
||||
/** Preload the component. */
|
||||
static preload(){
|
||||
if(ColorPicker.prototype.modules[0])return
|
||||
if(isFetching)return
|
||||
new ColorPicker({}).render()
|
||||
if(ColorPicker.prototype.modules[0])return // already loaded
|
||||
if(isFetching)return // is fetching so don't double preload.
|
||||
try{ // If we caught an error
|
||||
new ColorPicker({}).render()
|
||||
}catch(e){
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
onChange(val){
|
||||
@ -114,9 +119,10 @@ export default class ColorPicker extends React.PureComponent<ColorPickerProps, {
|
||||
return {
|
||||
id: null
|
||||
}
|
||||
}
|
||||
},
|
||||
renderHeader: GuildSettingsRoles.prototype.renderHeader
|
||||
})
|
||||
const GuildRoleSettings = settings.props.children.type
|
||||
const GuildRoleSettings = settings.props.children[1].type
|
||||
let children = GuildRoleSettings.prototype.renderColorPicker.call({
|
||||
props: {
|
||||
role: {
|
||||
@ -128,6 +134,7 @@ export default class ColorPicker extends React.PureComponent<ColorPickerProps, {
|
||||
}
|
||||
}).props.children
|
||||
children.type(children.props).props.children.type._ctor().then(c => {
|
||||
ColorPickerModules = null
|
||||
this.forceUpdate()
|
||||
resolve()
|
||||
})
|
||||
@ -175,7 +182,7 @@ export default class ColorPicker extends React.PureComponent<ColorPickerProps, {
|
||||
}
|
||||
|
||||
static help = {
|
||||
info: "To convert hex colors to decimal, you can do `Lightcord.Api.Utils.HexColorToDecimal('#yourcolor')` and go back with `Lightcord.Api.Utils.DecimalColorToHex(7506394)`",
|
||||
info: "To convert hex colors to decimal, you can do `Lightcord.Api.Utils.HexColorToDecimal('#7289DA')` and go back with `Lightcord.Api.Utils.DecimalColorToHex(7506394)`",
|
||||
warn: "The component may not appear instantly. The component needs to be loaded, so you could experience 50-300ms loading time depending on your internet connection."
|
||||
}
|
||||
}
|
||||
|
97
LightcordApi/src/components/private/ErrorCatcher.tsx
Normal file
97
LightcordApi/src/components/private/ErrorCatcher.tsx
Normal file
@ -0,0 +1,97 @@
|
||||
import { ReactNode } from "react";
|
||||
import WebpackLoader from "../../modules/WebpackLoader";
|
||||
import DiscordTools from "../../modules/DiscordTools";
|
||||
import NOOP from "../../modules/noop";
|
||||
import uuid from "../../modules/uuid";
|
||||
|
||||
|
||||
type ErrorCatcherProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
let ErrorCatcherModules
|
||||
export default class ErrorCatcher extends React.Component<ErrorCatcherProps, {error: boolean, hasSentNotification: boolean}> {
|
||||
constructor(props:ErrorCatcherProps){
|
||||
super(props)
|
||||
this.state = {
|
||||
error: false,
|
||||
hasSentNotification: false
|
||||
}
|
||||
}
|
||||
|
||||
get modules():any[]{
|
||||
return ErrorCatcherModules || (ErrorCatcherModules = [
|
||||
WebpackLoader.find(e => e.emptyStateImage && e.emptyState)
|
||||
])
|
||||
}
|
||||
|
||||
defaultProps:ErrorCatcherProps = {
|
||||
children: null
|
||||
}
|
||||
|
||||
render(){
|
||||
if(!this.state.error){
|
||||
return this.props.children
|
||||
}else{ // try to render a user-friendly interface.
|
||||
const [
|
||||
emptyClasses
|
||||
] = this.modules
|
||||
if(!emptyClasses){ // If we can't, render nothing and show a notification.
|
||||
if(this.state.hasSentNotification)return null // If the notification was already sent, don't send one.
|
||||
const notification = DiscordTools.showNotification({
|
||||
body: "An error occured. Please check the console for more informations.",
|
||||
icon: "https://github.com/lightcord.png",
|
||||
onClick: NOOP,
|
||||
onClose: NOOP,
|
||||
onShow: NOOP,
|
||||
title: "Lightcord Informations"
|
||||
})
|
||||
this.setState({
|
||||
hasSentNotification: true
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.close()
|
||||
}, 2000)
|
||||
return null
|
||||
}
|
||||
return <div className={emptyClasses.emptyState}>
|
||||
<div className={emptyClasses.emptyStateImage} style={{
|
||||
marginTop: "20px"
|
||||
}}></div>
|
||||
<div className={emptyClasses.emptyStateHeader}>An error occured</div>
|
||||
<p className={emptyClasses.emptyStateSubtext}>
|
||||
Please check the console for more informations. Join our support server for more help.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
componentDidCatch(error, errorInfo){
|
||||
console.error(errorInfo.componentStack)
|
||||
this.setState({
|
||||
error: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function createProxyErrorCatcherClass<base = Function>(Class:base):base & {
|
||||
readonly original: base
|
||||
}{
|
||||
const ClassCopy = (class Proxied extends React.Component {
|
||||
render(){
|
||||
return <ErrorCatcher key={uuid()}>
|
||||
{React.createElement(Class as any, {...this.props, key: uuid()})}
|
||||
</ErrorCatcher>
|
||||
}
|
||||
|
||||
static displayName = Class["displayName"] || Class["name"]
|
||||
|
||||
static get original(){
|
||||
return Class
|
||||
}
|
||||
}) as any
|
||||
Object.entries(Object.getOwnPropertyDescriptors(Class)).forEach(value => {
|
||||
if(value[0] in ClassCopy)return
|
||||
Object.defineProperty(ClassCopy, value[0], value[1])
|
||||
})
|
||||
return ClassCopy
|
||||
}
|
@ -8,6 +8,8 @@ import excludeProperties from "./modules/excludeProperties"
|
||||
import cloneNullProto from "./modules/cloneNullProto"
|
||||
import NOOP from "./modules/noop"
|
||||
import unfreeze from "./modules/Unfreeze"
|
||||
import { isNative, isImported } from "./modules/environnement"
|
||||
import * as bandagedbdApi from "@bandagedbd/bdapi"
|
||||
patchers.patch()
|
||||
|
||||
const LightcordApi = {
|
||||
@ -21,19 +23,29 @@ const LightcordApi = {
|
||||
cloneNullProto: cloneNullProto,
|
||||
NOOP: NOOP,
|
||||
unfreeze: unfreeze
|
||||
}
|
||||
},
|
||||
get isNative(){return isNative},
|
||||
get isImported(){return isImported}
|
||||
}
|
||||
|
||||
declare global {
|
||||
var React:typeof import("react")
|
||||
interface Window {
|
||||
/**
|
||||
* Lightcord is only availlaible in Lightcord (native)
|
||||
*/
|
||||
Lightcord: LightcordGlobal,
|
||||
/**
|
||||
* BDModules is only availlaible in Lightcord (native)
|
||||
*/
|
||||
BDModules: {
|
||||
modules:any[],
|
||||
get(filter:(mod:any)=>boolean, modules?:any[]):any[],
|
||||
get(id:number, modules?:any[]):any,
|
||||
get(ids: [number|((mod:any)=>boolean)], modules?:any[]):any
|
||||
}
|
||||
},
|
||||
BdApi: typeof bandagedbdApi.BdApi,
|
||||
EDApi: typeof bandagedbdApi.BdApi
|
||||
}
|
||||
var Lightcord:LightcordGlobal
|
||||
}
|
||||
@ -59,7 +71,7 @@ export interface LightcordGlobal {
|
||||
},
|
||||
Api: LightcordApiGlobal,
|
||||
BetterDiscord: {
|
||||
BdApi: typeof import("@bandagedbd/bdapi").BdApi,
|
||||
BdApi: typeof bandagedbdApi.BdApi,
|
||||
[mod:string]:any
|
||||
}
|
||||
}
|
||||
|
82
LightcordApi/src/modules/BDModules.ts
Normal file
82
LightcordApi/src/modules/BDModules.ts
Normal file
@ -0,0 +1,82 @@
|
||||
let req
|
||||
setReq()
|
||||
function filterDangerous(mods){
|
||||
return mods.map(e => {
|
||||
return protect(e)
|
||||
})
|
||||
}
|
||||
function protect(exports){
|
||||
let theModule = exports.exports
|
||||
let mod = theModule.default
|
||||
if(!mod)return exports
|
||||
if (mod.remove && mod.set && mod.clear && mod.get && !mod.sort) return null;
|
||||
if (!mod.getToken && !mod.getEmail && !mod.showToken)return exports
|
||||
|
||||
const proxy = new Proxy(mod, {
|
||||
getOwnPropertyDescriptor: function(obj, prop) {
|
||||
if (prop === "getToken" || prop === "getEmail" || prop === "showToken") return undefined;
|
||||
return Object.getOwnPropertyDescriptor(obj, prop);
|
||||
},
|
||||
get: function(obj, func) {
|
||||
if (func == "getToken" && obj.getToken) return () => "mfa.XCnbKzo0CLIqdJzBnL0D8PfDruqkJNHjwHXtr39UU3F8hHx43jojISyi5jdjO52e9_e9MjmafZFFpc-seOMa";
|
||||
if (func == "getEmail" && obj.getEmail) return () => "puppet11112@gmail.com";
|
||||
if (func == "showToken" && obj.showToken) return () => true;
|
||||
if (func == "__proto__" && obj.__proto__) return proxy;
|
||||
|
||||
return obj[func];
|
||||
}
|
||||
});
|
||||
|
||||
return Object.assign({}, exports, {exports: Object.assign({}, theModule, {default: proxy})})
|
||||
}
|
||||
|
||||
class Webpackloader {
|
||||
get modules(){
|
||||
if(req){
|
||||
return filterDangerous(Object.values(req.c).filter((e:any) => e && e.exports))
|
||||
}else{
|
||||
setReq()
|
||||
if(req){
|
||||
return filterDangerous(Object.values(req.c).filter((e:any) => e && e.exports))
|
||||
}else{
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
get(ids, modules){
|
||||
if(typeof ids === "function"){
|
||||
return (modules || this.modules).map((mdl) => {
|
||||
if(mdl && typeof mdl.exports !== "undefined"){
|
||||
return mdl.exports
|
||||
}else{
|
||||
return null
|
||||
}
|
||||
}).filter(e => e).filter(ids)
|
||||
}else if(Array.isArray(ids)){
|
||||
modules = modules || this.modules
|
||||
return ids.map(id => this.get(id, modules))
|
||||
}else{
|
||||
modules = modules || this.modules
|
||||
let module = modules.filter(e => !!e).find(e => e.i === ids)
|
||||
if(!module)return undefined
|
||||
return module.exports
|
||||
}
|
||||
}
|
||||
get default(){
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
export default new Webpackloader()
|
||||
|
||||
function setReq(){
|
||||
try{
|
||||
req = window["webpackJsonp"].push([[], {__extra_id__: (mdl, exports, req) => mdl.exports = req}, [["__extra_id__"]]]);
|
||||
if(req){
|
||||
delete req.m.__extra_id__;
|
||||
delete req.c.__extra_id__;
|
||||
}
|
||||
}catch(e){
|
||||
req = undefined
|
||||
}
|
||||
}
|
@ -152,6 +152,8 @@ export class Notice extends EventEmitter {
|
||||
index:number
|
||||
}
|
||||
|
||||
private nextTickRefresh:boolean = false
|
||||
|
||||
get removed():boolean{
|
||||
return !notices.find(e => e.id === this.id)
|
||||
}
|
||||
@ -166,36 +168,55 @@ export class Notice extends EventEmitter {
|
||||
return this.data.id
|
||||
}
|
||||
|
||||
update(data: Partial<notice>){
|
||||
for(let key in data){
|
||||
if(key === "id")continue
|
||||
this.data[key] = data[key]
|
||||
}
|
||||
|
||||
if(!this.nextTickRefresh){
|
||||
this.nextTickRefresh = true
|
||||
process.nextTick(() => {
|
||||
this.nextTickRefresh = false
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
get text(){
|
||||
return this.data.text
|
||||
}
|
||||
set text(text){
|
||||
this.data.text = text
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
this.update({
|
||||
text
|
||||
})
|
||||
}
|
||||
|
||||
get type(){
|
||||
return this.data.type
|
||||
}
|
||||
set type(type){
|
||||
this.data.type = type
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
this.update({
|
||||
type
|
||||
})
|
||||
}
|
||||
|
||||
get buttonText(){
|
||||
return this.data.buttonText
|
||||
}
|
||||
set buttonText(buttonText:string){
|
||||
this.data.buttonText = buttonText
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
this.update({
|
||||
buttonText
|
||||
})
|
||||
}
|
||||
|
||||
get onClick(){
|
||||
return this.data.onClick
|
||||
}
|
||||
set onClick(onClick){
|
||||
this.data.onClick = onClick
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
this.update({
|
||||
onClick
|
||||
})
|
||||
}
|
||||
|
||||
remove(){
|
||||
|
@ -1,4 +1,4 @@
|
||||
const BDModules = window.BDModules
|
||||
const BDModules:typeof window.BDModules = window.BDModules || require("./BDModules")
|
||||
|
||||
export default new class WebpackLoader {
|
||||
constructor(){}
|
||||
@ -50,7 +50,7 @@ export default new class WebpackLoader {
|
||||
|
||||
export class WebpackLoaderError extends Error {
|
||||
constructor(message:string = ""){
|
||||
message += "\n\tThis error is related to Lightcord not being able to find a WebpackModule. \n\tPlease show this error and a few lines of logs above this error. \n\tOpen an issue on https://github.com/Lightcord/Lightcord or in their discord server."
|
||||
message += "\n\tThis error is related to Lightcord not being able to find a WebpackModule. \n\tPlease show this error and a few lines of logs above this error to the devs. \n\tOpen an issue on https://github.com/Lightcord/Lightcord or in our discord server."
|
||||
super(message)
|
||||
this.name = "WebpackLoaderError"
|
||||
}
|
||||
|
2
LightcordApi/src/modules/environnement.ts
Normal file
2
LightcordApi/src/modules/environnement.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const isNative:boolean = typeof window.BDModules === "undefined"
|
||||
export const isImported:boolean = typeof window.BDModules !== "undefined"
|
0
LightcordApi/src/modules/lazyLoader.ts
Normal file
0
LightcordApi/src/modules/lazyLoader.ts
Normal file
@ -1,5 +1,6 @@
|
||||
import Utils from "./Utils"
|
||||
import Notices, { notices } from "../components/private/Notices"
|
||||
import { isNative } from "./environnement";
|
||||
|
||||
export function patch(){
|
||||
/** START NOTICE */
|
||||
@ -47,6 +48,62 @@ export function patch(){
|
||||
})
|
||||
/** END NOTICE */
|
||||
|
||||
if(isNative){
|
||||
/** START USERPOPOUT PATCH */
|
||||
awaitLogin()
|
||||
.then(async () => {
|
||||
let UserPopout = await getModule(e => e.default && e.default.displayName === "FluxContainer(ForwardRef(SubscribeGuildMembersContainer(UserPopout)))")
|
||||
const userModule = await getModule(e => e.default && e.default.getCurrentUser)
|
||||
const render1 = new UserPopout.default({userId: userModule.default.getCurrentUser().id, guildId: null, channelId: null, disableUserProfileLink: true}).render()
|
||||
const PopoutProps = render1.props
|
||||
const render2 = render1.type.render(PopoutProps, null)
|
||||
const render3 = new render2.type(render2.props).render()
|
||||
const UserPopoutComponent = render3.type
|
||||
if(!UserPopoutComponent)throw new Error(`Couldn't find the UserPopoutComponent component.`)
|
||||
|
||||
const render = UserPopoutComponent.prototype.render
|
||||
UserPopoutComponent.prototype.render = function(){
|
||||
const returnValue = render.call(this, ...arguments)
|
||||
try{
|
||||
returnValue.props.children.props["data-user-id"] = this.props.user.id
|
||||
}catch(e){
|
||||
console.error(e)
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
})
|
||||
/** END USERPOPOUT PATCH*/
|
||||
|
||||
/** START USERPROFILE PATCH */
|
||||
awaitLogin()
|
||||
.then(async () => {
|
||||
let UserProfile = await getModule(e => e.default && e.default.displayName === "UserProfile")
|
||||
const userModule = await getModule(e => e.default && e.default.getCurrentUser)
|
||||
const render1 = new UserProfile.default({
|
||||
user: userModule.default.getCurrentUser()
|
||||
}).render()
|
||||
const render2 = new render1.type(render1.props).render()
|
||||
const render3 = render2.type.render(render2.props, null)
|
||||
const render4 = new render3.type(render3.props).render()
|
||||
const UserProfileComponent = render4.type
|
||||
if(!UserProfileComponent)throw new Error(`Couldn't find the UserProfileComponent component.`)
|
||||
|
||||
const render = UserProfileComponent.prototype.render
|
||||
UserProfileComponent.prototype.render = function(){
|
||||
const returnValue = render.call(this, ...arguments)
|
||||
console.log(returnValue)
|
||||
try{
|
||||
returnValue.props.children.props["data-user-id"] = this.props.user.id
|
||||
}catch(e){
|
||||
console.error(e)
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
})
|
||||
/** END USERPROFILE PATCH */
|
||||
}
|
||||
|
||||
// TODO: Add in app-notifications / confirmations.
|
||||
/** START IN-APP NOTIFICATIONS */
|
||||
//getModule(e => true)
|
||||
/** END IN-APP NOTIFICATIONS */
|
||||
@ -61,3 +118,24 @@ function getModule(filter: (mod:any) => boolean):Promise<any>{
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
let hasCompletedLogin = false
|
||||
let loginPromise:Promise<void>
|
||||
function awaitLogin():Promise<void>{
|
||||
if(hasCompletedLogin)return Promise.resolve()
|
||||
if(loginPromise)return loginPromise
|
||||
|
||||
return loginPromise = new Promise((resolve) => {
|
||||
let isResolved = false
|
||||
window.Lightcord.DiscordModules.dispatcher.subscribe("CONNECTION_OPEN", (ev) => {
|
||||
if(isResolved)return
|
||||
hasCompletedLogin = true
|
||||
resolve()
|
||||
isResolved = true
|
||||
})
|
||||
})
|
||||
}
|
||||
window.Lightcord.DiscordModules.dispatcher.subscribe("LOGOUT", (ev) => {
|
||||
hasCompletedLogin = false
|
||||
loginPromise = undefined
|
||||
})
|
@ -23,7 +23,8 @@ module.exports = {
|
||||
request: `request`,
|
||||
"node-fetch": "node-fetch",
|
||||
"uuid/v1": "uuid/v1",
|
||||
"uuid/v4": "uuid/v4"
|
||||
"uuid/v4": "uuid/v4",
|
||||
"powercord/webpack": "powercord/webpack"
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".js", ".jsx", ".json", ".ts", ".tsx"],
|
||||
|
@ -48,7 +48,7 @@ async function privateInit(){
|
||||
ModuleLoader.get(e => e.getCurrentHub)[0].getCurrentHub().getClient().getOptions().enabled = false
|
||||
|
||||
// setting react in require cache
|
||||
const React = ModuleLoader.get(e => !["Component", "PureComponent", "Children", "createElement", "cloneElement"].map(c => !!e[c]).includes(false))[0]
|
||||
const React = ModuleLoader.get(e => !["Component", "PureComponent", "Children", "createElement", "cloneElement"].find(k => !e[k]))[0]
|
||||
window.React = React
|
||||
|
||||
const ReactDOM = ModuleLoader.get(e => e.findDOMNode)[0]
|
||||
@ -278,7 +278,7 @@ async function privateInit(){
|
||||
DiscordNative.ipc.send("UPDATE_THEME", data.settings.theme)
|
||||
})
|
||||
|
||||
require("lightcordapi/js/main.js")
|
||||
require("lightcordapi/js/main.min.js")
|
||||
|
||||
/*
|
||||
if(shouldShowPrompt){
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 22 KiB |
3
modules/discord_desktop_core/core/app/popoutPreload.js
Normal file
3
modules/discord_desktop_core/core/app/popoutPreload.js
Normal file
@ -0,0 +1,3 @@
|
||||
process.once('loaded', () => {
|
||||
console.log("sltsv")
|
||||
})
|
@ -14,9 +14,11 @@ var _electron = require('electron');
|
||||
var _appFeatures = require('./appFeatures');
|
||||
|
||||
var _mainScreen = require('./mainScreen');
|
||||
const { join } = require('path');
|
||||
|
||||
const MIN_POPOUT_WIDTH = 320;
|
||||
const MIN_POPOUT_HEIGHT = 180;
|
||||
/** @type {Electron.BrowserWindowConstructorOptions} */
|
||||
const DEFAULT_POPOUT_OPTIONS = {
|
||||
title: 'Lightcord Popout',
|
||||
backgroundColor: '#2f3136',
|
||||
@ -29,7 +31,8 @@ const DEFAULT_POPOUT_OPTIONS = {
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
nativeWindowOpen: true
|
||||
}
|
||||
},
|
||||
icon: join(__dirname, 'discord.png')
|
||||
};
|
||||
const features = (0, _appFeatures.getFeatures)();
|
||||
|
||||
|
@ -13,8 +13,8 @@
|
||||
"build:electron_linux": "electron-packager ./distApp --ignore=\"(distApp|builds|\\.ts|\\.dll)\" --arch=x64 --protocol=discord --platform=\"linux\" --out=builds --icon=app.ico --executable-name=\"Lightcord\" --asar.unpack=*.{node,so.4} --overwrite",
|
||||
"build:minify": "node build.js",
|
||||
"build:after": "node afterbuild.js",
|
||||
"devInstall": "npm i -g --arch=ia32 electron@8.4.0 && npm i -g typescript && npm i --save-dev @types/node@12.12.39 && npm i --save-dev --arch=ia32 electron@8.4.0 && node installSubModules.js && echo \"Everything is installed. You should be able to do `npm run test` to compile everything and launch.\"",
|
||||
"devInstall:64": "npm i -g --arch=x64 electron@8.4.0 && npm i -g typescript && npm i --save-dev @types/node@12.12.39 && npm i --save-dev --arch=x64 electron@8.4.0 && node installSubModules.js && echo \"Everything is installed. You should be able to do `npm run test` to compile everything and launch.\""
|
||||
"devInstall": "npm i --save-dev --arch=ia32 electron@8.4.0 && node installSubModules.js && echo \"Everything is installed. You should be able to do `npm run test` to compile everything and launch.\"",
|
||||
"devInstall:64": "npm i --save-dev --arch=x64 electron@8.4.0 && node installSubModules.js && echo \"Everything is installed. You should be able to do `npm run test` to compile everything and launch.\""
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
@ -34,7 +34,7 @@
|
||||
"@types/auto-launch": "^5.0.1",
|
||||
"@types/electron-devtools-installer": "^2.2.0",
|
||||
"@types/mkdirp": "^1.0.0",
|
||||
"@types/node": "^12.12.39",
|
||||
"@types/node": "12.12.39",
|
||||
"@types/rimraf": "^3.0.0",
|
||||
"@types/uuid": "^8.0.0",
|
||||
"@types/yauzl": "^2.9.1",
|
||||
|
Loading…
x
Reference in New Issue
Block a user