2020-10-20 23:25:34 +02:00
/ * *
* @ name ThemeSettings
* @ authorId 278543574059057154
* @ invite Jx3TjNS
* @ donate https : //www.paypal.me/MircoWittrien
* @ patreon https : //www.patreon.com/MircoWittrien
* @ website https : //github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ThemeSettings
* @ source https : //raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ThemeSettings/ThemeSettings.plugin.js
* /
2018-12-11 19:43:51 +01:00
2020-09-19 20:49:33 +02:00
module . exports = ( _ => {
2020-10-09 21:09:35 +02:00
const config = {
2020-09-19 20:49:33 +02:00
"info" : {
"name" : "ThemeSettings" ,
"author" : "DevilBro" ,
2020-11-06 16:46:50 +01:00
"version" : "1.2.5" ,
2020-10-16 10:25:30 +02:00
"description" : "Allow you to change Theme Variables within BetterDiscord. Adds a Settings button (similar to Plugins) to customizable Themes in your Themes Page"
2020-10-14 21:08:41 +02:00
} ,
"changeLog" : {
"fixed" : {
2020-11-06 16:14:31 +01:00
"BD Beta" : "Works with BD beta"
2020-10-14 21:08:41 +02:00
}
2020-03-28 07:55:39 +01:00
}
2020-09-19 20:49:33 +02:00
} ;
2020-10-09 21:09:35 +02:00
return ! window . BDFDB _Global || ( ! window . BDFDB _Global . loaded && ! window . BDFDB _Global . started ) ? class {
2020-09-19 20:49:33 +02:00
getName ( ) { return config . info . name ; }
getAuthor ( ) { return config . info . author ; }
getVersion ( ) { return config . info . version ; }
getDescription ( ) { return config . info . description ; }
2020-05-22 21:17:02 +02:00
2020-10-09 21:09:35 +02:00
load ( ) {
2020-09-19 20:49:33 +02:00
if ( ! window . BDFDB _Global || ! Array . isArray ( window . BDFDB _Global . pluginQueue ) ) window . BDFDB _Global = Object . assign ( { } , window . BDFDB _Global , { pluginQueue : [ ] } ) ;
if ( ! window . BDFDB _Global . downloadModal ) {
window . BDFDB _Global . downloadModal = true ;
BdApi . showConfirmationModal ( "Library Missing" , ` The library plugin needed for ${ config . info . name } is missing. Please click "Download Now" to install it. ` , {
confirmText : "Download Now" ,
cancelText : "Cancel" ,
onCancel : _ => { delete window . BDFDB _Global . downloadModal ; } ,
2020-09-20 08:15:13 +02:00
onConfirm : _ => {
delete window . BDFDB _Global . downloadModal ;
require ( "request" ) . get ( "https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js" , ( e , r , b ) => {
2020-10-20 23:25:34 +02:00
if ( ! e && b && b . indexOf ( ` * @name BDFDB ` ) > - 1 ) require ( "fs" ) . writeFile ( require ( "path" ) . join ( BdApi . Plugins . folder , "0BDFDB.plugin.js" ) , b , _ => { } ) ;
2020-09-20 08:15:13 +02:00
else BdApi . alert ( "Error" , "Could not download BDFDB library plugin, try again some time later." ) ;
} ) ;
}
2020-09-19 20:49:33 +02:00
} ) ;
2020-03-28 07:55:39 +01:00
}
2020-09-19 20:49:33 +02:00
if ( ! window . BDFDB _Global . pluginQueue . includes ( config . info . name ) ) window . BDFDB _Global . pluginQueue . push ( config . info . name ) ;
2020-10-09 21:09:35 +02:00
}
start ( ) { this . load ( ) ; }
stop ( ) { }
} : ( ( [ Plugin , BDFDB ] ) => {
2020-09-19 20:49:33 +02:00
var dir ;
2020-10-09 21:09:35 +02:00
return class ThemeSettings extends Plugin {
2020-09-19 20:49:33 +02:00
onLoad ( ) {
dir = BDFDB . BDUtils . getThemesFolder ( ) ;
}
onStart ( ) {
2020-05-22 21:17:02 +02:00
let cardObserver = ( new MutationObserver ( changes => { changes . forEach ( change => { if ( change . addedNodes ) { change . addedNodes . forEach ( node => {
if ( BDFDB . DOMUtils . containsClass ( node , BDFDB . disCN . _repocard ) ) this . appendSettingsButton ( node ) ;
2020-06-12 15:23:14 +02:00
if ( node . nodeType != Node . TEXT _NODE ) for ( let child of node . querySelectorAll ( BDFDB . dotCN . _repocard ) ) this . appendSettingsButton ( child ) ;
2020-05-22 21:17:02 +02:00
} ) ; } } ) ; } ) ) ;
2020-07-17 14:57:29 +02:00
BDFDB . ObserverUtils . connect ( this , document . querySelector ( ` ${ BDFDB . dotCN . layer } [aria-label=" ${ BDFDB . DiscordConstants . Layers . USER _SETTINGS } "] ` ) , { name : "cardObserver" , instance : cardObserver } , { childList : true , subtree : true } ) ;
2020-05-22 21:17:02 +02:00
BDFDB . ObserverUtils . connect ( this , BDFDB . dotCN . applayers , { name : "appLayerObserver" , instance : ( new MutationObserver ( changes => { changes . forEach ( change => { if ( change . addedNodes ) { change . addedNodes . forEach ( node => {
2020-07-17 14:57:29 +02:00
if ( node . nodeType != Node . TEXT _NODE && node . getAttribute ( "aria-label" ) == BDFDB . DiscordConstants . Layers . USER _SETTINGS ) BDFDB . ObserverUtils . connect ( this , node , { name : "cardObserver" , instance : cardObserver } , { childList : true , subtree : true } ) ;
2020-05-22 21:17:02 +02:00
} ) ; } } ) ; } ) ) } , { childList : true } ) ;
for ( let child of document . querySelectorAll ( BDFDB . dotCN . _repocard ) ) this . appendSettingsButton ( child ) ;
2020-03-28 07:55:39 +01:00
}
2020-09-19 20:49:33 +02:00
onStop ( ) {
2020-05-22 21:17:02 +02:00
BDFDB . DOMUtils . remove ( ".theme-settings-button" ) ;
2020-03-28 07:55:39 +01:00
}
2020-05-22 21:17:02 +02:00
2020-09-19 20:49:33 +02:00
appendSettingsButton ( card ) {
if ( card . querySelector ( ".theme-settings-button" ) ) return ;
let addon = BDFDB . ObjectUtils . get ( BDFDB . ReactUtils . getInstance ( card ) , "return.stateNode.props.addon" ) ;
2020-10-24 10:00:00 +02:00
if ( addon && ! addon . plugin && ! addon . instance && addon . css ) {
2020-09-19 20:49:33 +02:00
let vars = this . getThemeVars ( addon . css ) ;
if ( vars . length ) {
let footer = card . querySelector ( "." + BDFDB . dotCN . _repofooter . split ( "." ) . filter ( n => n ) . join ( ",." ) ) ;
if ( ! footer ) {
footer = document . createElement ( "div" ) ;
footer . className = BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . _repofooter ) ;
let links = document . createElement ( "span" ) ;
links . className = BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . _repolinks ) ;
footer . appendChild ( links ) ;
card . appendChild ( footer ) ;
2020-03-28 07:55:39 +01:00
}
2020-09-19 20:49:33 +02:00
let settingsButton = document . createElement ( "button" ) ;
2020-11-06 16:14:31 +01:00
let controls = footer . querySelector ( "." + BDFDB . disCN . _repocontrols . split ( " " ) [ 0 ] ) ;
if ( controls ) {
2020-11-06 16:32:34 +01:00
settingsButton . className = BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . _repobutton , BDFDB . disCN . _repocontrolsbutton , "theme-settings-button" ) ;
2020-11-06 16:14:31 +01:00
settingsButton . appendChild ( BDFDB . DOMUtils . create ( ` <svg viewBox="0 0 20 20" style="width: 20px; height: 20px;">
< path fill = "none" d = "M0 0h20v20H0V0z" > < / p a t h >
< path d = "M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z" > < / p a t h >
< / s v g > ` ) ) ;
controls . insertBefore ( settingsButton , controls . firstElementChild ) ;
settingsButton . addEventListener ( "click" , _ => {
BDFDB . ModalUtils . open ( this , {
header : ` ${ addon . name } Settings ` ,
subheader : "" ,
className : BDFDB . disCN . _repomodal ,
size : "MEDIUM" ,
children : BDFDB . ReactUtils . elementToReact ( this . createThemeVarInputs ( addon , vars ) ) ,
buttons : [ { contents : "Update" , color : "GREEN" , click : modal => { this . updateTheme ( modal , addon ) ; } } ]
} ) ;
2020-09-19 20:49:33 +02:00
} ) ;
2020-11-06 16:14:31 +01:00
}
else {
2020-11-06 16:28:34 +01:00
settingsButton . className = BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . _reposettingsbutton , "theme-settings-button" ) ;
2020-11-06 16:14:31 +01:00
settingsButton . innerText = "Settings" ;
footer . appendChild ( settingsButton ) ;
settingsButton . addEventListener ( "click" , _ => {
BDFDB . DOMUtils . addClass ( card , BDFDB . disCN . _reposettingsopen ) ;
BDFDB . DOMUtils . removeClass ( card , BDFDB . disCN . _reposettingsclosed ) ;
let children = [ ] ;
while ( card . childElementCount ) {
children . push ( card . firstChild ) ;
card . firstChild . remove ( ) ;
}
let closeButton = BDFDB . DOMUtils . create ( ` <div style="float: right; cursor: pointer;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" style="width: 18px; height: 18px;"><g class="background" fill="none" fill-rule="evenodd"><path d="M0 0h12v12H0"></path><path class="fill" fill="#dcddde" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path></g></svg></div> ` ) ;
card . appendChild ( closeButton ) ;
closeButton . addEventListener ( "click" , _ => {
BDFDB . DOMUtils . removeClass ( card , BDFDB . disCN . _reposettingsopen ) ;
BDFDB . DOMUtils . addClass ( card , BDFDB . disCN . _reposettingsclosed ) ;
while ( card . childElementCount ) card . firstChild . remove ( ) ;
while ( children . length ) card . appendChild ( children . shift ( ) ) ;
} ) ;
2020-11-06 16:46:50 +01:00
card . appendChild ( this . createThemeVarInputs ( addon , vars , [
2020-11-06 16:14:31 +01:00
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsItem , {
type : "Button" ,
color : BDFDB . LibraryComponents . Button . Colors . GREEN ,
label : "Update all variables" ,
2020-11-06 16:46:50 +01:00
onClick : _ => { this . updateTheme ( card , addon ) ; } ,
2020-11-06 16:14:31 +01:00
children : "Update"
} )
] ) ) ;
} ) ;
}
2020-09-19 20:49:33 +02:00
}
2020-03-28 07:55:39 +01:00
}
2018-12-11 19:43:51 +01:00
}
2020-11-06 16:14:31 +01:00
2020-11-06 16:46:50 +01:00
updateTheme ( card , addon ) {
2020-11-06 16:14:31 +01:00
let path = BDFDB . LibraryRequires . path . join ( dir , addon . filename ) ;
let css = BDFDB . LibraryRequires . fs . readFileSync ( path ) . toString ( ) ;
if ( css ) {
let amount = 0 ;
2020-11-06 16:46:50 +01:00
for ( let input of card . querySelectorAll ( BDFDB . dotCN . input ) ) {
2020-11-06 16:14:31 +01:00
let oldValue = input . getAttribute ( "placeholder" ) ;
let newValue = input . value ;
if ( newValue && newValue . trim ( ) && newValue != oldValue ) {
let varName = input . getAttribute ( "varName" ) ;
css = css . replace ( new RegExp ( ` -- ${ BDFDB . StringUtils . regEscape ( varName ) } ( \\ s*):( \\ s*) ${ BDFDB . StringUtils . regEscape ( oldValue ) } ` , "g" ) , ` -- ${ varName } $ 1: $ 2 ${ newValue } ` ) ;
input . setAttribute ( "placeholder" , newValue ) ;
amount ++ ;
}
}
if ( amount > 0 ) {
BDFDB . LibraryRequires . fs . writeFileSync ( path , css ) ;
BDFDB . NotificationUtils . toast ( ` Updated ${ amount } variable ${ amount == 1 ? "" : "s" } in ${ addon . filename } ` , { type : "success" } ) ;
}
else BDFDB . NotificationUtils . toast ( ` There are no changed variables to be updated in ${ addon . filename } ` , { type : "warning" } ) ;
}
else BDFDB . NotificationUtils . toast ( ` Could not find themefile: ${ addon . filename } ` , { type : "error" } ) ;
}
2019-01-26 22:45:19 +01:00
2020-09-19 20:49:33 +02:00
getThemeVars ( css ) {
let vars = css . split ( ":root" ) ;
if ( vars . length > 1 ) {
vars = vars [ 1 ] . replace ( /\t\(/g , " (" ) . replace ( /\r|\t| {2,}/g , "" ) . replace ( /\/\*\n*((?!\/\*|\*\/).|\n)*\n+((?!\/\*|\*\/).|\n)*\n*\*\//g , "" ) . replace ( /\n\/\*.*?\*\//g , "" ) . replace ( /\n/g , "" ) ;
vars = vars . split ( "{" ) ;
vars . shift ( ) ;
vars = vars . join ( "{" ) . replace ( /\s*(:|;|--|\*)\s*/g , "$1" ) ;
vars = vars . split ( "}" ) [ 0 ] ;
return vars . slice ( 2 ) . split ( /;--|\*\/--/ ) ;
}
return [ ] ;
2020-03-28 07:55:39 +01:00
}
2019-01-26 22:45:19 +01:00
2020-11-06 16:14:31 +01:00
createThemeVarInputs ( theme , vars , settingsItems = [ ] ) {
2020-09-19 20:49:33 +02:00
for ( let varStr of vars ) {
varStr = varStr . split ( ":" ) ;
let varName = varStr . shift ( ) . trim ( ) ;
varStr = varStr . join ( ":" ) . split ( /;[^A-z0-9]|\/\*/ ) ;
let varValue = varStr . shift ( ) . trim ( ) ;
if ( varValue ) {
let childType = "text" , childMode = "" ;
let isColor = BDFDB . ColorUtils . getType ( varValue ) ;
let isComp = ! isColor && /^[0-9 ]+,[0-9 ]+,[0-9 ]+$/g . test ( varValue ) ;
if ( isColor || isComp ) {
childType = "color" ;
childMode = isComp && "comp" ;
}
else {
let isUrlFile = /url\(.+\)/gi . test ( varValue ) ;
let isFile = ! isUrlFile && /(http(s)?):\/\/[(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/ . test ( varValue ) ;
if ( isFile || isUrlFile ) {
childType = "file" ;
childMode = isUrlFile && "url" ;
}
2020-03-28 07:55:39 +01:00
}
2020-09-19 20:49:33 +02:00
let varDescription = varStr . join ( "" ) . replace ( /\*\/|\/\*/g , "" ) . replace ( /:/g , ": " ) . replace ( /: \//g , ":/" ) . replace ( /--/g , " --" ) . replace ( /\( --/g , "(--" ) . trim ( ) ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsItem , {
type : "TextInput" ,
2020-10-14 21:08:41 +02:00
margin : 20 ,
dividerBottom : vars [ vars . length - 1 ] != varStr ,
2020-09-19 20:49:33 +02:00
childProps : {
type : childType ,
mode : childMode ,
filter : childType == "file" && "image"
} ,
label : varName [ 0 ] . toUpperCase ( ) + varName . slice ( 1 ) ,
note : varDescription && varDescription . indexOf ( "*" ) == 0 ? varDescription . slice ( 1 ) : varDescription ,
basis : "70%" ,
varName : varName ,
value : varValue ,
placeholder : varValue
} ) ) ;
2018-12-12 12:08:53 +01:00
}
2018-12-11 19:43:51 +01:00
}
2020-09-19 20:49:33 +02:00
2020-11-06 16:14:31 +01:00
return BDFDB . PluginUtils . createSettingsPanel ( theme , settingsItems ) ;
2019-01-15 20:26:33 +01:00
}
2020-09-19 20:49:33 +02:00
} ;
2020-10-09 21:09:35 +02:00
} ) ( window . BDFDB _Global . PluginUtils . buildPlugin ( config ) ) ;
2020-09-19 20:49:33 +02:00
} ) ( ) ;