RichPresence fix

Light theme semi-fix
LightcordApi update
This commit is contained in:
Jean Ouina 2020-07-17 14:54:49 +02:00
parent c96f94b314
commit 7ec315a11f
29 changed files with 1490 additions and 986 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2015-present Jiiks | 2017-present Zack Rauen
Copyright (c) 2015-present Jiiks | 2017-present Zack Rauen | 2020-present Lightcord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -952,20 +952,13 @@ body .ace_closeButton:active {
justify-content: space-between;
}
.theme-dark .ui-tab-bar-header .bd-changelog-button {
color: #72767d;
}
.theme-light .ui-tab-bar-header .bd-changelog-button {
color: #b9bbbe;
}
.ui-tab-bar-header .bd-icon {
cursor: pointer;
fill: #72767d;
fill: var(--text-muted);
}
.ui-tab-bar-header .bd-icon:hover {
fill: #fff;
fill: var(--text-normal);
}
.ui-tab-bar-separator {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,6 @@
/* BDEvents */
const EventEmitter = require("events");
export default new class BDEvents extends EventEmitter {
constructor(){
super()

View File

@ -95,10 +95,10 @@ ThemeModule.prototype.unloadTheme = function(filenameOrName) {
};
ThemeModule.prototype.delete = function(filenameOrName) {
const bdplugin = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
if (!bdplugin) return;
this.unloadTheme(bdplugin.filename);
const fullPath = require("path").resolve(ContentManager.pluginsFolder, bdplugin.filename);
const bdtheme = Object.values(bdthemes).find(p => p.filename == filenameOrName) || bdthemes[filenameOrName];
if (!bdtheme) return;
this.unloadTheme(bdtheme.filename);
const fullPath = require("path").resolve(ContentManager.themesFolder, bdtheme.filename);
require("fs").unlinkSync(fullPath);
};

View File

@ -1,9 +1,7 @@
import ErrorBoundary from "./errorBoundary";
import ContentColumn from "./contentColumn";
import Tools from "./tools";
import ReloadIcon from "./reloadIcon";
import AddonCard from "./addoncard";
import Scroller from "./scroller";
import Dropdown from "./components/dropdown";
import Search from "./components/search";
@ -15,7 +13,8 @@ import themeModule from "../modules/themeModule";
import WebpackModules from "../modules/webpackModules";
import BdApi from "../modules/bdApi";
import Utils from "../modules/utils";
import tooltipWrap from "./tooltipWrap";
import TooltipWrap from "./tooltipWrap";
import bdEvents from "../modules/bdEvents";
const Tooltip = WebpackModules.findByDisplayName("Tooltip");
@ -32,6 +31,25 @@ export default class CardList extends BDV2.reactComponent {
this.sort = this.sort.bind(this);
this.reverse = this.reverse.bind(this);
this.search = this.search.bind(this);
this.onAddonChanges = function(){
this.forceUpdate()
}
this.onAddonChanges = this.onAddonChanges.bind(this)
}
componentDidMount(){
const type = (this.isPlugins ? "plugin" : "theme") + "-"
bdEvents.on(`${type}loaded`, this.onAddonChanges)
bdEvents.on(`${type}unloaded`, this.onAddonChanges)
bdEvents.on(`${type}reloaded`, this.onAddonChanges)
}
componentWillUnmount(){
const type = (this.isPlugins ? "plugin" : "theme") + "-"
bdEvents.off(`${type}loaded`, this.onAddonChanges)
bdEvents.off(`${type}unloaded`, this.onAddonChanges)
bdEvents.off(`${type}reloaded`, this.onAddonChanges)
}
openFolder() {
@ -154,7 +172,7 @@ export default class CardList extends BDV2.reactComponent {
if(typeof window.PluginUpdates.checkAll !== "function")return null
if(!this.isPlugins)return null
return <tooltipWrap text="Checks for updates of plugins that support this feature. Right-click for a list.">
return <TooltipWrap text="Checks for updates of plugins that support this feature. Right-click for a list.">
<span style={{marginLeft: "10px"}}>
<Lightcord.Api.Components.inputs.Button color="brand" look="filled" size="min" hoverColor="default" onClick={() => {
try{
@ -174,7 +192,7 @@ export default class CardList extends BDV2.reactComponent {
Check for Updates
</Lightcord.Api.Components.inputs.Button>
</span>
</tooltipWrap>
</TooltipWrap>
}
render() {

View File

@ -5,7 +5,7 @@ const React = BDV2.React;
export default class Delete extends React.Component {
render() {
const size = this.props.size || "24px";
return <svg className={this.props.className || ""} fill="#FFFFFF" viewBox="0 0 24 24" style={{width: size, height: size}} onClick={this.props.onClick}>
return <svg className={this.props.className || ""} fill="var(--text-normal)" viewBox="0 0 24 24" style={{width: size, height: size}} onClick={this.props.onClick}>
<path fill="none" d="M0 0h24v24H0V0z"/><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/>
<path fill="none" d="M0 0h24v24H0z"/>
</svg>;

View File

@ -5,7 +5,7 @@ const React = BDV2.React;
export default class DownArrow extends React.Component {
render() {
const size = this.props.size || "16px";
return <svg className={this.props.className || ""} fill="#FFFFFF" viewBox="0 0 24 24" style={{width: size, height: size}}>
return <svg className={this.props.className || ""} fill="var(--text-normal)" viewBox="0 0 24 24" style={{width: size, height: size}}>
<path d="M8.12 9.29L12 13.17l3.88-3.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-4.59 4.59c-.39.39-1.02.39-1.41 0L6.7 10.7c-.39-.39-.39-1.02 0-1.41.39-.38 1.03-.39 1.42 0z"/>
</svg>;
}

View File

@ -5,7 +5,7 @@ const React = BDV2.React;
export default class Edit extends React.Component {
render() {
const size = this.props.size || "24px";
return <svg className={this.props.className || ""} viewBox="0 0 24 24" fill="#FFFFFF" style={{width: size, height: size}} onClick={this.props.onClick}>
return <svg className={this.props.className || ""} viewBox="0 0 24 24" fill="var(--text-normal)" style={{width: size, height: size}} onClick={this.props.onClick}>
<path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
<path d="M0 0h24v24H0z" fill="none" />
</svg>;

View File

@ -10,9 +10,9 @@ const React = BDV2.React;
export default class History extends React.Component {
render() {
const size = this.props.size || "18px";
return <svg viewBox="0 0 24 24" fill="#FFFFFF" className={this.props.className || ""} style={{width: size, height: size}} onClick={this.props.onClick}>
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/>
</svg>;
return <svg viewBox="0 0 24 24" fill="var(--text-normal)" className={this.props.className || ""} style={{width: size, height: size}} onClick={this.props.onClick}>
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/>
</svg>;
}
}

View File

@ -5,7 +5,7 @@ const React = BDV2.React;
export default class Search extends React.Component {
render() {
const size = this.props.size || "16px";
return <svg className={this.props.className || ""} fill="#FFFFFF" viewBox="0 0 24 24" style={{width: size, height: size}}>
return <svg className={this.props.className || ""} fill="var(--text-normal)" viewBox="0 0 24 24" style={{width: size, height: size}}>
<path fill="none" d="M0 0h24v24H0V0z"/>
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
</svg>;

View File

@ -7,7 +7,8 @@ import CustomRichPresence from "../modules/CustomRichPresence"
import timestampRender from "./timestampRender"
import { remote } from "electron";
import MarginTop from "./margintop";
import Utils from "../modules/utils";
import { uuidv4 } from "../modules/distant";
const React = BDV2.React;
@ -496,16 +497,12 @@ class RpcPreview extends React.Component {
}
render(){
let preview = new this.preview({
preview: this
})
preview.setState(this.state.rpc)
return (<div className="lc-tabWrapper">
<div className="lc-tabnav" style={{flex: "0 1 auto"}}>
<Tab preview={this} title="Full Profile" id="profile"/>
<Tab preview={this} title="User Popout" id="popout"/>
</div>
{preview.render()}
<PresenceErrorCatcher preview={this.preview} state={this.state.rpc} props={{preview: this}} key={this.state.active} />
</div>)
}
@ -550,6 +547,204 @@ class Tab extends React.Component {
}
}
let emptyClasses
class PresenceErrorCatcher extends React.Component {
componentDidCatch(err, errInfo){
console.error(err, errInfo)
this.setState({
error: true
})
}
render(){
if(!this.state){
this.state = {
error: false
}
}
if(!this.state.error){
try{
const preview = new this.props.preview(this.props.props)
preview.setState(this.props.state)
return preview.render()
}catch(err){
console.error(err)
this.state.error = true
return this.render()
}
}else{
emptyClasses = emptyClasses || BDV2.WebpackModules.find(e => e.emptyStateImage)
if(!emptyClasses){
Utils.showToast("An error occured. Please check the console for more informations.")
return null
}
return <div style={{
margin: "20px"
}}>
<div style={{
backgroundColor: "var(--background-primary)",
padding: "30px 30px",
borderRadius: "8px"
}} className="lc-tab-box-shadow">
<div className={emptyClasses.emptyStateImage} style={{
marginTop: "20px"
}}>
</div>
<div className={emptyClasses.emptyStateHeader}>An error occured</div>
<p className={emptyClasses.emptyStateSubtext}>
Please check the console for more informations. Join our ­
<a className={`${BDV2.anchorClasses.anchor} ${BDV2.anchorClasses.anchorUnderlineOnHover}`} role="button" tabindex={0} onClick={() => {
BDV2.joinLC()
}}>
support server
</a>
­ for help.
</p>
</div>
</div>
}
}
}
let popoutModules
let UserPopoutComponent
let PopoutProps
class Popout extends React.Component {
get modules(){
return popoutModules || (popoutModules = [
BDV2.WebpackModules.find(e => e.default && e.default.displayName === "FluxContainer(ForwardRef(SubscribeGuildMembersContainer(UserPopout)))"),
BDV2.WebpackModules.find(e => e.default && e.default.getCurrentUser)
])
}
render(){
let [
UserPopout,
userModule
] = this.modules
const user = userModule.default.getCurrentUser()
if(!UserPopoutComponent){
if(!UserPopout)throw new Error(`Couldn't find the UserPopout component.`)
const render1 = new UserPopout.default({userId: user.id, guildId: null, channelId: null, disableUserProfileLink: true}).render()
PopoutProps = render1.props
const render2 = render1.type.render(PopoutProps, null)
const render3 = new render2.type(render2.props).render()
UserPopoutComponent = render3.type
}
if(!UserPopoutComponent)throw new Error(`Couldn't find the UserPopoutComponent component.`)
let data = Object.assign({}, defaultRPC, this.props.preview.props.settings.state.data)
const activity = (function(){
if(!this.game)return null
let game = {
name: this.game.name || defaultRPC.name,
application_id: this.game.application_id || defaultRPC.application_id,
details: this.game.details || undefined,
state: this.game.state || undefined,
timestamps: this.game["timestamps.start"] ? {
start: this.game["timestamps.start"]
} : undefined,
assets: this.game["assets.large"] ? {
large_image: this.game["assets.large"],
small_image: this.game["assets.small"] || undefined
} : undefined,
type: 0
}
return game
}).call({
game: data
})
PopoutProps = new UserPopout.default({userId: user.id, guildId: null, channelId: null, disableUserProfileLink: true}).render().props
const popout = new UserPopoutComponent(Object.assign({}, PopoutProps, {
activity: activity
})).render().props.children // bypass tracking
// remove the stop propagation shit.
const container = <div {...window.Lightcord.Api._.excludeProperties(popout.props, ["onClick", "onContextMenu"])} />
return <div className="lc-userPopout lc-tab-box-shadow">
{container}
</div>
}
}
let profileModules
let UserProfileComponent
let ProfileProps
let connectedProfileStore
class Profile extends React.Component {
get modules(){
return profileModules || (profileModules = [
BDV2.WebpackModules.find(e => e.default && e.default.displayName === "UserProfile"),
BDV2.WebpackModules.find(e => e.default && e.default.getCurrentUser)
])
}
render(){
let [
UserProfile,
userModule
] = this.modules
const user = userModule.default.getCurrentUser()
if(!UserProfileComponent){
const render1 = new UserProfile.default({
user: user
}).render()
connectedProfileStore = render1.type
const render2 = new render1.type(render1.props).render()
const render3 = render2.type.render(render2.props, null)
const render4 = new render3.type(render3.props).render()
UserProfileComponent = render4.type
}
if(!UserProfileComponent)throw new Error(`Couldn't find the UserProfileComponent component.`)
let data = Object.assign({}, defaultRPC, this.props.preview.props.settings.state.data)
const activity = (function(){
if(!this.game)return null
let game = {
name: this.game.name || defaultRPC.name,
application_id: this.game.application_id || defaultRPC.application_id,
details: this.game.details || undefined,
state: this.game.state || undefined,
timestamps: this.game["timestamps.start"] ? {
start: this.game["timestamps.start"]
} : undefined,
assets: this.game["assets.large"] ? {
large_image: this.game["assets.large"],
small_image: this.game["assets.small"] || undefined
} : undefined,
type: 0
}
return game
}).call({
game: data
})
ProfileProps = new connectedProfileStore({
user: user,
close: () => {}
}).render().props
const profile = new UserProfileComponent(Object.assign({}, ProfileProps, {
activity: activity
})).render().props.children // bypass tracking
console.log(profile)
profile.props.style = {
width: "auto"
}
return <div className="lc-tab lc-tab-box-shadow">
{profile}
</div>
}
}
/*
let popoutModule
class Popout extends React.Component { // TODO: Probably use internal Components instead of making it from scratch.
get modules(){
@ -979,4 +1174,4 @@ class Timestamp extends React.Component {
{this.props.message}
</div>
}
}
}*/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -176,7 +176,7 @@ export default class ColorPicker extends React.PureComponent<ColorPickerProps, {
static help = {
info: "To convert hex colors to decimal, you can do `Lightcord.Api.Utils.HexColorToDecimal('#yourcolor')` and go back with `Lightcord.Api.Utils.DecimalColorToHex(7506394)`",
warn: "The component may not appear instantly. The component need to be loaded, so you could experience 50-300ms loading time depending on your internet connection."
warn: "The component may not appear instantly. The component needs to be loaded, so you could experience 50-300ms loading time depending on your internet connection."
}
}
let AllPreviews

View File

@ -4,6 +4,10 @@ import uuid from "./modules/uuid"
import Utils from "./modules/Utils"
import DiscordTools from "./modules/DiscordTools"
import * as patchers from "./modules/patchers"
import excludeProperties from "./modules/excludeProperties"
import cloneNullProto from "./modules/cloneNullProto"
import NOOP from "./modules/noop"
import unfreeze from "./modules/Unfreeze"
patchers.patch()
const LightcordApi = {
@ -11,7 +15,13 @@ const LightcordApi = {
Components: Components,
uuid: uuid,
Utils: Utils,
DiscordTools: DiscordTools
DiscordTools: DiscordTools,
_: {
excludeProperties: excludeProperties,
cloneNullProto: cloneNullProto,
NOOP: NOOP,
unfreeze: unfreeze
}
}
declare global {
@ -47,7 +57,11 @@ export interface LightcordGlobal {
devMode: boolean,
callRingingBeat: boolean
},
Api: LightcordApiGlobal
Api: LightcordApiGlobal,
BetterDiscord: {
BdApi: typeof import("@bandagedbd/bdapi").BdApi,
[mod:string]:any
}
}
/**

View File

@ -43,10 +43,15 @@ export default new class DiscordTools {
return notification
}
playSound(sound:Sound){
createSound(sound:Sound){
soundModule = soundModule || WebpackLoader.findByUniqueProperties(["createSound"])
if(!soundModule)throw new WebpackLoaderError("Couldn't find soundModule here.")
const created = soundModule.createSound(sound)
return created
}
playSound(sound:Sound){
const created = this.createSound(sound)
created.play()
return created
}
@ -102,6 +107,45 @@ export class Notice extends EventEmitter {
})
}
/**
* Will be called whem the notice is removed.
*/
on(event: "removed", listener: () => void):this
/**
* Will be called when the notice is visible or not.
*/
on(event: "showing", listener: (isShowing:boolean) => void):this
/**
* Will be called when the notice queue changes.
*/
on(event: "index", listener: (index:number) => void):this
on(event: string, listener: (...args:any[]) => void){
return super.on(event, listener)
}
/**
* Will be called whem the notice is removed.
*/
once(event: "removed", listener: () => void):this
/**
* Will be called when the notice is visible or not.
*/
once(event: "showing", listener: (isShowing:boolean) => void):this
/**
* Will be called when the notice queue changes.
*/
once(event: "index", listener: (index:number) => void):this
once(event: string, listener: (...args:any[]) => void){
return super.once(event, listener)
}
off(event: "removed", listener: () => void):this
off(event: "showing", listener: (isShowing:boolean) => void):this
off(event: "index", listener: (index:number) => void):this
off(event: string, listener: (...args:any[]) => void){
return super.off(event, listener)
}
state:{
removed:boolean,
showing:boolean,

View File

@ -38,7 +38,7 @@ export default new class Utils {
}
FindReact(dom:Element, traverseUp:number = 0):React.Component|React.PureComponent{
/** took from https://stackoverflow.com/questions/29321742/react-getting-a-component-from-a-dom-element-for-debugging */
// taken from https://stackoverflow.com/questions/29321742/react-getting-a-component-from-a-dom-element-for-debugging#39165137
const key = Object.keys(dom).find(key=>key.startsWith("__reactInternalInstance$"));
const domFiber = dom[key];
if (domFiber == null) return null;

View File

@ -47,7 +47,9 @@ export function patch(){
})
/** END NOTICE */
/** START IN-APP NOTIFICATIONS */
//getModule(e => true)
/** END IN-APP NOTIFICATIONS */
}
function getModule(filter: (mod:any) => boolean):Promise<any>{

View File

@ -3,7 +3,7 @@ const path = require("path")
const terser = require("terser")
const util = require("util")
const production = true
const production = false
let fs = require("fs")

View File

@ -0,0 +1 @@
module.exports = require("@lightcord/api")

View File

@ -0,0 +1,11 @@
{
"name": "@lightcord/components",
"version": "1.0.0",
"description": "Components that can be found inside Ligthcord Api",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Lightcord",
"license": "ISC"
}

View File

@ -1,7 +1,7 @@
{
"name": "lightcord",
"version": "0.1.2",
"description": "",
"description": "A simple - customizable - Discord Client.",
"main": "dist/index.js",
"scripts": {
"compile": "node compile.js",

View File

@ -4,7 +4,7 @@
import { releaseChannel } from './buildInfo';
import appSettings from './appSettings';
const pak = require("../package.json")
const pak = require("../package.json" as any) as any
import * as path from "path"
const settings = appSettings.getSettings();
@ -22,3 +22,4 @@ export const UPDATE_ENDPOINT = settings.get('UPDATE_ENDPOINT') || API_ENDPOINT;
export const mainAppDirname = path.join(__dirname, "..")
export const version:string = pak.version
export const packageJSON:any = pak

View File

@ -19,6 +19,8 @@ import * as moduleUpdater from "./common/moduleUpdater"
import * as paths from "./common/paths"
import { create } from "./singleInstance";
import * as splashScreen from "./splashScreen"
import { join } from "path"
import { homedir } from "os"
if (process.platform === 'linux') {
// Some people are reporting audio problems on Linux that are fixed by setting
@ -56,6 +58,22 @@ function hasArgvFlag(flag) {
(async function Main(){
await electron.app.whenReady()
if(process.argv.includes("--should-create-shortcut")){
console.log(`Creating shortcuts.`)
if(process.platform === "win32"){
electron.shell.writeShortcutLink(join(homedir(), "Desktop", "Lightcord.lnk"), "create", {
"appUserModelId": Constants.APP_ID,
description: Constants.packageJSON.description,
target: process.execPath
})
electron.shell.writeShortcutLink(join(electron.app.getPath("appData"), "Microsoft", "Windows", "Start Menu", "Programs", "Lightcord.lnk"), "create", {
"appUserModelId": Constants.APP_ID,
description: Constants.packageJSON.description,
target: process.execPath
})
}
}
console.log(`Initializing Lightcord.`)
console.log(`Version: ${buildInfo.version}
releaseChannel: ${buildInfo.releaseChannel}
@ -82,14 +100,16 @@ commit: ${buildInfo.commit}`)
coreModule.setMainWindowVisible(!startMinimized)
}, (args) => {
if (args != null && args.length > 0 && args[0] === '--squirrel-uninstall') {
electron.app.quit();
return;
}
if(args && args.length > 0){
if(args.length > 0 && args[0] === '--squirrel-uninstall') {
electron.app.quit();
return;
}
if(args.length === 1 && args[0] === "--overlay-host"){ // this is a patch for Lightcord that focus itself
//console.warn("OVERLAY HOST DÉTECTÉ. EVENNEMENT IGNORÉ MAIS POURRAIT CAUSER UN PROBLÈME.")
return
if(args && args.length === 1 && args[0] === "--overlay-host"){ // this is a patch for Lightcord that focus itself
//console.warn("OVERLAY HOST DÉTECTÉ. EVENNEMENT IGNORÉ MAIS POURRAIT CAUSER UN PROBLÈME.")
return
}
}
if (coreModule) {