2020-02-27 08:44:03 +01:00
//META{"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
class ThemeSettings {
2019-01-15 20:26:33 +01:00
getName ( ) { return "ThemeSettings" ; }
2020-01-27 10:37:57 +01:00
getVersion ( ) { return "1.1.7" ; }
2019-01-15 20:26:33 +01:00
getAuthor ( ) { return "DevilBro" ; }
getDescription ( ) { return "Allows you to change Theme Variables within BetterDiscord. Adds a Settings button (similar to Plugins) to customizable Themes in your Themes Page." ; }
2019-01-26 22:45:19 +01:00
2019-09-04 12:34:02 +02:00
constructor ( ) {
2019-09-11 12:14:43 +02:00
this . changelog = {
2019-11-10 23:44:01 +01:00
"improved" : [ [ "New Library Structure & React" , "Restructured my Library and switched to React rendering instead of DOM manipulation" ] ]
2019-09-11 12:14:43 +02:00
} ;
2019-11-14 17:56:26 +01:00
this . patchedModules = {
after : {
V2C _ThemeCard : "render"
}
2019-01-05 23:53:38 +01:00
} ;
}
2018-12-11 19:43:51 +01:00
//legacy
load ( ) { }
start ( ) {
2020-01-17 19:50:31 +01:00
if ( ! window . BDFDB ) window . BDFDB = { myPlugins : { } } ;
if ( window . BDFDB && window . BDFDB . myPlugins && typeof window . BDFDB . myPlugins == "object" ) window . BDFDB . myPlugins [ this . getName ( ) ] = this ;
2020-01-21 12:56:26 +01:00
let libraryScript = document . querySelector ( "head script#BDFDBLibraryScript" ) ;
2019-05-26 13:55:26 +02:00
if ( ! libraryScript || ( performance . now ( ) - libraryScript . getAttribute ( "date" ) ) > 600000 ) {
2018-12-11 19:43:51 +01:00
if ( libraryScript ) libraryScript . remove ( ) ;
libraryScript = document . createElement ( "script" ) ;
2019-05-26 13:55:26 +02:00
libraryScript . setAttribute ( "id" , "BDFDBLibraryScript" ) ;
2018-12-11 19:43:51 +01:00
libraryScript . setAttribute ( "type" , "text/javascript" ) ;
2019-10-18 10:56:41 +02:00
libraryScript . setAttribute ( "src" , "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.min.js" ) ;
2019-01-17 23:48:29 +01:00
libraryScript . setAttribute ( "date" , performance . now ( ) ) ;
2020-01-14 00:06:07 +01:00
libraryScript . addEventListener ( "load" , _ => { this . initialize ( ) ; } ) ;
2018-12-11 19:43:51 +01:00
document . head . appendChild ( libraryScript ) ;
}
2020-01-17 19:50:31 +01:00
else if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) this . initialize ( ) ;
2020-01-14 00:06:07 +01:00
this . startTimeout = setTimeout ( _ => {
2019-11-01 10:27:07 +01:00
try { return this . initialize ( ) ; }
catch ( err ) { console . error ( ` %c[ ${ this . getName ( ) } ]%c ` , "color: #3a71c1; font-weight: 700;" , "" , "Fatal Error: Could not initiate plugin! " + err ) ; }
} , 30000 ) ;
2018-12-11 19:43:51 +01:00
}
initialize ( ) {
2020-01-17 19:50:31 +01:00
if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
2019-01-22 11:05:54 +01:00
if ( this . started ) return ;
2019-10-22 18:55:25 +02:00
BDFDB . PluginUtils . init ( this ) ;
2019-09-11 12:14:43 +02:00
2019-10-23 11:10:01 +02:00
this . dir = BDFDB . BDUtils . getThemesFolder ( ) ;
2019-01-26 22:45:19 +01:00
2019-10-22 18:55:25 +02:00
BDFDB . ModuleUtils . forceAllUpdates ( this ) ;
2018-12-11 19:43:51 +01:00
}
2019-11-01 10:14:50 +01:00
else console . error ( ` %c[ ${ this . getName ( ) } ]%c ` , "color: #3a71c1; font-weight: 700;" , "" , "Fatal Error: Could not load BD functions!" ) ;
2018-12-11 19:43:51 +01:00
}
stop ( ) {
2020-01-17 19:50:31 +01:00
if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
2019-10-22 11:37:23 +02:00
this . stopping = true ;
2019-11-10 23:44:01 +01:00
BDFDB . ModuleUtils . forceAllUpdates ( this ) ;
2019-10-22 18:55:25 +02:00
BDFDB . PluginUtils . clear ( this ) ;
2018-12-11 19:43:51 +01:00
}
}
2019-01-26 22:45:19 +01:00
2018-12-11 19:43:51 +01:00
// begin of own functions
2019-01-26 22:45:19 +01:00
2019-11-10 23:44:01 +01:00
processV2CThemeCard ( e ) {
2019-11-11 10:48:30 +01:00
if ( e . instance . props . theme && ! e . instance . state . settings ) {
2019-11-10 23:44:01 +01:00
let vars = this . getThemeVars ( e . instance . props . theme . css ) ;
2019-01-05 23:53:38 +01:00
if ( vars . length ) {
2019-11-10 23:44:01 +01:00
let [ children , index ] = BDFDB . ReactUtils . findChildren ( e . returnvalue , { props : [ [ "className" , BDFDB . disCN . _repofooter ] ] } ) ;
if ( index == - 1 ) {
let footer = BDFDB . ReactUtils . createElement ( "div" , { className : BDFDB . disCN . _repofooter , children : [ ] } ) ;
e . returnvalue . props . children . push ( footer ) ;
children = footer . props . children ;
2018-12-11 19:43:51 +01:00
}
2020-01-27 10:37:57 +01:00
else {
children [ index ] . props . children = [ children [ index ] . props . children ] . flat ( ) ;
children = children [ index ] . props . children ;
}
2019-11-10 23:44:01 +01:00
children . push ( BDFDB . ReactUtils . createElement ( "button" , {
className : BDFDB . disCNS . _reposettingsbutton ,
children : "Settings" ,
onClick : event => {
let wrapper = BDFDB . DOMUtils . getParent ( BDFDB . dotCN . _reposettingsclosed , event . currentTarget ) ;
BDFDB . DOMUtils . addClass ( wrapper , BDFDB . disCN . _reposettingsopen ) ;
BDFDB . DOMUtils . removeClass ( wrapper , BDFDB . disCN . _reposettingsclosed ) ;
let children = [ ] ;
while ( wrapper . childElementCount ) {
children . push ( wrapper . firstChild ) ;
wrapper . 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> ` ) ;
wrapper . appendChild ( closebutton ) ;
2020-01-14 00:06:07 +01:00
closebutton . addEventListener ( "click" , _ => {
2019-11-10 23:44:01 +01:00
BDFDB . DOMUtils . removeClass ( wrapper , BDFDB . disCN . _reposettingsopen ) ;
BDFDB . DOMUtils . addClass ( wrapper , BDFDB . disCN . _reposettingsclosed ) ;
while ( wrapper . childElementCount ) wrapper . firstChild . remove ( ) ;
while ( children . length ) wrapper . appendChild ( children . shift ( ) ) ;
} )
this . createThemeSettings ( wrapper , e . instance . props . theme , vars ) ;
2018-12-11 19:43:51 +01:00
}
2019-11-10 23:44:01 +01:00
} ) ) ;
2018-12-11 19:43:51 +01:00
}
}
}
2019-01-26 22:45:19 +01:00
2018-12-11 19:43:51 +01:00
getThemeVars ( css ) {
let vars = css . split ( ":root" ) ;
if ( vars . length > 1 ) {
2019-09-27 13:10:10 +02:00
vars = vars [ 1 ] . replace ( /\t\(/g , " (" ) . replace ( /\r|\t| {2,}/g , "" ) . replace ( /\/\*\n*((?!\/\*|\*\/).|\n)*\n+((?!\/\*|\*\/).|\n)*\n*\*\//g , "" ) . replace ( /\n\/\*.*?\*\//g , "" ) . replace ( /\n/g , "" ) ;
2018-12-11 19:43:51 +01:00
vars = vars . split ( "{" ) ;
vars . shift ( ) ;
2019-09-24 13:49:14 +02:00
vars = vars . join ( "{" ) . replace ( /\s*(:|;|--|\*)\s*/g , "$1" ) ;
2018-12-11 21:36:15 +01:00
vars = vars . split ( "}" ) [ 0 ] ;
2018-12-12 12:08:53 +01:00
return vars . slice ( 2 ) . split ( /;--|\*\/--/ ) ;
2018-12-11 19:43:51 +01:00
}
return [ ] ;
}
2019-01-26 22:45:19 +01:00
2019-01-07 20:50:24 +01:00
createThemeSettings ( wrapper , theme , vars ) {
2020-01-17 19:50:31 +01:00
if ( ! window . BDFDB || typeof BDFDB != "object" || ! BDFDB . loaded || ! this . started ) return ;
2019-11-10 23:44:01 +01:00
let settingsitems = [ ] ;
settingsitems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsItem , {
type : "Button" ,
className : BDFDB . disCN . marginbottom8 ,
color : BDFDB . LibraryComponents . Button . Colors . GREEN ,
label : "Update all variables" ,
onClick : _ => {
let path = BDFDB . LibraryRequires . path . join ( this . dir , theme . filename ) ;
let css = BDFDB . LibraryRequires . fs . readFileSync ( path ) . toString ( ) ;
if ( css ) {
let amount = 0 ;
for ( let input of wrapper . querySelectorAll ( BDFDB . dotCN . input ) ) {
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 } ` ) ;
amount ++ ;
}
}
if ( amount > 0 ) {
BDFDB . LibraryRequires . fs . writeFileSync ( path , css ) ;
BDFDB . NotificationUtils . toast ( ` Updated ${ amount } variable ${ amount == 1 ? "" : "s" } in ${ theme . filename } ` , { type : "success" } ) ;
}
else BDFDB . NotificationUtils . toast ( ` There are no changed variables to be updated in ${ theme . filename } ` , { type : "warning" } ) ;
}
else BDFDB . NotificationUtils . toast ( ` Could not find themefile: ${ theme . filename } ` , { type : "error" } ) ;
} ,
children : "Update"
} ) ) ;
2019-01-26 22:45:19 +01:00
2018-12-11 19:43:51 +01:00
for ( let varstr of vars ) {
varstr = varstr . split ( ":" ) ;
2018-12-12 12:08:53 +01:00
let varname = varstr . shift ( ) . trim ( ) ;
2019-01-07 21:19:06 +01:00
varstr = varstr . join ( ":" ) . split ( /;[^A-z0-9]|\/\*/ ) ;
2018-12-12 12:08:53 +01:00
let varvalue = varstr . shift ( ) . trim ( ) ;
2019-09-24 13:49:14 +02:00
if ( varvalue ) {
2019-11-10 23:44:01 +01:00
let childType = "text" , childMode = "" ;
2019-10-23 10:03:33 +02:00
let iscolor = BDFDB . ColorUtils . getType ( varvalue ) ;
2019-09-25 17:35:00 +02:00
let iscomp = ! iscolor && /[0-9 ]+,[0-9 ]+,[0-9 ]+/g . test ( varvalue ) ;
if ( iscolor || iscomp ) {
2019-11-10 23:44:01 +01:00
childType = "color" ;
childMode = iscomp && "comp" ;
2019-09-25 17:35:00 +02:00
}
2019-11-10 23:44:01 +01:00
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" ;
2018-12-12 12:08:53 +01:00
}
2018-12-11 19:43:51 +01:00
}
2019-11-10 23:44:01 +01:00
let vardescription = varstr . join ( "" ) . replace ( /\*\/|\/\*/g , "" ) . replace ( /:/g , ": " ) . replace ( /: \//g , ":/" ) . replace ( /--/g , " --" ) . replace ( /\( --/g , "(--" ) . trim ( ) ;
settingsitems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsItem , {
className : BDFDB . disCN . marginbottom20 ,
dividerbottom : vars [ vars . length - 1 ] != varstr ,
type : "TextInput" ,
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
} ) ) ;
2019-01-15 20:26:33 +01:00
}
2019-11-10 23:44:01 +01:00
}
wrapper . appendChild ( BDFDB . PluginUtils . createSettingsPanel ( theme , settingsitems ) ) ;
2018-12-11 19:43:51 +01:00
}
2019-01-05 23:53:38 +01:00
}