Glasstron clarification + option to disable it

This commit is contained in:
Jean Ouina 2020-07-10 23:30:05 +02:00
parent 8e546f2914
commit 2ff7a5cea8
8 changed files with 334 additions and 269 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -44,7 +44,7 @@ export const bbdChangelog = {
title: "What's New?",
items: [
"**Lightcord** is now using BandagedBD. That means all plugins you were using can be used too !",
"**Window Transparency** changes were made to more compatible with external window managers and addons like Glasscord.",
"**Window Transparency** changes were made to more compatible with external window managers and addons like Glasstron.",
"Initialization sequence has once again been changed slightly to hopefully improve loading times."
]
},
@ -95,11 +95,12 @@ export const settings = {
"Ad Block": {id: "lightcord-4", info: "Block any BOT that dms you with an invite link. Even in an embed.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
"Enable Lightcord Servers": {id: "lightcord-5", info: "Enable Lightcord's servers. Disabling this will disable custom badges.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
"Disable typing": {id: "lightcord-7", info: "Don't let other see you're typing.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
"Lightcord Tabs": {id: "lightcord-8", info: "Allows you to launch multiple instances of Lightcord in the same window (EXPERIMENTAL).", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
"No Window Bounds": {id: "no_window_bound", info: "Disable Window Bounds. Can be useful if you use a window manager.", implemented: true, hidden: process.platform == "linux", cat: "lightcord", category: "Lightcord"},
"Lightcord Tabs": {id: "lightcord-8", info: "Allows you to launch multiple instances of Lightcord in the same window.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord", experimental: true},
/** Lightcord Window */
"Always-on-Top": {id: "lightcord-3", info: "Enable window's Always-on-Top mode, where Lightcord stays on top of other applications.", implemented: true, hidden: false, cat: "lightcord", category: "Window"},
"Always-on-Top": {id: "lightcord-3", info: "Enable the window's Always-on-Top mode, where Lightcord stays on top of other applications.", implemented: true, hidden: false, cat: "lightcord", category: "Window"},
"No Window Bounds": {id: "no_window_bound", info: "Disable Window Bounds. Can be useful if you use a window manager.", implemented: true, hidden: process.platform !== "linux", cat: "lightcord", category: "Window"},
"Enable Glasstron": {id: "enable_glasstron", info: "Enable Glasstron. If you're not using transparent themes, this can reduce lag.", implemented: true, hidden: false, cat: "lightcord", category: "Window"},
/** RichPresence */
"Enable": {id: "lightcord-presence-1", info: "Enable RichPresence below.", implemented: true, hidden: false, cat: "status"}

View File

@ -1,178 +1,170 @@
import BugHunterBadge from "../svg/bug_hunter"
import LightcordUserBadge from "../svg/LightcordUser";
import nodeFetch from "node-fetch"
import { settingsCookie } from "../0globals";
import Circus from "../svg/circus";
export function uuidv4() { // Generate UUID (No crypto rng)
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
const awaitingBadgesPromises = {}
let badgesToFetch = []
export default new class DistantServer {
constructor(){
this._cache = {
badges: {
}
}
window.Lightcord.BetterDiscord.DistantServer = this
}
get cache(){
return this._cache
}
set cache(data){
if(typeof data !== "object" || typeof this._cache !== "object")return this._cache = data
return this._cache = Object.assign(this._cache, data)
}/*
async delete(){
BdApi.showToast("Deleting all infos about you on Lightcord Servers...", {type: "warn"})
return handleRequest(Routes.delete, "delete")
.then(async res => {
if(res.status !== 200){
BdApi.showToast("An error occured, couldn't delete informations. See console for more infos", {type: "error"})
throw new Error(`Couldn't delete all informations: ${(res.status+" "+res.statusText+" "+await res.text())}`)
}
console.info(`Succesfully deleted informations.`)
BdApi.showToast("Succesfully deleted informations", {type: "success"})
window.Lightcord.Api.Authorization = null
return res.json()
}).catch((err) => {
BdApi.showToast("An error occured, couldn't delete informations. See console for more infos", {type: "error"})
throw new Error(`Couldn't delete all informations: ${err.stack}`)
})
}*/
/**
* Get custom badges from the user ID.
* @param {string} user The user ID
* @returns {Promise<Constants["badges"]>}
*/
async getBadges(user){
if(this.cache.badges[user])return this.cache.badges[user]
if(awaitingBadgesPromises[user])return awaitingBadgesPromises[user]
let resolve
const newPromise = new Promise((res) => (resolve = res))
awaitingBadgesPromises[user] = newPromise
const badges = []
for(let badge of Constants.badges){
if(badge.defaultUsers.includes(user))badges.push(badge)
}
const fetchedBadges = await new Promise((resolve) => {
if(!settingsCookie["lightcord-5"])return resolve([])
badgesToFetch.push([user, resolve])
setTimeout(() => {
let users = badgesToFetch
if(users.length === 0)return
badgesToFetch = []
handleRequest(Routes.badges, "POST", JSON.stringify(users.map(e => e[0])))
.then(async res => {
if(res.status !== 200){// Couldn't fetch badges: server error
users.forEach(data => {
data[1]([])// resolve no badge fetched
})
}
const responseBody = await res.json()
for(let user of responseBody){
let promise = users.find(promise => promise[0] === user.user_id)
promise[1](user.badges)
}
}).catch((err) => {// Couldn't fetch badges: error
if(!(err instanceof LightcordError))console.error(err)
users.forEach(data => {
data[1]([])// resolve no badge fetched
})
})
}, 0)
})
for(let badge of fetchedBadges){
if(!Constants.badges.find(e => e.id === badge))continue // We do not have the Component, skip it.
if(badges.find(e => e.id === badge))continue // Already inserted.
badges.push(Constants.badges.find(e => e.id === badge))
}
this.cache = {
badges: Object.assign(this.cache.badges, {[user]: badges})
}
setTimeout(() => {
delete this.cache.badges[user]
}, 600000);
resolve(badges)
delete awaitingBadgesPromises[user]
return badges
}
}
const handleRequest = function(route, method, data){
if(!settingsCookie["lightcord-5"]){
return Promise.reject(new LightcordError("The current settings blocked the request."))
}
return nodeFetch(`${Constants.SERVER_URL}/api/v1${route}`, {
method,
headers: {
"CLIENT": "Lightcord",
"Authorization": window.Lightcord.Api.Authorization || "None::Anonymous"
},
...(data ? {
body: data
} : {})
})
}
class LightcordError extends Error {
constructor(){
super(...arguments)
this.name = "LightcordError"
}
}
export const Constants = {
SERVER_URL: "https://lightcord.deroku.xyz",
badges: [ // TODO:
/*{
name: "Lightcord User",
id: "01cfa7b0-7cdb-4b0e-8258-9c6a78235c93",
defaultUsers: [],
scopes: [
"user"
],
component: LightcordUserBadge
}, */{
name: "Lightcord Bug Hunter",
id: "f04698f5-816b-41e3-bd01-92291193d7a5",
defaultUsers: [
"696481194443014174",
"696003456611385396"
],
scopes: [],
component: BugHunterBadge,
href: "https://github.com/lightcord/lightcord/wiki/badges#bug_hunter"
}, {
name: "Buffoon",
id: "06904d31-65b4-41ec-a50c-8658bbd1af96",
defaultUsers: [
"389016895543705602",
"664600134528663565",
"625350657829896224"
],
scopes: [],
component: Circus,
href: "https://youtu.be/EJtb6z-dlT8?t=145"
}
]
}
export const Routes = {
badges: `/users/badges`
import BugHunterBadge from "../svg/bug_hunter"
import LightcordUserBadge from "../svg/LightcordUser";
import nodeFetch from "node-fetch"
import { settingsCookie } from "../0globals";
import Circus from "../svg/circus";
export function uuidv4() { // Generate UUID (No crypto rng)
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
const awaitingBadgesPromises = {}
let badgesToFetch = []
export default new class DistantServer {
constructor(){
this._cache = {
badges: {
}
}
window.Lightcord.BetterDiscord.DistantServer = this
}
get cache(){
return this._cache
}
set cache(data){
if(typeof data !== "object" || typeof this._cache !== "object")return this._cache = data
return this._cache = Object.assign(this._cache, data)
}/*
async delete(){
BdApi.showToast("Deleting all infos about you on Lightcord Servers...", {type: "warn"})
return handleRequest(Routes.delete, "delete")
.then(async res => {
if(res.status !== 200){
BdApi.showToast("An error occured, couldn't delete informations. See console for more infos", {type: "error"})
throw new Error(`Couldn't delete all informations: ${(res.status+" "+res.statusText+" "+await res.text())}`)
}
console.info(`Succesfully deleted informations.`)
BdApi.showToast("Succesfully deleted informations", {type: "success"})
window.Lightcord.Api.Authorization = null
return res.json()
}).catch((err) => {
BdApi.showToast("An error occured, couldn't delete informations. See console for more infos", {type: "error"})
throw new Error(`Couldn't delete all informations: ${err.stack}`)
})
}*/
/**
* Get custom badges from the user ID.
* @param {string} user The user ID
* @returns {Promise<Constants["badges"]>}
*/
async getBadges(user){
if(this.cache.badges[user])return this.cache.badges[user]
if(awaitingBadgesPromises[user])return awaitingBadgesPromises[user]
let resolve
const newPromise = new Promise((res) => (resolve = res))
awaitingBadgesPromises[user] = newPromise
const badges = []
for(let badge of Constants.badges){
if(badge.defaultUsers.includes(user))badges.push(badge)
}
const fetchedBadges = await new Promise((resolve) => {
if(!settingsCookie["lightcord-5"])return resolve([])
badgesToFetch.push([user, resolve])
setTimeout(() => {
let users = badgesToFetch
if(users.length === 0)return
badgesToFetch = []
handleRequest(Routes.badges, "POST", JSON.stringify(users.map(e => e[0])))
.then(async res => {
if(res.status !== 200){// Couldn't fetch badges: server error
users.forEach(data => {
data[1]([])// resolve no badge fetched
})
}
const responseBody = await res.json()
for(let user of responseBody){
let promise = users.find(promise => promise[0] === user.user_id)
promise[1](user.badges)
}
}).catch((err) => {// Couldn't fetch badges: error
if(!(err instanceof LightcordError))console.error(err)
users.forEach(data => {
data[1]([])// resolve no badge fetched
})
})
}, 0)
})
for(let badge of fetchedBadges){
if(!Constants.badges.find(e => e.id === badge))continue // We do not have the Component, skip it.
if(badges.find(e => e.id === badge))continue // Already inserted.
badges.push(Constants.badges.find(e => e.id === badge))
}
this.cache = {
badges: Object.assign(this.cache.badges, {[user]: badges})
}
setTimeout(() => {
delete this.cache.badges[user]
}, 600000);
resolve(badges)
delete awaitingBadgesPromises[user]
return badges
}
}
const handleRequest = function(route, method, data){
if(!settingsCookie["lightcord-5"]){
return Promise.reject(new LightcordError("The current settings blocked the request."))
}
return nodeFetch(`${Constants.SERVER_URL}/api/v1${route}`, {
method,
headers: {
"CLIENT": "Lightcord",
"Authorization": window.Lightcord.Api.Authorization || "None::Anonymous"
},
...(data ? {
body: data
} : {})
})
}
class LightcordError extends Error {
constructor(){
super(...arguments)
this.name = "LightcordError"
}
}
export const Constants = {
SERVER_URL: "https://lightcord.deroku.xyz",
badges: [ // TODO: Add more badges + server side svg
{
name: "Lightcord Bug Hunter",
id: "f04698f5-816b-41e3-bd01-92291193d7a5",
defaultUsers: [
"696481194443014174",
"696003456611385396"
],
scopes: [],
component: BugHunterBadge,
href: "https://github.com/lightcord/lightcord/wiki/badges#bug_hunter"
}, {
name: "Buffoon",
id: "06904d31-65b4-41ec-a50c-8658bbd1af96",
defaultUsers: [
"389016895543705602",
"664600134528663565",
"625350657829896224"
],
scopes: [],
component: Circus,
href: "https://youtu.be/EJtb6z-dlT8?t=145"
}
]
}
export const Routes = {
badges: `/users/badges`
}

View File

@ -142,7 +142,7 @@ export default new class V2_SettingsPanel {
}
updateSettings(id, enabled, sidebar) {
if(!["lightcord-8", "no_window_bound"].includes(id))settingsCookie[id] = enabled;
if(!["lightcord-8", "no_window_bound", "enable_glasstron"].includes(id))settingsCookie[id] = enabled;
if (id == "bda-gs-2") {
if (enabled) DOM.addClass(document.body, "bd-minimal");
@ -273,6 +273,13 @@ export default new class V2_SettingsPanel {
remote.app.relaunch()
remote.app.exit()
}
if (id === "enable_glasstron"){
let appSettings = remote.getGlobal("appSettings")
appSettings.set("GLASSTRON", enabled)
appSettings.save()
remote.app.relaunch()
remote.app.exit()
}
this.saveSettings();
}
@ -335,24 +342,27 @@ export default new class V2_SettingsPanel {
let isChecked = settingsCookie[setting.id]
if(setting.id === "lightcord-8")isChecked = appSettings.get("isTabs", false);
if(setting.id === "no_window_bound")isChecked = appSettings.get("NO_WINDOWS_BOUND", false)
if(setting.id === "enable_glasstron")isChecked = appSettings.get("GLASSTRON", true)
let returnValue = BDV2.react.createElement(Switch, {id: setting.id, key: setting.id, data: setting, checked: isChecked, onChange: (id, checked) => {
this.onChange(id, checked, sidebar);
}})
if(setting.id !== "lightcord-8" || !isChecked)return returnValue
return [
returnValue,
React.createElement(Lightcord.Api.Components.inputs.Button, {
color: "green",
look: "outlined",
size: "small",
hoverColor: "brand",
onClick: () => {
DiscordNative.ipc.send("NEW_TAB")
},
wrapper: false,
disabled: false
}, "Open a new Tab")
]
if(setting.id == "lightcord-8" && isChecked){
return [
returnValue,
React.createElement(Lightcord.Api.Components.inputs.Button, {
color: "green",
look: "outlined",
size: "small",
hoverColor: "brand",
onClick: () => {
DiscordNative.ipc.send("NEW_TAB")
},
wrapper: false,
disabled: false
}, "Open a new Tab")
]
}
return returnValue
})
]
}),

View File

@ -1,26 +1,44 @@
import BDV2 from "../modules/v2";
import Switch from "./components/switch";
export default class SwitchItem extends BDV2.reactComponent {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
}
onChange() {
this.props.checked = !this.props.checked;
this.props.onChange(this.props.id, this.props.checked);
}
render() {
const {text, info} = this.props.data;
return BDV2.react.createElement("div", {className: "ui-flex flex-vertical flex-justify-start flex-align-stretch flex-nowrap ui-switch-item"},
BDV2.react.createElement("div", {className: "ui-flex flex-horizontal flex-justify-start flex-align-stretch flex-nowrap"},
BDV2.react.createElement("h3", {className: "ui-form-title h3 margin-reset margin-reset ui-flex-child"}, text),
BDV2.react.createElement(Switch, {onChange: this.onChange, checked: this.props.checked})
),
BDV2.react.createElement("div", {className: "ui-form-text style-description margin-top-4", style: {flex: "1 1 auto"}}, info)
);
}
import BDV2 from "../modules/v2";
import Switch from "./components/switch";
let classnames = []
function getClassName(name){
let className = classnames.find(e => e.startsWith(name+"-"))
if(className)return className
className = BDModules.get(e => e.name)[0]
classnames.push(className)
return className
}
export default class SwitchItem extends BDV2.reactComponent {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
}
onChange() {
this.props.checked = !this.props.checked;
this.props.onChange(this.props.id, this.props.checked);
}
render() {
let {text, info} = this.props.data;
if(!classnames.find(e => e.startsWith("beta-"))){
classnames.push(BDModules.get(e => e.beta && (!e.container && !e.userSettingsVoice))[0].beta)
}
if(this.props.data.experimental){
info = [
info,
React.createElement("sup", {className: getClassName("beta")}, "(EXPERIMENTAL)")
]
}
return BDV2.react.createElement("div", {className: "ui-flex flex-vertical flex-justify-start flex-align-stretch flex-nowrap ui-switch-item"},
BDV2.react.createElement("div", {className: "ui-flex flex-horizontal flex-justify-start flex-align-stretch flex-nowrap"},
BDV2.react.createElement("h3", {className: "ui-form-title h3 margin-reset margin-reset ui-flex-child"}, text),
BDV2.react.createElement(Switch, {onChange: this.onChange, checked: this.props.checked})
),
BDV2.react.createElement("div", {className: "ui-form-text style-description margin-top-4", style: {flex: "1 1 auto"}}, info)
);
}
}

View File

@ -374,11 +374,13 @@ function launchMainAppWindow(isVisible) {
mainWindow = new electron.BrowserWindow(mainWindowOptions);
mainWindowId = mainWindow.id;
global.mainWindowId = mainWindowId;
glasstron.update(mainWindow, {
windows: {blurType: 'blurbehind'},
macos: {vibrancy: 'fullscreen-ui'},
linux: {requestBlur: true} // KWin
});
if(settings.get("GLASSTRON", true)){
glasstron.update(mainWindow, {
windows: {blurType: 'blurbehind'},
macos: {vibrancy: 'fullscreen-ui'},
linux: {requestBlur: true} // KWin
});
}
mainWindow.webContents.session.webRequest.onHeadersReceived(function(details, callback) {
if (!details.responseHeaders["content-security-policy-report-only"] && !details.responseHeaders["content-security-policy"]) return callback({cancel: false});
@ -434,8 +436,6 @@ function launchMainAppWindow(isVisible) {
insideAuthFlow = false;
}
console.log(`Emitting focus as ready`)
webContentsSend(mainWindow != null && mainWindow.isFocused() ? 'MAIN_WINDOW_FOCUS' : 'MAIN_WINDOW_BLUR');
if (!lastPageLoadFailed) {

View File

@ -1,11 +1,16 @@
/** settings */
import appSettings from "./appSettings"
let settings = appSettings.getSettings()
/** Glasstron */
import * as glasstron from "glasstron"
glasstron.init()
if(settings.get("GLASSTRON", true)){
const glasstron = require("glasstron")
glasstron.init()
}
/** Modules */
import * as electron from "electron"
import requireNativeDiscordModule from "./requireNative";
import appSettings from "./appSettings"
import autoStart from "./autoStart"
import * as buildInfo from "./buildInfo"
import * as Constants from "./Constants"