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?", title: "What's New?",
items: [ items: [
"**Lightcord** is now using BandagedBD. That means all plugins you were using can be used too !", "**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." "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"}, "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"}, "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"}, "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"}, "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},
"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 Window */ /** 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 */ /** RichPresence */
"Enable": {id: "lightcord-presence-1", info: "Enable RichPresence below.", implemented: true, hidden: false, cat: "status"} "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 BugHunterBadge from "../svg/bug_hunter"
import LightcordUserBadge from "../svg/LightcordUser"; import LightcordUserBadge from "../svg/LightcordUser";
import nodeFetch from "node-fetch" import nodeFetch from "node-fetch"
import { settingsCookie } from "../0globals"; import { settingsCookie } from "../0globals";
import Circus from "../svg/circus"; import Circus from "../svg/circus";
export function uuidv4() { // Generate UUID (No crypto rng) export function uuidv4() { // Generate UUID (No crypto rng)
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16); return v.toString(16);
}); });
} }
const awaitingBadgesPromises = {} const awaitingBadgesPromises = {}
let badgesToFetch = [] let badgesToFetch = []
export default new class DistantServer { export default new class DistantServer {
constructor(){ constructor(){
this._cache = { this._cache = {
badges: { badges: {
} }
} }
window.Lightcord.BetterDiscord.DistantServer = this window.Lightcord.BetterDiscord.DistantServer = this
} }
get cache(){ get cache(){
return this._cache return this._cache
} }
set cache(data){ set cache(data){
if(typeof data !== "object" || typeof this._cache !== "object")return this._cache = data if(typeof data !== "object" || typeof this._cache !== "object")return this._cache = data
return this._cache = Object.assign(this._cache, data) return this._cache = Object.assign(this._cache, data)
}/* }/*
async delete(){ async delete(){
BdApi.showToast("Deleting all infos about you on Lightcord Servers...", {type: "warn"}) BdApi.showToast("Deleting all infos about you on Lightcord Servers...", {type: "warn"})
return handleRequest(Routes.delete, "delete") return handleRequest(Routes.delete, "delete")
.then(async res => { .then(async res => {
if(res.status !== 200){ if(res.status !== 200){
BdApi.showToast("An error occured, couldn't delete informations. See console for more infos", {type: "error"}) 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())}`) throw new Error(`Couldn't delete all informations: ${(res.status+" "+res.statusText+" "+await res.text())}`)
} }
console.info(`Succesfully deleted informations.`) console.info(`Succesfully deleted informations.`)
BdApi.showToast("Succesfully deleted informations", {type: "success"}) BdApi.showToast("Succesfully deleted informations", {type: "success"})
window.Lightcord.Api.Authorization = null window.Lightcord.Api.Authorization = null
return res.json() return res.json()
}).catch((err) => { }).catch((err) => {
BdApi.showToast("An error occured, couldn't delete informations. See console for more infos", {type: "error"}) 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}`) throw new Error(`Couldn't delete all informations: ${err.stack}`)
}) })
}*/ }*/
/** /**
* Get custom badges from the user ID. * Get custom badges from the user ID.
* @param {string} user The user ID * @param {string} user The user ID
* @returns {Promise<Constants["badges"]>} * @returns {Promise<Constants["badges"]>}
*/ */
async getBadges(user){ async getBadges(user){
if(this.cache.badges[user])return this.cache.badges[user] if(this.cache.badges[user])return this.cache.badges[user]
if(awaitingBadgesPromises[user])return awaitingBadgesPromises[user] if(awaitingBadgesPromises[user])return awaitingBadgesPromises[user]
let resolve let resolve
const newPromise = new Promise((res) => (resolve = res)) const newPromise = new Promise((res) => (resolve = res))
awaitingBadgesPromises[user] = newPromise awaitingBadgesPromises[user] = newPromise
const badges = [] const badges = []
for(let badge of Constants.badges){ for(let badge of Constants.badges){
if(badge.defaultUsers.includes(user))badges.push(badge) if(badge.defaultUsers.includes(user))badges.push(badge)
} }
const fetchedBadges = await new Promise((resolve) => { const fetchedBadges = await new Promise((resolve) => {
if(!settingsCookie["lightcord-5"])return resolve([]) if(!settingsCookie["lightcord-5"])return resolve([])
badgesToFetch.push([user, resolve]) badgesToFetch.push([user, resolve])
setTimeout(() => { setTimeout(() => {
let users = badgesToFetch let users = badgesToFetch
if(users.length === 0)return if(users.length === 0)return
badgesToFetch = [] badgesToFetch = []
handleRequest(Routes.badges, "POST", JSON.stringify(users.map(e => e[0]))) handleRequest(Routes.badges, "POST", JSON.stringify(users.map(e => e[0])))
.then(async res => { .then(async res => {
if(res.status !== 200){// Couldn't fetch badges: server error if(res.status !== 200){// Couldn't fetch badges: server error
users.forEach(data => { users.forEach(data => {
data[1]([])// resolve no badge fetched data[1]([])// resolve no badge fetched
}) })
} }
const responseBody = await res.json() const responseBody = await res.json()
for(let user of responseBody){ for(let user of responseBody){
let promise = users.find(promise => promise[0] === user.user_id) let promise = users.find(promise => promise[0] === user.user_id)
promise[1](user.badges) promise[1](user.badges)
} }
}).catch((err) => {// Couldn't fetch badges: error }).catch((err) => {// Couldn't fetch badges: error
if(!(err instanceof LightcordError))console.error(err) if(!(err instanceof LightcordError))console.error(err)
users.forEach(data => { users.forEach(data => {
data[1]([])// resolve no badge fetched data[1]([])// resolve no badge fetched
}) })
}) })
}, 0) }, 0)
}) })
for(let badge of fetchedBadges){ for(let badge of fetchedBadges){
if(!Constants.badges.find(e => e.id === badge))continue // We do not have the Component, skip it. 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. if(badges.find(e => e.id === badge))continue // Already inserted.
badges.push(Constants.badges.find(e => e.id === badge)) badges.push(Constants.badges.find(e => e.id === badge))
} }
this.cache = { this.cache = {
badges: Object.assign(this.cache.badges, {[user]: badges}) badges: Object.assign(this.cache.badges, {[user]: badges})
} }
setTimeout(() => { setTimeout(() => {
delete this.cache.badges[user] delete this.cache.badges[user]
}, 600000); }, 600000);
resolve(badges) resolve(badges)
delete awaitingBadgesPromises[user] delete awaitingBadgesPromises[user]
return badges return badges
} }
} }
const handleRequest = function(route, method, data){ const handleRequest = function(route, method, data){
if(!settingsCookie["lightcord-5"]){ if(!settingsCookie["lightcord-5"]){
return Promise.reject(new LightcordError("The current settings blocked the request.")) return Promise.reject(new LightcordError("The current settings blocked the request."))
} }
return nodeFetch(`${Constants.SERVER_URL}/api/v1${route}`, { return nodeFetch(`${Constants.SERVER_URL}/api/v1${route}`, {
method, method,
headers: { headers: {
"CLIENT": "Lightcord", "CLIENT": "Lightcord",
"Authorization": window.Lightcord.Api.Authorization || "None::Anonymous" "Authorization": window.Lightcord.Api.Authorization || "None::Anonymous"
}, },
...(data ? { ...(data ? {
body: data body: data
} : {}) } : {})
}) })
} }
class LightcordError extends Error { class LightcordError extends Error {
constructor(){ constructor(){
super(...arguments) super(...arguments)
this.name = "LightcordError" this.name = "LightcordError"
} }
} }
export const Constants = { export const Constants = {
SERVER_URL: "https://lightcord.deroku.xyz", SERVER_URL: "https://lightcord.deroku.xyz",
badges: [ // TODO: badges: [ // TODO: Add more badges + server side svg
/*{ {
name: "Lightcord User", name: "Lightcord Bug Hunter",
id: "01cfa7b0-7cdb-4b0e-8258-9c6a78235c93", id: "f04698f5-816b-41e3-bd01-92291193d7a5",
defaultUsers: [], defaultUsers: [
scopes: [ "696481194443014174",
"user" "696003456611385396"
], ],
component: LightcordUserBadge scopes: [],
}, */{ component: BugHunterBadge,
name: "Lightcord Bug Hunter", href: "https://github.com/lightcord/lightcord/wiki/badges#bug_hunter"
id: "f04698f5-816b-41e3-bd01-92291193d7a5", }, {
defaultUsers: [ name: "Buffoon",
"696481194443014174", id: "06904d31-65b4-41ec-a50c-8658bbd1af96",
"696003456611385396" defaultUsers: [
], "389016895543705602",
scopes: [], "664600134528663565",
component: BugHunterBadge, "625350657829896224"
href: "https://github.com/lightcord/lightcord/wiki/badges#bug_hunter" ],
}, { scopes: [],
name: "Buffoon", component: Circus,
id: "06904d31-65b4-41ec-a50c-8658bbd1af96", href: "https://youtu.be/EJtb6z-dlT8?t=145"
defaultUsers: [ }
"389016895543705602", ]
"664600134528663565", }
"625350657829896224"
], export const Routes = {
scopes: [], badges: `/users/badges`
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) { 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 (id == "bda-gs-2") {
if (enabled) DOM.addClass(document.body, "bd-minimal"); if (enabled) DOM.addClass(document.body, "bd-minimal");
@ -273,6 +273,13 @@ export default new class V2_SettingsPanel {
remote.app.relaunch() remote.app.relaunch()
remote.app.exit() 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(); this.saveSettings();
} }
@ -335,24 +342,27 @@ export default new class V2_SettingsPanel {
let isChecked = settingsCookie[setting.id] let isChecked = settingsCookie[setting.id]
if(setting.id === "lightcord-8")isChecked = appSettings.get("isTabs", false); 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 === "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) => { let returnValue = BDV2.react.createElement(Switch, {id: setting.id, key: setting.id, data: setting, checked: isChecked, onChange: (id, checked) => {
this.onChange(id, checked, sidebar); this.onChange(id, checked, sidebar);
}}) }})
if(setting.id !== "lightcord-8" || !isChecked)return returnValue if(setting.id == "lightcord-8" && isChecked){
return [ return [
returnValue, returnValue,
React.createElement(Lightcord.Api.Components.inputs.Button, { React.createElement(Lightcord.Api.Components.inputs.Button, {
color: "green", color: "green",
look: "outlined", look: "outlined",
size: "small", size: "small",
hoverColor: "brand", hoverColor: "brand",
onClick: () => { onClick: () => {
DiscordNative.ipc.send("NEW_TAB") DiscordNative.ipc.send("NEW_TAB")
}, },
wrapper: false, wrapper: false,
disabled: false disabled: false
}, "Open a new Tab") }, "Open a new Tab")
] ]
}
return returnValue
}) })
] ]
}), }),

