2019-09-20 22:32:52 +02:00
//META{"name":"ThemeSettings","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" ; }
2019-09-27 13:10:10 +02:00
getVersion ( ) { return "1.1.5" ; }
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-09-25 17:35:00 +02:00
"improved" : [ [ "Colorpicker & Filenavigator" , "The plugin now tries to guess if whether an input is used as a colorinput or a fileinput and adds elements to more easily change them" ] ]
2019-09-11 12:14:43 +02:00
} ;
2019-01-05 23:53:38 +01:00
this . patchModules = {
2019-01-07 20:50:24 +01:00
"V2C_ThemeCard" : "componentDidMount"
2019-01-05 23:53:38 +01:00
} ;
}
2018-12-11 19:43:51 +01:00
//legacy
load ( ) { }
start ( ) {
2019-02-04 09:13:15 +01:00
if ( ! global . BDFDB ) global . BDFDB = { myPlugins : { } } ;
if ( global . BDFDB && global . BDFDB . myPlugins && typeof global . BDFDB . myPlugins == "object" ) global . BDFDB . myPlugins [ this . getName ( ) ] = this ;
2019-05-26 13:55:26 +02:00
var libraryScript = document . querySelector ( 'head script#BDFDBLibraryScript' ) ;
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" ) ;
libraryScript . setAttribute ( "src" , "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js" ) ;
2019-01-17 23:48:29 +01:00
libraryScript . setAttribute ( "date" , performance . now ( ) ) ;
2019-05-26 13:55:26 +02:00
libraryScript . addEventListener ( "load" , ( ) => { this . initialize ( ) ; } ) ;
2018-12-11 19:43:51 +01:00
document . head . appendChild ( libraryScript ) ;
2019-05-26 13:55:26 +02:00
this . libLoadTimeout = setTimeout ( ( ) => {
libraryScript . remove ( ) ;
2019-09-11 12:14:43 +02:00
BDFDB . LibraryRequires . request ( "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js" , ( error , response , body ) => {
2019-05-26 13:55:26 +02:00
if ( body ) {
libraryScript = document . createElement ( "script" ) ;
libraryScript . setAttribute ( "id" , "BDFDBLibraryScript" ) ;
libraryScript . setAttribute ( "type" , "text/javascript" ) ;
libraryScript . setAttribute ( "date" , performance . now ( ) ) ;
libraryScript . innerText = body ;
document . head . appendChild ( libraryScript ) ;
}
this . initialize ( ) ;
} ) ;
} , 15000 ) ;
2018-12-11 19:43:51 +01:00
}
2019-01-17 23:48:29 +01:00
else if ( global . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) this . initialize ( ) ;
2018-12-11 19:43:51 +01:00
this . startTimeout = setTimeout ( ( ) => { this . initialize ( ) ; } , 30000 ) ;
}
initialize ( ) {
2019-01-17 23:48:29 +01:00
if ( global . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
2019-01-22 11:05:54 +01:00
if ( this . started ) return ;
2018-12-11 19:43:51 +01:00
BDFDB . loadMessage ( this ) ;
2019-09-11 12:14:43 +02:00
2018-12-11 19:43:51 +01:00
this . dir = BDFDB . getThemesFolder ( ) ;
2019-01-26 22:45:19 +01:00
2019-01-05 23:53:38 +01:00
BDFDB . WebModules . forceAllUpdates ( this ) ;
2018-12-11 19:43:51 +01:00
}
else {
2019-02-12 21:56:34 +01:00
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 ( ) {
2019-01-17 23:48:29 +01:00
if ( global . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
2019-01-05 23:53:38 +01:00
BDFDB . removeEles ( ".themes-settings-button" , ".themes-settings-footer" ) ;
2018-12-11 19:43:51 +01:00
BDFDB . unloadMessage ( this ) ;
}
}
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-01-05 23:53:38 +01:00
processV2CThemeCard ( instance , wrapper ) {
if ( instance . props && instance . props . theme && ! wrapper . querySelector ( BDFDB . dotCN . _reposettingsbutton + ".themes-settings-button" ) ) {
let vars = this . getThemeVars ( instance . props . theme . css ) ;
if ( vars . length ) {
let footer = wrapper . querySelector ( BDFDB . dotCN . _repofooter ) ;
if ( ! footer ) {
footer = document . createElement ( "div" ) ;
footer . className = BDFDB . disCNS . _repofooter + "themes-settings-footer" ;
wrapper . appendChild ( footer ) ;
2018-12-11 19:43:51 +01:00
}
2019-01-05 23:53:38 +01:00
let button = document . createElement ( "button" ) ;
button . className = BDFDB . disCNS . _reposettingsbutton + "themes-settings-button" ;
button . innerText = "Settings" ;
footer . appendChild ( button ) ;
button . addEventListener ( "click" , ( ) => {
2019-01-17 23:48:29 +01:00
BDFDB . addClass ( wrapper , BDFDB . disCN . _reposettingsopen ) ;
BDFDB . removeClass ( wrapper , BDFDB . disCN . _reposettingsclosed ) ;
2019-01-05 23:53:38 +01:00
let children = [ ] ;
while ( wrapper . childElementCount ) {
children . push ( wrapper . firstChild ) ;
wrapper . firstChild . remove ( ) ;
2018-12-11 19:43:51 +01:00
}
2019-01-15 20:26:33 +01:00
let closebutton = BDFDB . htmlToElement ( ` <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> ` ) ;
2019-01-05 23:53:38 +01:00
wrapper . appendChild ( closebutton ) ;
closebutton . addEventListener ( "click" , ( ) => {
2019-01-17 23:48:29 +01:00
BDFDB . removeClass ( wrapper , BDFDB . disCN . _reposettingsopen ) ;
BDFDB . addClass ( wrapper , BDFDB . disCN . _reposettingsclosed ) ;
2019-01-05 23:53:38 +01:00
while ( wrapper . childElementCount ) wrapper . firstChild . remove ( ) ;
while ( children . length ) wrapper . appendChild ( children . shift ( ) ) ;
} )
2019-01-07 20:50:24 +01:00
this . createThemeSettings ( wrapper , instance . props . theme , vars ) ;
2019-01-05 23:53:38 +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 ) {
2019-01-22 11:28:32 +01:00
if ( ! global . BDFDB || typeof BDFDB != "object" || ! BDFDB . loaded || ! this . started ) return ;
2019-10-08 11:51:41 +02:00
var settingshtml = ` <div class="theme-settings" id="theme-settings- ${ theme . name } "><div class=" ${ theme . name } -settings BDFDB-settings"><div class=" ${ BDFDB . disCNS . titledefault + BDFDB . disCNS . size18 + BDFDB . disCNS . height24 + BDFDB . disCNS . weightnormal + BDFDB . disCN . marginbottom8 } "> ${ BDFDB . encodeToHTML ( theme . name ) } </div><div class="BDFDB-settings-inner"><div class=" ${ BDFDB . disCNS . flex + BDFDB . disCNS . horizontal + BDFDB . disCNS . justifystart + BDFDB . disCNS . aligncenter + BDFDB . disCNS . nowrap + BDFDB . disCN . marginbottom8 } " style="flex: 0 0 auto;"><h3 class=" ${ BDFDB . disCNS . titledefault + BDFDB . disCNS . marginreset + BDFDB . disCNS . weightmedium + BDFDB . disCNS . size16 + BDFDB . disCNS . height24 + BDFDB . disCN . flexchild } " style="flex: 1 1 auto;">Update all variables</h3><button type="button" class=" ${ BDFDB . disCNS . flexchild + BDFDB . disCNS . button + BDFDB . disCNS . buttonlookfilled + BDFDB . disCNS . buttoncolorgreen + BDFDB . disCNS . buttonsizemedium + BDFDB . disCN . buttongrow } update-button" style="flex: 0 0 auto;"><div class=" ${ BDFDB . disCN . buttoncontents } ">Update</div></button></div></div></div> ` ;
2019-01-26 22:45:19 +01:00
2019-01-15 20:26:33 +01:00
let settingspanel = BDFDB . htmlToElement ( settingshtml ) ;
2019-04-18 09:28:20 +02:00
var settingspanelinner = settingspanel . querySelector ( ".BDFDB-settings-inner" ) ;
2019-01-26 22:45:19 +01:00
2019-01-17 23:48:29 +01:00
var maxwidth = BDFDB . getRects ( wrapper ) . width - 80 ;
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 ) {
let vardescription = varstr . join ( "" ) . replace ( /\*\/|\/\*/g , "" ) . replace ( /:/g , ": " ) . replace ( /: \//g , ":/" ) . replace ( /--/g , " --" ) . replace ( /\( --/g , "(--" ) . trim ( ) ;
vardescription = vardescription && vardescription . indexOf ( "*" ) == 0 ? vardescription . slice ( 1 ) : vardescription ;
2019-10-08 11:51:41 +02:00
let varcontainer = BDFDB . htmlToElement ( ` <div class=" ${ BDFDB . disCNS . flex + BDFDB . disCNS . horizontal + BDFDB . disCNS . directioncolumn + BDFDB . disCNS . justifystart + BDFDB . disCNS . alignstretch + BDFDB . disCNS . nowrap + BDFDB . disCN . marginbottom20 } varcontainer" style="flex: 1 1 auto;"><div class=" ${ BDFDB . disCNS . flex + BDFDB . disCNS . horizontal + BDFDB . disCNS . justifystart + BDFDB . disCNS . aligncenter + BDFDB . disCN . nowrap } " style="flex: 1 1 auto;"><h3 class=" ${ BDFDB . disCNS . titledefault + BDFDB . disCNS . weightmedium + BDFDB . disCNS . size16 + BDFDB . disCN . flexchild } BDFDB-textscrollwrapper" style="flex: 0 0 30%;"><div class="BDFDB-textscroll"> ${ varname [ 0 ] . toUpperCase ( ) + varname . slice ( 1 ) } </div></h3><div class=" ${ BDFDB . disCNS . inputwrapper + BDFDB . disCNS . vertical + BDFDB . disCNS . flex2 + BDFDB . disCN . directioncolumn } " style="flex: 1 1 auto;"><input type="text" option=" ${ varname } " class=" ${ BDFDB . disCNS . inputdefault + BDFDB . disCNS . input + BDFDB . disCN . size16 } varinput"></div><button type="button" class=" ${ BDFDB . disCN . colorpickerswatch } single-swatch" style="background-color: black;"></button><button type="button" class=" ${ BDFDB . disCNS . flexchild + BDFDB . disCNS . button + BDFDB . disCNS . buttonlookfilled + BDFDB . disCNS . buttoncolorbrand + BDFDB . disCNS . buttonsizemedium + BDFDB . disCN . buttongrow } file-navigator" style="flex: 0 0 auto;"><div class=" ${ BDFDB . disCN . buttoncontents } "></div><input type="file" accept="image/*" style="display:none!important;"></button></div> ${ vardescription ? ` <div class=" ${ BDFDB . disCNS . description + BDFDB . disCNS . note + BDFDB . disCN . primary } BDFDB-textscrollwrapper" style="flex: 1 1 auto; max-width: ${ maxwidth } px !important;"><div class="BDFDB-textscroll"> ${ BDFDB . encodeToHTML ( vardescription ) } </div></div> ` : "" } ${ vars [ vars . length - 1 ] == varstr ? '' : ` <div class=" ${ BDFDB . disCNS . modaldivider + BDFDB . disCN . modaldividerdefault } "></div> ` } </div> ` ) ;
2019-09-24 13:49:14 +02:00
let varinput = varcontainer . querySelector ( BDFDB . dotCN . input ) ;
2019-09-25 17:35:00 +02:00
varinput . value = varvalue ;
varinput . setAttribute ( "placeholder" , varvalue ) ;
let swatch = varcontainer . querySelector ( ".single-swatch" ) ;
let navigator = varcontainer . querySelector ( ".file-navigator" ) ;
let iscolor = BDFDB . colorTYPE ( varvalue ) ;
let iscomp = ! iscolor && /[0-9 ]+,[0-9 ]+,[0-9 ]+/g . test ( varvalue ) ;
let isurlfile = ! iscolor && ! iscolor && /url\(.+\)/gi . test ( varvalue ) ;
let isfile = ! iscolor && ! iscolor && ! isurlfile && /(http(s)?):\/\/[(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/ . test ( varvalue ) ;
if ( iscolor || iscomp ) {
let color = iscomp ? BDFDB . colorCONVERT ( varvalue . split ( "," ) , "RGB" ) : varvalue ;
swatch . style . setProperty ( "background-color" , color , "important" ) ;
swatch . addEventListener ( "click" , e => {
BDFDB . openColorPicker ( varcontainer , e . currentTarget , color , { gradient : false , comp : iscomp , alpha : iscolor } ) ;
} ) ;
}
else BDFDB . removeEles ( swatch ) ;
if ( isurlfile || isfile ) {
navigator . addEventListener ( "change" , e => {
let file = navigator . querySelector ( "input" ) . files [ 0 ] ;
if ( file && file . type . indexOf ( "image" ) == 0 ) varinput . value = ` ${ isurlfile ? "url('" : "" } data: ${ file . type } ;base64, ${ BDFDB . LibraryRequires . fs . readFileSync ( file . path ) . toString ( "base64" ) } ${ isurlfile ? "')" : "" } ` ;
else varinput . value = varvalue ;
} ) ;
}
else BDFDB . removeEles ( navigator ) ;
2019-09-24 13:49:14 +02:00
settingspanelinner . appendChild ( varcontainer ) ;
}
2018-12-12 12:13:27 +01:00
}
2019-01-26 22:45:19 +01:00
2019-01-15 20:26:33 +01:00
BDFDB . initElements ( settingspanel , this ) ;
2018-12-11 19:43:51 +01:00
2019-01-17 23:48:29 +01:00
BDFDB . addEventListener ( this , settingspanel , "click" , ".update-button" , ( ) => {
2019-09-11 12:14:43 +02:00
let path = BDFDB . LibraryRequires . path . join ( this . dir , theme . filename ) ;
let css = BDFDB . LibraryRequires . fs . readFileSync ( path ) . toString ( ) ;
2019-01-15 20:26:33 +01:00
if ( css ) {
let amount = 0 ;
for ( let input of settingspanel . querySelectorAll ( BDFDB . dotCN . input ) ) {
let oldvalue = input . getAttribute ( "placeholder" ) ;
let newvalue = input . value ;
if ( newvalue && newvalue . trim ( ) && newvalue != oldvalue ) {
let varname = input . getAttribute ( "option" ) ;
css = css . replace ( new RegExp ( ` -- ${ BDFDB . regEscape ( varname ) } ( \\ s*):( \\ s*) ${ BDFDB . regEscape ( oldvalue ) } ` , "g" ) , ` -- ${ varname } $ 1: $ 2 ${ newvalue } ` ) ;
amount ++ ;
2018-12-12 12:08:53 +01:00
}
2018-12-11 19:43:51 +01:00
}
2019-01-15 20:26:33 +01:00
if ( amount > 0 ) {
2019-09-11 12:14:43 +02:00
BDFDB . LibraryRequires . fs . writeFileSync ( path , css ) ;
2019-01-15 20:26:33 +01:00
BDFDB . showToast ( ` Updated ${ amount } variable ${ amount == 1 ? "" : "s" } in ${ theme . filename } ` , { type : "success" } ) ;
}
else BDFDB . showToast ( ` There are no changed variables to be updated in ${ theme . filename } ` , { type : "warning" } ) ;
}
else BDFDB . showToast ( ` Could not find themefile: ${ theme . filename } ` , { type : "error" } ) ;
} ) ;
2019-01-26 22:45:19 +01:00
2019-01-07 20:50:24 +01:00
wrapper . appendChild ( settingspanel ) ;
2018-12-11 19:43:51 +01:00
}
2019-01-05 23:53:38 +01:00
}