View File

@ -1,26 +1,44 @@
import BDV2 from "../modules/v2"; import BDV2 from "../modules/v2";
import Switch from "./components/switch"; import Switch from "./components/switch";
export default class SwitchItem extends BDV2.reactComponent { let classnames = []
function getClassName(name){
constructor(props) { let className = classnames.find(e => e.startsWith(name+"-"))
super(props); if(className)return className
this.onChange = this.onChange.bind(this); className = BDModules.get(e => e.name)[0]
} classnames.push(className)
return className
onChange() { }
this.props.checked = !this.props.checked;
this.props.onChange(this.props.id, this.props.checked); export default class SwitchItem extends BDV2.reactComponent {
}
constructor(props) {
render() { super(props);
const {text, info} = this.props.data; this.onChange = this.onChange.bind(this);
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), onChange() {
BDV2.react.createElement(Switch, {onChange: this.onChange, checked: this.props.checked}) this.props.checked = !this.props.checked;
), this.props.onChange(this.props.id, this.props.checked);
BDV2.react.createElement("div", {className: "ui-form-text style-description margin-top-4", style: {flex: "1 1 auto"}}, info) }
);
} 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); mainWindow = new electron.BrowserWindow(mainWindowOptions);
mainWindowId = mainWindow.id; mainWindowId = mainWindow.id;
global.mainWindowId = mainWindowId; global.mainWindowId = mainWindowId;
glasstron.update(mainWindow, { if(settings.get("GLASSTRON", true)){
windows: {blurType: 'blurbehind'}, glasstron.update(mainWindow, {
macos: {vibrancy: 'fullscreen-ui'}, windows: {blurType: 'blurbehind'},
linux: {requestBlur: true} // KWin macos: {vibrancy: 'fullscreen-ui'},
}); linux: {requestBlur: true} // KWin
});
}
mainWindow.webContents.session.webRequest.onHeadersReceived(function(details, callback) { 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}); 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; insideAuthFlow = false;
} }
console.log(`Emitting focus as ready`)
webContentsSend(mainWindow != null && mainWindow.isFocused() ? 'MAIN_WINDOW_FOCUS' : 'MAIN_WINDOW_BLUR'); webContentsSend(mainWindow != null && mainWindow.isFocused() ? 'MAIN_WINDOW_FOCUS' : 'MAIN_WINDOW_BLUR');
if (!lastPageLoadFailed) { if (!lastPageLoadFailed) {

View File

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