2015-08-27 15:46:53 +02:00
/ * B e t t e r D i s c o r d A p p C o r e J a v a S c r i p t
2017-04-30 03:11:22 +02:00
* Version : 1.78
2015-08-27 15:46:53 +02:00
* Author : Jiiks | http : //jiiks.net
* Date : 27 / 08 / 2015 - 16 : 36
2016-04-30 23:25:14 +02:00
* Last Update : 01 / 05 / 2016
2015-08-27 15:46:53 +02:00
* https : //github.com/Jiiks/BetterDiscordApp
* /
2017-01-09 06:41:36 +01:00
2018-01-09 04:24:00 +01:00
/* global Proxy, bdplugins, bdthemes, betterDiscordIPC, bdVersion, version, BDV2, webpackJsonp */
2017-11-03 04:05:33 +01:00
/* eslint-disable no-console */
2017-01-11 10:21:17 +01:00
/*Localstorage fix*/
( function ( ) {
let _ _fs = window . require ( "fs" ) ;
2017-01-22 19:00:24 +01:00
let _ _process = window . require ( "process" ) ;
let _ _platform = _ _process . platform ;
2017-01-26 08:44:28 +01:00
let _ _dataPath = ( _ _platform === 'win32' ? _ _process . env . APPDATA : _ _platform === 'darwin' ? _ _process . env . HOME + '/Library/Preferences' : process . env . HOME + '/.config' ) + '/BetterDiscord/' ;
2018-01-09 04:24:00 +01:00
let localStorageFile = "localStorage.json" ;
2017-01-22 19:00:24 +01:00
2017-01-11 11:43:46 +01:00
let _ _data = { } ;
2018-01-09 04:24:00 +01:00
if ( _ _fs . existsSync ( ` ${ _ _dataPath } ${ localStorageFile } ` ) ) {
2017-01-22 19:00:24 +01:00
try {
2018-01-09 04:24:00 +01:00
_ _data = JSON . parse ( _ _fs . readFileSync ( ` ${ _ _dataPath } ${ localStorageFile } ` ) ) ;
2017-01-22 19:00:24 +01:00
} catch ( err ) {
console . log ( err ) ;
}
2018-01-09 04:24:00 +01:00
} else if ( _ _fs . existsSync ( localStorageFile ) ) {
2017-01-11 10:21:17 +01:00
try {
2018-01-09 04:24:00 +01:00
_ _data = JSON . parse ( _ _fs . readFileSync ( localStorageFile ) ) ;
2017-01-11 10:23:15 +01:00
} catch ( err ) {
console . log ( err ) ;
}
2017-01-11 10:21:17 +01:00
}
2017-01-11 11:43:46 +01:00
var _ _ls = _ _data ;
_ _ls . setItem = function ( i , v ) {
2017-01-11 10:21:17 +01:00
_ _ls [ i ] = v ;
2017-01-11 11:43:46 +01:00
this . save ( ) ;
2017-01-11 10:21:17 +01:00
} ;
_ _ls . getItem = function ( i ) {
2017-01-11 19:59:24 +01:00
return _ _ls [ i ] || null ;
2017-01-11 10:21:17 +01:00
} ;
2017-01-11 11:43:46 +01:00
_ _ls . save = function ( ) {
2018-01-09 04:24:00 +01:00
_ _fs . writeFileSync ( ` ${ _ _dataPath } ${ localStorageFile } ` , JSON . stringify ( this ) , null , 4 ) ;
2017-01-11 10:21:17 +01:00
} ;
2017-01-11 11:43:46 +01:00
var _ _proxy = new Proxy ( _ _ls , {
2017-11-03 04:05:33 +01:00
set : function ( target , name , val ) {
2017-01-11 11:43:46 +01:00
_ _ls [ name ] = val ;
_ _ls . save ( ) ;
} ,
2017-11-03 04:05:33 +01:00
get : function ( target , name ) {
2017-01-11 19:59:24 +01:00
return _ _ls [ name ] || null ;
2017-01-11 11:43:46 +01:00
}
} ) ;
window . localStorage = _ _proxy ;
2017-01-11 10:25:20 +01:00
} ) ( ) ;
2017-01-11 10:21:17 +01:00
2017-04-30 03:11:22 +02:00
( ( ) => {
let v2Loader = document . createElement ( 'div' ) ;
v2Loader . className = "bd-loaderv2" ;
v2Loader . title = "BetterDiscord is loading..." ;
document . body . appendChild ( v2Loader ) ;
} ) ( ) ;
2017-01-09 06:41:36 +01:00
window . bdStorage = { } ;
window . bdStorage . get = function ( i ) {
return betterDiscordIPC . sendSync ( 'synchronous-message' , { 'arg' : 'storage' , 'cmd' : 'get' , 'var' : i } ) ;
} ;
window . bdStorage . set = function ( i , v ) {
betterDiscordIPC . sendSync ( 'synchronous-message' , { 'arg' : 'storage' , 'cmd' : 'set' , 'var' : i , 'data' : v } ) ;
} ;
window . bdPluginStorage = { } ;
window . bdPluginStorage . get = function ( pn , i ) {
return betterDiscordIPC . sendSync ( 'synchronous-message' , { 'arg' : 'pluginstorage' , 'cmd' : 'get' , 'pn' : pn , 'var' : i } ) ;
} ;
window . bdPluginStorage . set = function ( pn , i , v ) {
betterDiscordIPC . sendSync ( 'synchronous-message' , { 'arg' : 'pluginstorage' , 'cmd' : 'set' , 'pn' : pn , 'var' : i , 'data' : v } ) ;
} ;
betterDiscordIPC . on ( 'asynchronous-reply' , ( event , arg ) => {
console . log ( event ) ;
console . log ( arg ) ;
} ) ;
2018-01-09 04:24:00 +01:00
var settingsPanel , emoteModule , utils , quickEmoteMenu , voiceMode , pluginModule , themeModule , dMode , publicServersModule ;
2017-06-17 19:08:43 +02:00
var jsVersion = 1.792 ;
2017-01-09 09:38:52 +01:00
var supportedVersion = "0.2.81" ;
2018-01-10 02:08:59 +01:00
var bbdVersion = "0.0.5" ;
2015-08-29 11:36:47 +02:00
var mainObserver ;
2015-08-27 15:46:53 +02:00
var twitchEmoteUrlStart = "https://static-cdn.jtvnw.net/emoticons/v1/" ;
var twitchEmoteUrlEnd = "/1.0" ;
var ffzEmoteUrlStart = "https://cdn.frankerfacez.com/emoticon/" ;
var ffzEmoteUrlEnd = "/1" ;
2015-12-10 04:01:24 +01:00
var bttvEmoteUrlStart = "https://cdn.betterttv.net/emote/" ;
var bttvEmoteUrlEnd = "/1x" ;
2015-08-27 15:46:53 +02:00
2015-10-26 06:27:55 +01:00
var mainCore ;
2015-08-27 15:46:53 +02:00
2015-08-29 11:36:47 +02:00
var settings = {
2016-04-09 21:56:29 +02:00
"Save logs locally" : { "id" : "bda-gs-0" , "info" : "Saves chat logs locally" , "implemented" : false , "hidden" : false , "cat" : "core" } ,
2018-01-09 04:24:00 +01:00
"Public Servers" : { "id" : "bda-gs-1" , "info" : "Display public servers button" , "implemented" : false , "hidden" : false , "cat" : "core" } ,
2017-10-30 22:24:54 +01:00
"Minimal Mode" : { "id" : "bda-gs-2" , "info" : "Hide elements and reduce the size of elements." , "implemented" : true , "hidden" : false , "cat" : "core" } ,
2016-04-09 21:56:29 +02:00
"Voice Mode" : { "id" : "bda-gs-4" , "info" : "Only show voice chat" , "implemented" : true , "hidden" : false , "cat" : "core" } ,
2017-10-30 22:24:54 +01:00
"Hide Channels" : { "id" : "bda-gs-3" , "info" : "Hide channels in minimal mode" , "implemented" : true , "hidden" : false , "cat" : "core" } ,
2016-04-09 21:56:29 +02:00
"Dark Mode" : { "id" : "bda-gs-5" , "info" : "Make certain elements dark by default(wip)" , "implemented" : true , "hidden" : false , "cat" : "core" } ,
"Override Default Emotes" : { "id" : "bda-es-5" , "info" : "Override default emotes" , "implemented" : false , "hidden" : false , "cat" : "core" } ,
"Voice Disconnect" : { "id" : "bda-dc-0" , "info" : "Disconnect from voice server when closing Discord" , "implemented" : true , "hidden" : false , "cat" : "core" } ,
2016-05-06 20:31:20 +02:00
"Custom css live update" : { "id" : "bda-css-0" , "info" : "" , "implemented" : true , "hidden" : true , "cat" : "core" } ,
"Custom css auto udpate" : { "id" : "bda-css-1" , "info" : "" , "implemented" : true , "hidden" : true , "cat" : "core" } ,
"24 Hour Timestamps" : { "id" : "bda-gs-6" , "info" : "Replace 12hr timestamps with proper ones" , "implemented" : true , "hidden" : false , "cat" : "core" } ,
2016-05-20 04:30:54 +02:00
"Coloured Text" : { "id" : "bda-gs-7" , "info" : "Make text colour the same as role colour" , "implemented" : true , "hidden" : false , "cat" : "core" } ,
2017-04-30 03:11:22 +02:00
"BetterDiscord Blue" : { "id" : "bda-gs-b" , "info" : "Replace Discord blue with BD Blue" , "implemented" : true , "hidden" : false , "cat" : "core" } ,
2017-12-22 20:29:59 +01:00
"Developer Mode" : { "id" : "bda-gs-8" , "info" : "Developer Mode" , "implemented" : true , "hidden" : false , "cat" : "core" } ,
2017-12-24 07:51:24 +01:00
"Startup Error Modal" : { "id" : "fork-ps-1" , "info" : "Show a modal with plugin/theme errors on startup" , "implemented" : true , "hidden" : false , "cat" : "fork" } ,
"Show Toasts" : { "id" : "fork-ps-2" , "info" : "Shows a small notification for starting and stopping plugins & themes" , "implemented" : true , "hidden" : false , "cat" : "fork" } ,
2018-01-09 18:16:48 +01:00
"Scroll To Settings" : { "id" : "fork-ps-3" , "info" : "Auto-scrolls to a plugin's settings when the button is clicked (only if out of view)" , "implemented" : true , "hidden" : false , "cat" : "fork" } ,
2017-12-24 07:51:24 +01:00
"Emote Modifier Tooltip" : { "id" : "fork-es-1" , "info" : "Shows the emote modifier in the tooltip." , "implemented" : true , "hidden" : false , "cat" : "fork" } ,
"Animate On Hover" : { "id" : "fork-es-2" , "info" : "Only animate the emote modifiers on hover" , "implemented" : true , "hidden" : false , "cat" : "fork" } ,
"Copy Selector" : { "id" : "fork-dm-1" , "info" : "Adds a \"Copy Selector\" option to context menus when developer mode is active" , "implemented" : true , "hidden" : false , "cat" : "fork" } ,
2016-04-09 21:56:29 +02:00
2016-05-20 04:30:54 +02:00
"Twitch Emotes" : { "id" : "bda-es-7" , "info" : "Show Twitch emotes" , "implemented" : true , "hidden" : false , "cat" : "emote" } ,
2016-04-09 21:56:29 +02:00
"FrankerFaceZ Emotes" : { "id" : "bda-es-1" , "info" : "Show FrankerFaceZ Emotes" , "implemented" : true , "hidden" : false , "cat" : "emote" } ,
"BetterTTV Emotes" : { "id" : "bda-es-2" , "info" : "Show BetterTTV Emotes" , "implemented" : true , "hidden" : false , "cat" : "emote" } ,
"Emote Menu" : { "id" : "bda-es-0" , "info" : "Show Twitch/Favourite emotes in emote menu" , "implemented" : true , "hidden" : false , "cat" : "emote" } ,
"Emoji Menu" : { "id" : "bda-es-9" , "info" : "Show Discord emoji menu" , "implemented" : true , "hidden" : false , "cat" : "emote" } ,
"Emote Autocomplete" : { "id" : "bda-es-3" , "info" : "Autocomplete emote commands" , "implemented" : false , "hidden" : false , "cat" : "emote" } ,
"Emote Auto Capitalization" : { "id" : "bda-es-4" , "info" : "Autocapitalize emote commands" , "implemented" : true , "hidden" : false , "cat" : "emote" } ,
2016-05-20 04:30:54 +02:00
"Show Names" : { "id" : "bda-es-6" , "info" : "Show emote names on hover" , "implemented" : true , "hidden" : false , "cat" : "emote" } ,
2017-12-22 20:29:59 +01:00
"Show emote modifiers" : { "id" : "bda-es-8" , "info" : "Enable emote mods (flip, spin, pulse, spin2, spin3, 1spin, 2spin, 3spin, tr, bl, br, shake, shake2, shake3, flap)" , "implemented" : true , "hidden" : false , "cat" : "emote" } ,
2016-01-08 16:33:43 +01:00
} ;
2015-08-29 11:36:47 +02:00
2017-11-03 04:05:33 +01:00
// var links = {
// "Jiiks.net": { "text": "Jiiks.net", "href": "thtp://jiiks.net", "target": "_blank" },
// "twitter": { "text": "Twitter", "href": "http://twitter.com/jiiksi", "target": "_blank" },
// "github": { "text": "Github", "href": "http://github.com/jiiks", "target": "_blank" }
// };
2015-11-27 01:14:33 +01:00
2015-08-29 11:36:47 +02:00
var defaultCookie = {
2016-01-08 16:33:43 +01:00
"version" : jsVersion ,
2015-11-29 18:21:58 +01:00
"bda-gs-0" : false ,
2017-10-29 08:23:43 +01:00
"bda-gs-1" : false ,
2015-12-23 22:48:59 +01:00
"bda-gs-2" : false ,
2015-11-29 18:21:58 +01:00
"bda-gs-3" : false ,
"bda-gs-4" : false ,
2016-04-09 14:51:59 +02:00
"bda-gs-5" : true ,
2016-05-06 20:31:20 +02:00
"bda-gs-6" : false ,
"bda-gs-7" : false ,
2016-05-24 22:33:24 +02:00
"bda-gs-8" : false ,
2015-11-29 18:21:58 +01:00
"bda-es-0" : true ,
2015-12-23 09:56:16 +01:00
"bda-es-1" : true ,
2015-12-23 22:48:59 +01:00
"bda-es-2" : true ,
2015-11-29 18:21:58 +01:00
"bda-es-3" : false ,
"bda-es-4" : false ,
"bda-es-5" : true ,
"bda-es-6" : true ,
"bda-es-7" : true ,
2017-04-30 03:11:22 +02:00
"bda-gs-b" : true ,
2016-04-02 09:56:19 +02:00
"bda-es-8" : true ,
2016-04-08 00:21:30 +02:00
"bda-jd" : true ,
"bda-dc-0" : false ,
"bda-css-0" : false ,
2016-04-09 08:04:34 +02:00
"bda-css-1" : false ,
2017-12-24 07:51:24 +01:00
"bda-es-9" : true ,
"fork-dm-1" : false ,
"fork-ps-1" : true ,
"fork-ps-2" : true ,
"fork-ps-3" : true ,
"fork-es-1" : true ,
"fork-es-2" : false ,
2015-11-29 18:21:58 +01:00
} ;
2015-08-29 11:36:47 +02:00
var settingsCookie = { } ;
2015-08-27 15:46:53 +02:00
2017-11-03 21:01:49 +01:00
var bdpluginErrors , bdthemeErrors ; // define for backwards compatibility
2018-01-09 04:24:00 +01:00
var bdConfig = null ;
function Core ( config ) {
if ( ! config ) {
config = {
branch : "master" ,
repo : "rauenzi" ,
updater : {
CDN : "cdn.rawgit.com"
}
}
}
else config . newLoader = true ;
window . bdConfig = config ;
}
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
Core . prototype . init = function ( ) {
2015-11-27 11:07:59 +01:00
var self = this ;
2016-04-30 23:25:14 +02:00
var lVersion = ( typeof ( version ) === "undefined" ) ? bdVersion : version ;
if ( lVersion < supportedVersion ) {
this . alert ( "Not Supported" , "BetterDiscord v" + lVersion + "(your version)" + " is not supported by the latest js(" + jsVersion + ").<br><br> Please download the latest version from <a href='https://betterdiscord.net' target='_blank'>BetterDiscord.net</a>" ) ;
2015-10-26 06:27:55 +01:00
return ;
}
2015-08-29 11:36:47 +02:00
2015-08-27 15:46:53 +02:00
utils = new Utils ( ) ;
2015-11-01 12:37:04 +01:00
utils . getHash ( ) ;
2018-01-09 04:24:00 +01:00
publicServersModule = new V2 _PublicServers ( ) ;
2015-08-27 15:46:53 +02:00
emoteModule = new EmoteModule ( ) ;
quickEmoteMenu = new QuickEmoteMenu ( ) ;
2015-10-26 06:27:55 +01:00
voiceMode = new VoiceMode ( ) ;
2016-05-24 22:33:24 +02:00
dMode = new devMode ( ) ;
2015-08-27 15:46:53 +02:00
2017-12-22 20:29:59 +01:00
utils . log ( "Initializing Settings" ) ;
2015-08-29 11:36:47 +02:00
this . initSettings ( ) ;
2015-10-26 06:27:55 +01:00
//Incase were too fast
function gwDefer ( ) {
console . log ( new Date ( ) . getTime ( ) + " Defer" ) ;
2017-10-29 08:00:33 +01:00
if ( document . querySelectorAll ( '.guilds .guild' ) . length > 0 ) {
2015-10-26 06:27:55 +01:00
console . log ( new Date ( ) . getTime ( ) + " Defer Loaded" ) ;
2017-11-01 06:43:07 +01:00
self . injectExternals ( ) ;
2017-11-03 20:58:30 +01:00
2018-01-09 22:32:02 +01:00
utils . log ( "Initializing EmoteModule" ) ;
emoteModule . init ( ) ;
2018-01-20 02:17:52 +01:00
utils . log ( "Updating Settings" ) ;
settingsPanel = new V2 _SettingsPanel ( ) ;
settingsPanel . updateSettings ( ) ;
2017-11-03 20:58:30 +01:00
// Add check for backwards compatibility
2017-11-03 21:02:50 +01:00
if ( ! bdpluginErrors ) bdpluginErrors = [ ] ;
if ( ! bdthemeErrors ) bdthemeErrors = [ ] ;
2017-11-03 20:58:30 +01:00
2017-12-22 20:29:59 +01:00
utils . log ( "Loading Plugins" ) ;
2015-12-12 07:07:56 +01:00
pluginModule = new PluginModule ( ) ;
pluginModule . loadPlugins ( ) ;
2017-11-01 16:10:16 +01:00
2017-12-22 20:29:59 +01:00
utils . log ( "Loading Themes" ) ;
2017-11-01 16:10:16 +01:00
themeModule = new ThemeModule ( ) ;
themeModule . loadThemes ( ) ;
2015-12-12 07:07:56 +01:00
2018-01-09 18:16:48 +01:00
$ ( "#customcss" ) . detach ( ) . appendTo ( document . head ) ;
2017-12-22 20:29:59 +01:00
utils . log ( "Initializing QuickEmoteMenu" ) ;
2018-01-09 22:32:02 +01:00
quickEmoteMenu . init ( ) ;
2016-04-07 14:22:33 +02:00
2016-04-08 00:21:30 +02:00
window . addEventListener ( "beforeunload" , function ( ) {
if ( settingsCookie [ "bda-dc-0" ] ) {
2017-10-29 21:33:48 +01:00
document . querySelector ( '.btn.btn-disconnect' ) . click ( ) ;
2016-04-08 00:21:30 +02:00
}
} ) ;
2018-01-09 04:24:00 +01:00
publicServersModule . initialize ( ) ;
2015-10-26 06:27:55 +01:00
emoteModule . autoCapitalize ( ) ;
2015-11-29 18:21:58 +01:00
/*Display new features in BetterDiscord*/
2016-01-08 16:33:43 +01:00
if ( settingsCookie [ "version" ] < jsVersion ) {
2017-10-30 01:00:34 +01:00
//var cl = self.constructChangelog();
2015-11-29 18:21:58 +01:00
settingsCookie [ "version" ] = jsVersion ;
self . saveSettings ( ) ;
}
2015-12-27 16:39:10 +01:00
2017-12-22 20:29:59 +01:00
utils . log ( "Removing Loading Icon" ) ;
2017-04-30 03:11:22 +02:00
document . getElementsByClassName ( "bd-loaderv2" ) [ 0 ] . remove ( ) ;
2017-11-03 18:54:47 +01:00
// Show loading errors
2017-12-24 07:51:24 +01:00
if ( settingsCookie [ "fork-ps-1" ] ) {
2017-12-22 20:29:59 +01:00
utils . log ( "Collecting Startup Errors" ) ;
2017-11-03 18:54:47 +01:00
self . showStartupErrors ( ) ;
}
2017-12-22 20:29:59 +01:00
utils . log ( "Initializing Main Observer" ) ;
2017-11-01 06:43:07 +01:00
self . initObserver ( ) ;
2015-08-31 15:20:33 +02:00
} else {
2015-10-26 06:27:55 +01:00
setTimeout ( gwDefer , 100 ) ;
2015-08-31 15:20:33 +02:00
}
2015-10-26 06:27:55 +01:00
}
2015-08-31 15:59:34 +02:00
2016-01-08 16:33:43 +01:00
$ ( document ) . ready ( function ( ) {
2015-10-26 06:27:55 +01:00
setTimeout ( gwDefer , 1000 ) ;
} ) ;
} ;
2015-08-27 15:46:53 +02:00
2017-11-01 06:28:53 +01:00
Core . prototype . injectExternals = function ( ) {
2018-01-10 02:08:59 +01:00
utils . injectJs ( "https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/ace.js" )
// utils.injectJs("https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.10.1/min/vs/loader.js");
2018-01-09 04:24:00 +01:00
/*utils.injectJs("https:/ / cdnjs . cloudflare . com / ajax / libs / codemirror / 5.25 . 0 / codemirror . min . js " ) ;
2017-11-01 06:28:53 +01:00
utils . injectJs ( "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.0/mode/css/css.min.js" ) ;
utils . injectJs ( "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.0/addon/scroll/simplescrollbars.min.js" ) ;
utils . injectCss ( "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.0/addon/scroll/simplescrollbars.min.css" ) ;
utils . injectCss ( "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.25.0/theme/material.min.css" ) ;
2018-01-09 04:24:00 +01:00
utils . injectJs ( "https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.4.2/Sortable.min.js" ) ; * /
2017-11-01 06:28:53 +01:00
} ;
2016-01-08 16:33:43 +01:00
Core . prototype . initSettings = function ( ) {
if ( $ . cookie ( "better-discord" ) == undefined ) {
2015-08-29 11:36:47 +02:00
settingsCookie = defaultCookie ;
this . saveSettings ( ) ;
} else {
this . loadSettings ( ) ;
2017-11-09 14:23:20 +01:00
$ ( '<style id="customcss">' ) . html ( atob ( window . bdStorage . get ( "bdcustomcss" ) ) ) . appendTo ( document . head ) ;
2016-01-08 16:33:43 +01:00
for ( var setting in defaultCookie ) {
if ( settingsCookie [ setting ] == undefined ) {
2015-10-26 06:27:55 +01:00
settingsCookie [ setting ] = defaultCookie [ setting ] ;
2015-08-29 11:36:47 +02:00
this . saveSettings ( ) ;
}
2015-08-27 15:46:53 +02:00
}
}
2015-10-26 06:27:55 +01:00
} ;
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
Core . prototype . saveSettings = function ( ) {
$ . cookie ( "better-discord" , JSON . stringify ( settingsCookie ) , {
expires : 365 ,
path : '/'
} ) ;
2015-10-26 06:27:55 +01:00
} ;
2015-08-29 11:36:47 +02:00
2016-01-08 16:33:43 +01:00
Core . prototype . loadSettings = function ( ) {
2015-08-29 11:36:47 +02:00
settingsCookie = JSON . parse ( $ . cookie ( "better-discord" ) ) ;
2015-10-26 06:27:55 +01:00
} ;
2016-04-09 08:04:34 +02:00
2016-01-08 16:33:43 +01:00
Core . prototype . initObserver = function ( ) {
2017-10-30 21:53:27 +01:00
let self = this ;
2016-01-08 16:33:43 +01:00
mainObserver = new MutationObserver ( function ( mutations ) {
2016-05-21 11:19:29 +02:00
2016-01-08 16:33:43 +01:00
mutations . forEach ( function ( mutation ) {
2016-05-21 11:19:29 +02:00
2016-04-04 16:22:53 +02:00
if ( typeof pluginModule !== "undefined" ) pluginModule . rawObserver ( mutation ) ;
2016-05-06 20:31:20 +02:00
2017-10-30 22:04:48 +01:00
// onSwitch()
// leaving Activity Feed/Friends menu
2017-10-30 21:53:27 +01:00
if ( mutation . removedNodes . length && mutation . removedNodes [ 0 ] instanceof Element ) {
let node = mutation . removedNodes [ 0 ] ;
if ( node . classList . contains ( "activityFeed-HeiGwL" ) || node . id === "friends" ) {
pluginModule . channelSwitch ( ) ;
2016-05-06 20:31:20 +02:00
}
2017-10-30 21:53:27 +01:00
}
2017-10-30 22:04:48 +01:00
// if there was nothing added, skip
2017-10-30 21:53:27 +01:00
if ( ! mutation . addedNodes . length || ! ( mutation . addedNodes [ 0 ] instanceof Element ) ) return ;
let node = mutation . addedNodes [ 0 ] ;
2018-01-10 02:08:59 +01:00
if ( node . classList . contains ( "layer" ) || node . classList . contains ( "layer-kosS71" ) ) {
2017-11-01 06:28:53 +01:00
if ( node . querySelector ( ".guild-settings-base-section" ) ) node . setAttribute ( 'layer-id' , 'server-settings' ) ;
2017-12-24 07:51:24 +01:00
if ( node . getElementsByClassName ( "socialLinks-1oZoF3" ) . length ) {
2017-11-01 06:28:53 +01:00
node . setAttribute ( 'layer-id' , 'user-settings' ) ;
if ( ! node . querySelector ( "#bd-settings-sidebar" ) ) settingsPanel . renderSidebar ( ) ;
}
}
2017-10-30 22:04:48 +01:00
// Emoji Picker
2017-12-22 20:29:59 +01:00
if ( node . classList . contains ( 'popout' ) && ! node . classList . contains ( 'popout-left' ) ) {
2018-01-09 22:32:02 +01:00
if ( node . getElementsByClassName ( 'emoji-picker' ) . length || node . getElementsByClassName ( 'emojiPicker-3g68GS' ) . length ) quickEmoteMenu . obsCallback ( node ) ;
2017-10-30 22:04:48 +01:00
}
// onSwitch()
2017-11-09 14:18:24 +01:00
// Not a channel, but still a switch (Activity Feed/Friends menu/NSFW check)
2017-11-03 18:34:26 +01:00
if ( node . classList . contains ( "activityFeed-HeiGwL" ) || node . id === "friends" ) {
2017-10-30 21:53:27 +01:00
pluginModule . channelSwitch ( ) ;
}
2017-10-30 22:04:48 +01:00
// onSwitch()
2017-10-30 21:53:27 +01:00
// New Channel
2017-11-09 14:18:24 +01:00
if ( node . classList . contains ( "messages-wrapper" ) || node . querySelector ( ".messages-wrapper" ) ) {
2017-10-30 21:53:27 +01:00
self . inject24Hour ( node ) ;
self . injectColoredText ( node ) ;
pluginModule . channelSwitch ( ) ;
}
2017-10-30 22:04:48 +01:00
// onMessage
2017-10-30 21:53:27 +01:00
// New Message Group
2018-01-09 18:16:48 +01:00
if ( node . classList . contains ( "message-group" ) ) {
2017-10-30 21:53:27 +01:00
self . inject24Hour ( node ) ;
self . injectColoredText ( node ) ;
2018-01-09 18:16:48 +01:00
if ( ! node . querySelector ( ".message-sending" ) && node . parentElement && node . parentElement . children && node == node . parentElement . children [ node . parentElement . children . length - 1 ] ) {
2017-10-30 22:04:48 +01:00
pluginModule . newMessage ( ) ;
2016-05-06 20:31:20 +02:00
}
2015-08-29 11:36:47 +02:00
}
2017-10-30 21:53:27 +01:00
2018-01-09 18:16:48 +01:00
if ( node . classList . contains ( "message-text" ) ) {
self . injectColoredText ( node . parentElement . parentElement . parentElement . parentElement ) ;
}
2017-10-30 22:04:48 +01:00
// onMessage
2017-10-30 21:53:27 +01:00
// Single Message
2018-01-09 18:16:48 +01:00
if ( node . classList . contains ( "message" ) ) {
2017-10-30 21:53:27 +01:00
self . injectColoredText ( node . parentElement . parentElement ) ;
2018-01-09 18:16:48 +01:00
if ( ! node . classList . contains ( "message-sending" ) ) pluginModule . newMessage ( ) ;
2017-10-30 21:53:27 +01:00
}
2015-08-29 11:36:47 +02:00
emoteModule . obsCallback ( mutation ) ;
} ) ;
} ) ;
2015-10-26 06:27:55 +01:00
//noinspection JSCheckFunctionSignatures
2016-01-08 16:33:43 +01:00
mainObserver . observe ( document , {
childList : true ,
subtree : true
} ) ;
2015-10-26 06:27:55 +01:00
} ;
2015-08-29 11:36:47 +02:00
2017-10-30 21:53:27 +01:00
Core . prototype . inject24Hour = function ( node ) {
if ( ! settingsCookie [ "bda-gs-6" ] ) return ;
2017-11-04 03:43:59 +01:00
node . querySelectorAll ( '.timestamp' ) . forEach ( elem => {
if ( elem . getAttribute ( "data-24" ) ) return ;
let text = elem . innerText || elem . textContent ;
let matches = /([^0-9]*)([0-9]?[0-9]:[0-9][0-9])([^0-9]*)/ . exec ( text ) ;
if ( matches == null ) return ;
if ( matches . length < 4 ) return ;
2017-11-04 06:59:30 +01:00
let time = matches [ 2 ] . split ( ':' ) ;
let hours = parseInt ( time [ 0 ] ) ;
let minutes = time [ 1 ] ;
let timeOfDay = matches [ 3 ] . toLowerCase ( ) ;
if ( timeOfDay . includes ( "am" ) && hours == 12 ) hours -= 12 ;
2018-01-09 18:16:48 +01:00
else if ( timeOfDay . includes ( "pm" ) && hours < 12 ) hours += 12 ;
2017-11-04 06:59:30 +01:00
hours = ( "0" + hours ) . slice ( - 2 ) ;
2017-11-04 03:43:59 +01:00
elem . innerText = matches [ 1 ] + hours + ":" + minutes + matches [ 3 ] ;
2017-11-04 06:59:30 +01:00
elem . setAttribute ( "data-24" , matches [ 2 ] ) ;
2017-11-04 03:43:59 +01:00
} ) ;
} ;
2017-11-04 06:59:30 +01:00
Core . prototype . remove24Hour = function ( node ) {
2017-10-30 21:53:27 +01:00
node . querySelectorAll ( '.timestamp' ) . forEach ( elem => {
2017-11-04 06:59:30 +01:00
if ( ! elem . getAttribute ( "data-24" ) ) return ;
let time = elem . getAttribute ( "data-24" ) ;
elem . removeAttribute ( "data-24" ) ;
2017-10-30 21:53:27 +01:00
let text = elem . innerText || elem . textContent ;
2017-11-04 06:59:30 +01:00
let matches = /([^0-9]*)([0-9]?[0-9]:[0-9][0-9])([^0-9]*)/ . exec ( text ) ;
2017-10-30 21:53:27 +01:00
if ( matches == null ) return ;
2017-11-04 06:59:30 +01:00
if ( matches . length < 4 ) return ;
elem . innerText = matches [ 1 ] + time + matches [ 3 ] ;
2017-10-30 21:53:27 +01:00
} ) ;
} ;
Core . prototype . injectColoredText = function ( node ) {
if ( ! settingsCookie [ "bda-gs-7" ] ) return ;
node . querySelectorAll ( '.user-name' ) . forEach ( elem => {
let color = elem . style . color ;
if ( color === "rgb(255, 255, 255)" ) return ;
elem . closest ( ".message-group" ) . querySelectorAll ( '.markup' ) . forEach ( elem => {
2018-01-09 22:32:02 +01:00
if ( elem . getAttribute ( "data-colour" ) ) return ;
elem . setAttribute ( "data-colour" , true ) ;
2017-10-30 21:53:27 +01:00
elem . style . setProperty ( "color" , color ) ;
} ) ;
} ) ;
} ;
2017-11-04 06:59:30 +01:00
Core . prototype . removeColoredText = function ( node ) {
node . querySelectorAll ( '.user-name' ) . forEach ( elem => {
elem . closest ( ".message-group" ) . querySelectorAll ( '.markup' ) . forEach ( elem => {
2018-01-09 22:32:02 +01:00
if ( ! elem . getAttribute ( "data-colour" ) ) return ;
elem . removeAttribute ( "data-colour" ) ;
2017-11-04 06:59:30 +01:00
elem . style . setProperty ( "color" , "" ) ;
} ) ;
} ) ;
} ;
2017-11-03 18:34:26 +01:00
Core . prototype . alert = function ( title , content ) {
let modal = $ ( ` <div class="bd-modal-wrapper theme-dark">
< div class = "bd-backdrop backdrop-2ohBEd" > < / d i v >
< div class = "bd-modal modal-2LIEKY" >
< div class = "bd-modal-inner inner-1_1f7b" >
< div class = "header header-3sp3cE" >
< div class = "title" > $ { title } < / d i v >
< / d i v >
< div class = "bd-modal-body" >
< div class = "scroller-wrap fade" >
< div class = "scroller" >
$ { content }
< / d i v >
< / d i v >
< / d i v >
< div class = "footer footer-1PYmcw" >
< button type = "button" > Okay < / b u t t o n >
< / d i v >
< / d i v >
< / d i v >
< / d i v > ` ) ;
modal . find ( '.footer button' ) . on ( 'click' , ( ) => {
modal . addClass ( 'closing' ) ;
setTimeout ( ( ) => { modal . remove ( ) ; } , 300 ) ;
} ) ;
modal . find ( '.bd-backdrop' ) . on ( 'click' , ( ) => {
modal . addClass ( 'closing' ) ;
setTimeout ( ( ) => { modal . remove ( ) ; } , 300 ) ;
} ) ;
modal . appendTo ( "#app-mount" ) ;
} ;
Core . prototype . showStartupErrors = function ( ) {
2017-11-03 20:52:35 +01:00
if ( ! bdpluginErrors || ! bdthemeErrors ) return ;
if ( ! bdpluginErrors . length && ! bdthemeErrors . length ) return ;
2017-11-03 18:34:26 +01:00
let modal = $ ( ` <div class="bd-modal-wrapper theme-dark">
< div class = "bd-backdrop backdrop-2ohBEd" > < / d i v >
< div class = "bd-modal bd-startup-modal modal-2LIEKY" >
< div class = "bd-modal-inner inner-1_1f7b" >
< div class = "header header-3sp3cE" > < div class = "title" > Startup Errors < / d i v > < / d i v >
< div class = "bd-modal-body" >
< div class = "tab-bar-container" >
< div class = "tab-bar TOP" >
< div class = "tab-bar-item" > Plugins < / d i v >
< div class = "tab-bar-item" > Themes < / d i v >
< / d i v >
< / d i v >
< div class = "table-header" >
< div class = "table-column column-name" > Name < / d i v >
< div class = "table-column column-reason" > Reason < / d i v >
< div class = "table-column column-error" > Error < / d i v >
< / d i v >
< div class = "scroller-wrap fade" >
< div class = "scroller" >
< / d i v >
< / d i v >
< / d i v >
< div class = "footer footer-1PYmcw" >
< button type = "button" > Okay < / b u t t o n >
< / d i v >
< / d i v >
< / d i v >
< / d i v > ` ) ;
function generateTab ( errors ) {
let container = $ ( ` <div class="errors"> ` ) ;
for ( let err of errors ) {
let error = $ ( ` <div class="error">
< div class = "table-column column-name" > $ { err . name ? err . name : err . file } < / d i v >
< div class = "table-column column-reason" > $ { err . reason } < / d i v >
< div class = "table-column column-error" > < a class = "error-link" href = "" > $ { err . error ? err . error . message : "" } < / a > < / d i v >
< / d i v > ` ) ;
container . append ( error ) ;
if ( err . error ) {
error . find ( 'a' ) . on ( 'click' , ( e ) => {
e . preventDefault ( ) ;
utils . err ( ` Error details for ${ err . name ? err . name : err . file } . ` , err . error ) ;
} ) ;
}
}
return container ;
}
let tabs = [ generateTab ( bdpluginErrors ) , generateTab ( bdthemeErrors ) ] ;
modal . find ( '.tab-bar-item' ) . on ( 'click' , ( e ) => {
e . preventDefault ( ) ;
modal . find ( '.tab-bar-item' ) . removeClass ( 'selected' ) ;
$ ( e . target ) . addClass ( 'selected' ) ;
modal . find ( '.scroller' ) . empty ( ) . append ( tabs [ $ ( e . target ) . index ( ) ] ) ;
} ) ;
modal . find ( '.footer button' ) . on ( 'click' , ( ) => {
modal . addClass ( 'closing' ) ;
setTimeout ( ( ) => { modal . remove ( ) ; } , 300 ) ;
} ) ;
modal . find ( '.bd-backdrop' ) . on ( 'click' , ( ) => {
modal . addClass ( 'closing' ) ;
setTimeout ( ( ) => { modal . remove ( ) ; } , 300 ) ;
} ) ;
modal . appendTo ( "#app-mount" ) ;
modal . find ( '.tab-bar-item' ) [ 0 ] . click ( ) ;
} ;
2017-11-03 20:52:35 +01:00
/ * *
* This shows a toast similar to android towards the bottom of the screen .
*
* @ param { string } content The string to show in the toast .
* @ param { object } options Options object . Optional parameter .
* @ param { string } options . type Changes the type of the toast stylistically and semantically . Choices : "" , "info" , "success" , "danger" / "error" , "warning" / "warn" . Default : ""
* @ param { boolean } options . icon Determines whether the icon should show corresponding to the type . A toast without type will always have no icon . Default : true
* @ param { number } options . timeout Adjusts the time ( in ms ) the toast should be shown for before disappearing automatically . Default : 3000
* /
Core . prototype . showToast = function ( content , options = { } ) {
if ( ! document . querySelector ( '.bd-toasts' ) ) {
let toastWrapper = document . createElement ( "div" ) ;
toastWrapper . classList . add ( "bd-toasts" ) ;
let boundingElement = document . querySelector ( '.chat form, #friends, .noChannel-2EQ0a9, .activityFeed-HeiGwL' ) ;
toastWrapper . style . setProperty ( "left" , boundingElement ? boundingElement . getBoundingClientRect ( ) . left + "px" : "0px" ) ;
toastWrapper . style . setProperty ( "width" , boundingElement ? boundingElement . offsetWidth + "px" : "100%" ) ;
toastWrapper . style . setProperty ( "bottom" , ( document . querySelector ( '.chat form' ) ? document . querySelector ( '.chat form' ) . offsetHeight : 80 ) + "px" ) ;
document . querySelector ( '.app' ) . appendChild ( toastWrapper ) ;
}
const { type = "" , icon = true , timeout = 3000 } = options ;
let toastElem = document . createElement ( "div" ) ;
toastElem . classList . add ( "bd-toast" ) ;
if ( type ) toastElem . classList . add ( "toast-" + type ) ;
if ( type && icon ) toastElem . classList . add ( "icon" ) ;
toastElem . innerText = content ;
document . querySelector ( '.bd-toasts' ) . appendChild ( toastElem ) ;
setTimeout ( ( ) => {
toastElem . classList . add ( 'closing' ) ;
setTimeout ( ( ) => {
toastElem . remove ( ) ;
if ( ! document . querySelectorAll ( '.bd-toasts .bd-toast' ) . length ) document . querySelector ( '.bd-toasts' ) . remove ( ) ;
} , 300 ) ;
} , timeout ) ;
} ;
2017-10-30 23:14:26 +01:00
2015-08-27 15:46:53 +02:00
/ * B e t t e r D i s c o r d A p p E m o t e M o d u l e J a v a S c r i p t
2015-10-26 06:27:55 +01:00
* Version : 1.5
2015-08-27 15:46:53 +02:00
* Author : Jiiks | http : //jiiks.net
* Date : 26 / 08 / 2015 - 15 : 29
2015-10-14 08:50:34 +02:00
* Last Update : 14 / 10 / 2015 - 09 : 48
2015-08-27 15:46:53 +02:00
* https : //github.com/Jiiks/BetterDiscordApp
* Note : Due to conflicts autocapitalize only supports global emotes
* /
2015-10-26 06:27:55 +01:00
/ *
* = Changelog =
* - v1 . 5
* -- Twitchemotes . com api
* /
2015-08-27 15:46:53 +02:00
var emotesFfz = { } ;
var emotesBTTV = { } ;
2017-11-03 04:05:33 +01:00
var emotesBTTV2 = { } ;
2018-01-09 04:24:00 +01:00
var emotesTwitch = { } ;
2015-10-26 06:27:55 +01:00
var subEmotesTwitch = { } ;
2015-08-27 15:46:53 +02:00
2018-01-09 04:24:00 +01:00
window . bdEmotes = {
TwitchGlobal : { } ,
TwitchSubscriber : { } ,
BTTV : { } ,
2018-01-24 00:08:20 +01:00
FrankerFaceZ : { } ,
2018-01-09 04:24:00 +01:00
BTTV2 : { }
}
window . bdEmoteSettingIDs = {
TwitchGlobal : "bda-es-7" ,
TwitchSubscriber : "bda-es-7" ,
BTTV : "bda-es-2" ,
2018-01-24 00:08:20 +01:00
FrankerFaceZ : "bda-es-1" ,
BTTV2 : "bda-es-2"
2018-01-09 04:24:00 +01:00
}
2016-01-08 16:33:43 +01:00
function EmoteModule ( ) { }
2015-08-29 11:36:47 +02:00
2018-01-09 04:24:00 +01:00
EmoteModule . prototype . init = function ( ) {
this . modifiers = [ "flip" , "spin" , "pulse" , "spin2" , "spin3" , "1spin" , "2spin" , "3spin" , "tr" , "bl" , "br" , "shake" , "shake2" , "shake3" , "flap" ] ;
2018-01-20 02:17:52 +01:00
this . overrides = [ 'twitch' , 'bttv' , 'ffz' ] ;
2018-01-09 04:24:00 +01:00
this . categories = Object . keys ( window . bdEmoteSettingIDs ) ;
let emoteInfo = {
'TwitchGlobal' : {
url : 'https://twitchemotes.com/api_cache/v3/global.json' ,
backup : "https://" + bdConfig . updater . CDN + '/' + bdConfig . repo + '/BetterDiscordApp/' + bdConfig . hash + '/data/emotedata_twitch_global.json' ,
variable : 'TwitchGlobal' ,
getEmoteURL : ( e ) => ` https://static-cdn.jtvnw.net/emoticons/v1/ ${ e . id } /1.0 `
} ,
'TwitchSubscriber' : {
url : 'https://twitchemotes.com/api_cache/v3/subscriber.json' ,
backup : "https://" + bdConfig . updater . CDN + '/' + bdConfig . repo + '/BetterDiscordApp/' + bdConfig . hash + '/data/emotedata_twitch_subscriber.json' ,
variable : 'TwitchSubscriber' ,
parser : ( data ) => {
let emotes = { } ;
for ( let c in data ) {
let channel = data [ c ] ;
for ( let e = 0 , elen = channel . emotes . length ; e < elen ; e ++ ) {
let emote = channel . emotes [ e ] ;
emotes [ emote . code ] = emote . id ;
}
}
return emotes ;
} ,
getEmoteURL : ( e ) => ` https://static-cdn.jtvnw.net/emoticons/v1/ ${ e } /1.0 `
} ,
'FrankerFaceZ' : {
url : "https://" + bdConfig . updater . CDN + '/' + bdConfig . repo + '/BetterDiscordApp/' + bdConfig . hash + '/data/emotedata_ffz.json' ,
variable : 'FrankerFaceZ' ,
getEmoteURL : ( e ) => ` https://cdn.frankerfacez.com/emoticon/ ${ e } /1 `
} ,
'BTTV' : {
url : 'https://api.betterttv.net/emotes' ,
variable : 'BTTV' ,
parser : ( data ) => {
let emotes = { } ;
for ( let e = 0 , len = data . emotes . length ; e < len ; e ++ ) {
let emote = data . emotes [ e ] ;
emotes [ emote . regex ] = emote . url ;
}
return emotes ;
} ,
getEmoteURL : ( e ) => ` ${ e } `
} ,
'BTTV2' : {
url : "https://" + bdConfig . updater . CDN + '/' + bdConfig . repo + '/BetterDiscordApp/' + bdConfig . hash + '/data/emotedata_bttv.json' ,
variable : 'BTTV2' ,
getEmoteURL : ( e ) => ` https://cdn.betterttv.net/emote/ ${ e } /1x `
}
} ;
if ( ! bdConfig . newLoader ) {
window . bdEmotes = {
TwitchGlobal : emotesTwitch ,
TwitchSubscriber : subEmotesTwitch ,
BTTV : emotesBTTV ,
2018-01-24 00:08:20 +01:00
FrankerFaceZ : emotesFfz ,
BTTV2 : emotesBTTV2
2018-01-09 04:24:00 +01:00
}
for ( let type in window . bdEmotes ) {
for ( let emote in window . bdEmotes [ type ] ) {
window . bdEmotes [ type ] [ emote ] = emoteInfo [ type ] . getEmoteURL ( window . bdEmotes [ type ] [ emote ] ) ;
}
}
return ;
}
this . loadEmoteData ( emoteInfo ) ;
} ;
EmoteModule . prototype . clearEmoteData = async function ( ) {
let _fs = require ( "fs" ) ;
let emoteFile = "emote_data.json" ;
let file = bdConfig . dataPath + emoteFile ;
let exists = _fs . existsSync ( file ) ;
if ( exists ) _fs . unlinkSync ( file ) ;
window . bdEmotes = {
TwitchGlobal : { } ,
TwitchSubscriber : { } ,
BTTV : { } ,
2018-01-24 00:08:20 +01:00
FrankerFaceZ : { } ,
2018-01-09 04:24:00 +01:00
BTTV2 : { }
}
} ;
EmoteModule . prototype . loadEmoteData = async function ( emoteInfo ) {
let _fs = require ( "fs" ) ;
let emoteFile = "emote_data.json" ;
let file = bdConfig . dataPath + emoteFile ;
let exists = _fs . existsSync ( file ) ;
2018-01-09 18:16:48 +01:00
2018-01-09 04:24:00 +01:00
if ( exists && ! bdConfig . cache . expired ) {
2018-01-09 18:16:48 +01:00
mainCore . showToast ( "Loading emotes from cache." , { type : "info" } ) ;
2018-01-09 04:24:00 +01:00
utils . log ( "[Emotes] Loading emotes from local cache." )
let data = _fs . readFileSync ( file , "utf8" ) ;
2018-01-09 18:16:48 +01:00
let isValid = this . testJSON ( data ) ;
2018-01-09 04:24:00 +01:00
2018-01-09 18:16:48 +01:00
if ( isValid ) bdEmotes = JSON . parse ( data ) ;
for ( let e in emoteInfo ) {
isValid = Object . keys ( bdEmotes [ emoteInfo [ e ] . variable ] ) . length > 0 ;
2018-01-09 04:24:00 +01:00
}
2018-01-09 18:16:48 +01:00
if ( isValid ) {
mainCore . showToast ( "Emotes successfully loaded." , { type : "success" } )
return ;
2018-01-09 04:24:00 +01:00
}
2018-01-09 18:16:48 +01:00
utils . log ( "[Emotes] Cache was corrupt, downloading..." )
_fs . unlinkSync ( file ) ;
2018-01-09 04:24:00 +01:00
}
2018-01-09 18:16:48 +01:00
mainCore . showToast ( "Downloading emotes in the background do not reload." , { type : "info" } ) ;
2018-01-09 04:24:00 +01:00
for ( let e in emoteInfo ) {
let data = await this . downloadEmotes ( emoteInfo [ e ] ) ;
bdEmotes [ emoteInfo [ e ] . variable ] = data ;
}
2018-01-09 18:16:48 +01:00
mainCore . showToast ( "All emotes successfully downloaded." , { type : "success" } ) ;
2018-01-09 04:24:00 +01:00
try { _fs . writeFileSync ( file , JSON . stringify ( bdEmotes ) , "utf8" ) ; }
catch ( err ) { utils . err ( "[Emotes] Could not save emote data." , err ) ; }
2018-01-09 22:32:02 +01:00
quickEmoteMenu . init ( ) ;
2018-01-09 04:24:00 +01:00
}
EmoteModule . prototype . downloadEmotes = function ( emoteMeta ) {
let request = require ( "request" ) ;
let options = {
url : emoteMeta . url ,
timeout : emoteMeta . timeout ? emoteMeta . timeout : 5000
} ;
utils . log ( "[Emotes] Downloading: " + emoteMeta . variable ) ;
return new Promise ( ( resolve , reject ) => {
request ( options , ( error , response , body ) => {
if ( error ) {
utils . err ( "[Emotes] Could not download " + emoteMeta . variable , error )
if ( emoteMeta . backup ) {
emoteMeta . url = emoteMeta . backup ;
emoteMeta . backup = null ;
return this . downloadEmotes ( emoteMeta ) ;
}
reject ( { } ) ;
}
else {
let parsedData = JSON . parse ( body ) ;
if ( typeof ( emoteMeta . parser ) === "function" ) parsedData = emoteMeta . parser ( parsedData ) ;
for ( let emote in parsedData ) {
parsedData [ emote ] = emoteMeta . getEmoteURL ( parsedData [ emote ] ) ;
}
resolve ( parsedData ) ;
2018-01-24 00:08:20 +01:00
utils . log ( "[Emotes] Downloaded: " + emoteMeta . variable ) ;
2018-01-09 04:24:00 +01:00
}
} ) ;
} ) ;
}
EmoteModule . prototype . testJSON = function ( data ) {
try {
let json = JSON . parse ( data ) ;
return true ;
}
catch ( err ) {
return false ;
}
return false ;
}
2015-11-01 12:57:10 +01:00
2016-01-08 16:33:43 +01:00
EmoteModule . prototype . getBlacklist = function ( ) {
2017-11-04 16:04:50 +01:00
$ . getJSON ( "https://cdn.rawgit.com/Jiiks/betterDiscordApp/" + _hash + "/data/emotefilter.json" , function ( data ) {
2016-01-08 16:33:43 +01:00
bemotes = data . blacklist ;
} ) ;
2015-11-01 12:44:25 +01:00
} ;
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
EmoteModule . prototype . obsCallback = function ( mutation ) {
2015-08-29 11:36:47 +02:00
var self = this ;
2016-05-24 22:33:24 +02:00
2016-01-08 16:33:43 +01:00
for ( var i = 0 ; i < mutation . addedNodes . length ; ++ i ) {
2015-08-29 11:36:47 +02:00
var next = mutation . addedNodes . item ( i ) ;
2016-01-08 16:33:43 +01:00
if ( next ) {
2015-08-29 11:36:47 +02:00
var nodes = self . getNodes ( next ) ;
2016-01-08 16:33:43 +01:00
for ( var node in nodes ) {
if ( nodes . hasOwnProperty ( node ) ) {
2016-05-21 11:19:29 +02:00
var elem = nodes [ node ] . parentElement ;
if ( elem && elem . classList . contains ( 'edited' ) ) {
2018-01-20 02:17:52 +01:00
self . injectEmote ( elem , true ) ;
2016-05-21 11:19:29 +02:00
} else {
self . injectEmote ( nodes [ node ] ) ;
}
2015-10-26 06:27:55 +01:00
}
2015-08-29 11:36:47 +02:00
}
}
}
2015-10-26 06:27:55 +01:00
} ;
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
EmoteModule . prototype . getNodes = function ( node ) {
2015-08-27 15:46:53 +02:00
var next ;
var nodes = [ ] ;
2015-10-31 22:49:42 +01:00
var treeWalker = document . createTreeWalker ( node , NodeFilter . SHOW _TEXT , null , false ) ;
2015-08-27 15:46:53 +02:00
2017-11-03 04:05:33 +01:00
// eslint-disable-next-line no-cond-assign
2016-01-08 16:33:43 +01:00
while ( next = treeWalker . nextNode ( ) ) {
2015-08-27 15:46:53 +02:00
nodes . push ( next ) ;
}
return nodes ;
2015-10-26 06:27:55 +01:00
} ;
2015-08-27 15:46:53 +02:00
2015-11-01 12:44:25 +01:00
var bemotes = [ ] ;
2015-08-27 15:46:53 +02:00
2018-01-20 02:17:52 +01:00
EmoteModule . prototype . injectEmote = async function ( node , edited ) {
2018-01-09 18:16:48 +01:00
if ( ! node . parentElement || ( ! node . parentElement . classList . contains ( "markup" ) && ! node . parentElement . classList . contains ( "message-content" ) ) ) return ;
2018-01-09 04:24:00 +01:00
let messageScroller = document . querySelector ( '.messages.scroller' ) ;
let message = node . parentElement ;
2018-01-20 02:17:52 +01:00
let editNode = null ;
// if (edited) editNode = $(message).children('.edited').detach();
2018-01-09 04:24:00 +01:00
let words = message . innerHTML . split ( /([^\s]+)([\s]|$)/g ) . filter ( function ( e ) { return e ; } ) ;
2015-08-27 15:46:53 +02:00
2018-01-20 02:17:52 +01:00
let inject = function ( message , messageScroller , category , emoteName , emoteModifier ) {
let inCategory = bdEmotes [ category ] . hasOwnProperty ( emoteName ) ;
if ( ! inCategory || ! settingsCookie [ bdEmoteSettingIDs [ category ] ] ) return false ;
let url = bdEmotes [ category ] [ emoteName ] ;
let element = this . createEmoteElement ( emoteName , url , emoteModifier ) ;
let oldHeight = message . offsetHeight ;
message . innerHTML = message . innerHTML . replace ( new RegExp ( ` ([ \\ s]|^) ${ emoteModifier ? emoteName + ":" + emoteModifier : emoteName } ([ \\ s]| $ ) ` , "g" ) , ` $ 1 ${ element } $ 2 ` ) ;
messageScroller . scrollTop = messageScroller . scrollTop + ( message . offsetHeight - oldHeight ) ;
return true ;
}
inject = inject . bind ( this , message , messageScroller ) ;
2018-01-09 04:24:00 +01:00
for ( let w = 0 , len = words . length ; w < len ; w ++ ) {
let emote = words [ w ] ;
let emoteSplit = emote . split ( ':' ) ;
let emoteName = emoteSplit [ 0 ] ;
let emoteModifier = emoteSplit [ 1 ] ? emoteSplit [ 1 ] : "" ;
2018-01-20 02:17:52 +01:00
let emoteOverride = emoteModifier . slice ( 0 ) ;
2016-01-08 16:33:43 +01:00
2018-01-09 04:55:12 +01:00
if ( bemotes . includes ( emoteName ) || emoteName . length < 4 ) continue ;
2018-01-09 04:24:00 +01:00
if ( ! this . modifiers . includes ( emoteModifier ) || ! settingsCookie [ "bda-es-8" ] ) emoteModifier = "" ;
2018-01-20 02:17:52 +01:00
if ( ! this . overrides . includes ( emoteOverride ) ) emoteOverride = "" ;
if ( emoteOverride === "twitch" ) {
let tglobal = false ;
let tsubscriber = false ;
tglobal = inject ( "TwitchGlobal" , emoteName , emoteOverride ) ;
if ( ! tglobal ) tsubscriber = inject ( "TwitchSubscriber" , emoteName , emoteOverride ) ;
if ( tglobal || tsubscriber ) continue ;
}
else if ( emoteOverride === "bttv" ) {
let bttv = false ;
let bttv2 = false ;
bttv = inject ( "BTTV" , emoteName , emoteOverride ) ;
if ( ! bttv ) bttv2 = inject ( "BTTV2" , emoteName , emoteOverride ) ;
if ( bttv || bttv2 ) continue ;
}
else if ( emoteOverride === "ffz" ) {
let ffz = inject ( "FrankerFaceZ" , emoteName , emoteOverride ) ;
if ( ffz ) continue ;
}
2016-05-21 11:19:29 +02:00
2018-01-09 04:24:00 +01:00
for ( let c = 0 , clen = this . categories . length ; c < clen ; c ++ ) {
2018-01-20 02:17:52 +01:00
inject ( this . categories [ c ] , emoteName , emoteModifier ) ;
2018-01-09 04:24:00 +01:00
}
2016-05-21 11:19:29 +02:00
2018-01-09 04:24:00 +01:00
if ( emote == "[!s]" ) message . classList . add ( "spoiler" ) ;
2016-05-21 11:19:29 +02:00
}
2018-01-20 02:17:52 +01:00
// if (edited) $(message).append(editNode);
2016-05-21 11:19:29 +02:00
} ;
2016-01-08 16:33:43 +01:00
2016-05-21 11:19:29 +02:00
EmoteModule . prototype . createEmoteElement = function ( word , url , mod ) {
var len = Math . round ( word . length / 4 ) ;
var name = word . substr ( 0 , len ) + "\uFDD9" + word . substr ( len , len ) + "\uFDD9" + word . substr ( len * 2 , len ) + "\uFDD9" + word . substr ( len * 3 ) ;
2018-01-09 04:24:00 +01:00
var stopAnim = settingsCookie [ 'fork-es-2' ] ? " stop-animation" : "" ;
var modClass = mod ? "emote" + mod : "" ;
var html = '<span class="emotewrapper"><img draggable="false" style="max-height:32px;" data-modifier="' + mod + '" class="emote ' + modClass + stopAnim + '" alt="' + name + '" src="' + url + '"/><input onclick=\'quickEmoteMenu.favorite("' + name + '", "' + url + '");\' class="fav" title="Favorite!" type="button"></span>' ;
return html . replace ( new RegExp ( "\uFDD9" , "g" ) , "" ) ;
2015-10-26 06:27:55 +01:00
} ;
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
EmoteModule . prototype . autoCapitalize = function ( ) {
2015-10-26 06:27:55 +01:00
2015-08-27 15:46:53 +02:00
var self = this ;
2015-08-31 15:36:28 +02:00
2017-10-29 21:33:48 +01:00
$ ( 'body' ) . delegate ( $ ( ".channelTextArea-1HTP3C textarea:first" ) , 'keyup change paste' , function ( ) {
2016-01-08 16:33:43 +01:00
if ( ! settingsCookie [ "bda-es-4" ] ) return ;
2015-08-27 15:46:53 +02:00
2017-10-29 21:33:48 +01:00
var text = $ ( ".channelTextArea-1HTP3C textarea:first" ) . val ( ) ;
2016-01-08 16:33:43 +01:00
if ( text == undefined ) return ;
2015-08-29 11:36:47 +02:00
2015-08-27 15:46:53 +02:00
var lastWord = text . split ( " " ) . pop ( ) ;
2016-01-08 16:33:43 +01:00
if ( lastWord . length > 3 ) {
if ( lastWord == "danSgame" ) return ;
2015-08-27 15:46:53 +02:00
var ret = self . capitalize ( lastWord . toLowerCase ( ) ) ;
2016-01-08 16:33:43 +01:00
if ( ret !== null && ret !== undefined ) {
2017-10-29 21:33:48 +01:00
utils . insertText ( utils . getTextArea ( ) [ 0 ] , text . replace ( lastWord , ret ) ) ;
2015-08-27 15:46:53 +02:00
}
}
} ) ;
2015-10-26 06:27:55 +01:00
} ;
2015-08-27 15:46:53 +02:00
2016-01-08 16:33:43 +01:00
EmoteModule . prototype . capitalize = function ( value ) {
2018-01-09 04:24:00 +01:00
var res = bdEmotes . TwitchGlobal ;
2016-01-08 16:33:43 +01:00
for ( var p in res ) {
if ( res . hasOwnProperty ( p ) && value == ( p + '' ) . toLowerCase ( ) ) {
2015-12-11 07:43:36 +01:00
return p ;
}
2015-08-27 15:46:53 +02:00
}
2015-10-26 06:27:55 +01:00
} ;
2016-12-05 21:05:48 +01:00
2017-04-30 03:11:22 +02:00
/ * B e t t e r D i s c o r d A p p Q u i c k E m o t e M e n u J a v a S c r i p t
* Version : 1.3
* Author : Jiiks | http : //jiiks.net
* Date : 26 / 08 / 2015 - 11 : 49
* Last Update : 29 / 08 / 2015 - 11 : 46
* https : //github.com/Jiiks/BetterDiscordApp
* /
2015-12-31 18:27:43 +01:00
2017-04-30 03:11:22 +02:00
function QuickEmoteMenu ( ) {
2015-12-31 18:27:43 +01:00
}
2017-04-30 03:11:22 +02:00
QuickEmoteMenu . prototype . init = function ( ) {
2015-12-31 18:27:43 +01:00
2017-04-30 03:11:22 +02:00
$ ( document ) . on ( "mousedown" , function ( e ) {
if ( e . target . id != "rmenu" ) $ ( "#rmenu" ) . remove ( ) ;
} ) ;
this . favoriteEmotes = { } ;
2017-11-03 04:05:33 +01:00
var fe = window . bdStorage . get ( "bdfavemotes" ) ;
2017-04-30 03:11:22 +02:00
if ( fe !== "" && fe !== null ) {
this . favoriteEmotes = JSON . parse ( atob ( fe ) ) ;
2016-01-08 16:33:43 +01:00
}
2015-12-31 18:27:43 +01:00
2017-11-01 06:03:48 +01:00
var qmeHeader = "" ;
2017-04-30 03:11:22 +02:00
qmeHeader += "<div id=\"bda-qem\">" ;
2017-11-03 04:05:33 +01:00
qmeHeader += " <button class=\"active\" id=\"bda-qem-twitch\" onclick='quickEmoteMenu.switchHandler(this); return false;'>Twitch</button>" ;
qmeHeader += " <button id=\"bda-qem-favourite\" onclick='quickEmoteMenu.switchHandler(this); return false;'>Favourite</button>" ;
qmeHeader += " <button id=\"bda-qem-emojis\" onclick='quickEmoteMenu.switchHandler(this); return false;'>Emojis</buttond>" ;
2017-11-01 06:03:48 +01:00
qmeHeader += "</div>" ;
2017-04-30 03:11:22 +02:00
this . qmeHeader = qmeHeader ;
2015-12-31 18:27:43 +01:00
2017-11-01 06:03:48 +01:00
var teContainer = "" ;
2017-04-30 03:11:22 +02:00
teContainer += "<div id=\"bda-qem-twitch-container\">" ;
teContainer += " <div class=\"scroller-wrap fade\">" ;
teContainer += " <div class=\"scroller\">" ;
teContainer += " <div class=\"emote-menu-inner\">" ;
2018-01-09 04:24:00 +01:00
for ( let emote in bdEmotes . TwitchGlobal ) {
if ( bdEmotes . TwitchGlobal . hasOwnProperty ( emote ) ) {
var url = bdEmotes . TwitchGlobal [ emote ] ;
2017-04-30 03:11:22 +02:00
teContainer += "<div class=\"emote-container\">" ;
2018-01-09 04:24:00 +01:00
teContainer += " <img class=\"emote-icon\" alt=\"\" src=\"" + url + "\" title=\"" + emote + "\">" ;
2017-04-30 03:11:22 +02:00
teContainer += " </img>" ;
teContainer += "</div>" ;
}
2015-12-31 18:27:43 +01:00
}
2017-11-03 04:05:33 +01:00
teContainer += " </div>" ;
teContainer += " </div>" ;
teContainer += " </div>" ;
teContainer += "</div>" ;
2017-04-30 03:11:22 +02:00
this . teContainer = teContainer ;
2015-12-31 18:27:43 +01:00
2017-11-01 06:03:48 +01:00
var faContainer = "" ;
2017-04-30 03:11:22 +02:00
faContainer += "<div id=\"bda-qem-favourite-container\">" ;
faContainer += " <div class=\"scroller-wrap fade\">" ;
faContainer += " <div class=\"scroller\">" ;
faContainer += " <div class=\"emote-menu-inner\">" ;
2017-11-03 04:05:33 +01:00
for ( let emote in this . favoriteEmotes ) {
2017-04-30 03:11:22 +02:00
var url = this . favoriteEmotes [ emote ] ;
faContainer += "<div class=\"emote-container\">" ;
2017-11-01 06:03:48 +01:00
faContainer += " <img class=\"emote-icon\" alt=\"\" src=\"" + url + "\" title=\"" + emote + "\" oncontextmenu='quickEmoteMenu.favContext(event, this);'>" ;
2017-04-30 03:11:22 +02:00
faContainer += " </img>" ;
faContainer += "</div>" ;
2015-12-31 18:27:43 +01:00
}
2017-11-01 06:03:48 +01:00
faContainer += " </div>" ;
faContainer += " </div>" ;
faContainer += " </div>" ;
faContainer += "</div>" ;
2017-04-30 03:11:22 +02:00
this . faContainer = faContainer ;
2015-12-31 18:27:43 +01:00
} ;
2017-04-30 03:11:22 +02:00
QuickEmoteMenu . prototype . favContext = function ( e , em ) {
e . stopPropagation ( ) ;
2017-11-03 20:52:35 +01:00
var menu = $ ( '<div>' , { id : "rmenu" , "data-emoteid" : $ ( em ) . prop ( "title" ) , text : "Remove" , class : "context-menu theme-dark" } ) ;
2017-04-30 03:11:22 +02:00
menu . css ( {
top : e . pageY - $ ( "#bda-qem-favourite-container" ) . offset ( ) . top ,
left : e . pageX - $ ( "#bda-qem-favourite-container" ) . offset ( ) . left
} ) ;
$ ( em ) . parent ( ) . append ( menu ) ;
menu . on ( "click" , function ( e ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
$ ( this ) . remove ( ) ;
2015-12-31 18:27:43 +01:00
2017-04-30 03:11:22 +02:00
delete quickEmoteMenu . favoriteEmotes [ $ ( this ) . data ( "emoteid" ) ] ;
quickEmoteMenu . updateFavorites ( ) ;
return false ;
} ) ;
return false ;
2015-12-31 18:27:43 +01:00
} ;
2017-04-30 03:11:22 +02:00
QuickEmoteMenu . prototype . switchHandler = function ( e ) {
this . switchQem ( $ ( e ) . attr ( "id" ) ) ;
2016-01-07 07:35:40 +01:00
} ;
2015-12-12 09:50:25 +01:00
2017-04-30 03:11:22 +02:00
QuickEmoteMenu . prototype . switchQem = function ( id ) {
var twitch = $ ( "#bda-qem-twitch" ) ;
var fav = $ ( "#bda-qem-favourite" ) ;
var emojis = $ ( "#bda-qem-emojis" ) ;
twitch . removeClass ( "active" ) ;
fav . removeClass ( "active" ) ;
emojis . removeClass ( "active" ) ;
2015-12-12 09:50:25 +01:00
2018-01-09 22:32:02 +01:00
$ ( ".emoji-picker, .emojiPicker-3g68GS" ) . hide ( ) ;
2017-04-30 03:11:22 +02:00
$ ( "#bda-qem-favourite-container" ) . hide ( ) ;
$ ( "#bda-qem-twitch-container" ) . hide ( ) ;
2015-12-12 09:50:25 +01:00
2017-04-30 03:11:22 +02:00
switch ( id ) {
case "bda-qem-twitch" :
twitch . addClass ( "active" ) ;
$ ( "#bda-qem-twitch-container" ) . show ( ) ;
break ;
case "bda-qem-favourite" :
fav . addClass ( "active" ) ;
$ ( "#bda-qem-favourite-container" ) . show ( ) ;
break ;
case "bda-qem-emojis" :
emojis . addClass ( "active" ) ;
2018-01-09 22:32:02 +01:00
$ ( ".emoji-picker, .emojiPicker-3g68GS" ) . show ( ) ;
$ ( ".emoji-picker .search-bar-inner input, .emojiPicker-3g68GS .search-bar-inner input" ) . focus ( ) ;
2017-04-30 03:11:22 +02:00
break ;
}
this . lastTab = id ;
2015-12-12 09:50:25 +01:00
2017-04-30 03:11:22 +02:00
var emoteIcon = $ ( ".emote-icon" ) ;
emoteIcon . off ( ) ;
emoteIcon . on ( "click" , function ( ) {
var emote = $ ( this ) . attr ( "title" ) ;
2017-10-29 21:33:48 +01:00
var ta = utils . getTextArea ( ) ;
utils . insertText ( ta [ 0 ] , ta . val ( ) . slice ( - 1 ) == " " ? ta . val ( ) + emote : ta . val ( ) + " " + emote ) ;
2017-04-30 03:11:22 +02:00
} ) ;
2015-12-12 09:50:25 +01:00
} ;
2017-10-29 21:33:48 +01:00
QuickEmoteMenu . prototype . obsCallback = function ( elem ) {
var e = $ ( elem ) ;
2017-04-30 03:11:22 +02:00
if ( ! settingsCookie [ "bda-es-9" ] ) {
e . addClass ( "bda-qme-hidden" ) ;
} else {
e . removeClass ( "bda-qme-hidden" ) ;
2015-12-12 09:50:25 +01:00
}
2017-04-30 03:11:22 +02:00
if ( ! settingsCookie [ "bda-es-0" ] ) return ;
2015-12-12 09:50:25 +01:00
2017-04-30 03:11:22 +02:00
e . prepend ( this . qmeHeader ) ;
e . append ( this . teContainer ) ;
e . append ( this . faContainer ) ;
if ( this . lastTab == undefined ) {
this . lastTab = "bda-qem-favourite" ;
}
this . switchQem ( this . lastTab ) ;
2015-12-12 13:53:07 +01:00
} ;
2017-04-30 03:11:22 +02:00
QuickEmoteMenu . prototype . favorite = function ( name , url ) {
2016-01-08 16:33:43 +01:00
2017-04-30 03:11:22 +02:00
if ( ! this . favoriteEmotes . hasOwnProperty ( name ) ) {
this . favoriteEmotes [ name ] = url ;
2015-12-12 17:54:44 +01:00
}
2017-04-30 03:11:22 +02:00
this . updateFavorites ( ) ;
2015-12-12 13:53:07 +01:00
} ;
2017-04-30 03:11:22 +02:00
QuickEmoteMenu . prototype . updateFavorites = function ( ) {
2016-01-08 16:33:43 +01:00
2017-11-01 06:03:48 +01:00
var faContainer = "" ;
2017-04-30 03:11:22 +02:00
faContainer += "<div id=\"bda-qem-favourite-container\">" ;
faContainer += " <div class=\"scroller-wrap fade\">" ;
faContainer += " <div class=\"scroller\">" ;
faContainer += " <div class=\"emote-menu-inner\">" ;
for ( var emote in this . favoriteEmotes ) {
var url = this . favoriteEmotes [ emote ] ;
faContainer += "<div class=\"emote-container\">" ;
2017-11-03 20:52:35 +01:00
faContainer += " <img class=\"emote-icon\" alt=\"\" src=\"" + url + "\" title=\"" + emote + "\" oncontextmenu=\"quickEmoteMenu.favContext(event, this);\">" ;
2017-04-30 03:11:22 +02:00
faContainer += " </img>" ;
faContainer += "</div>" ;
2015-12-12 17:54:44 +01:00
}
2017-11-01 06:03:48 +01:00
faContainer += " </div>" ;
faContainer += " </div>" ;
faContainer += " </div>" ;
faContainer += "</div>" ;
2017-04-30 03:11:22 +02:00
this . faContainer = faContainer ;
$ ( "#bda-qem-favourite-container" ) . replaceWith ( faContainer ) ;
window . bdStorage . set ( "bdfavemotes" , btoa ( JSON . stringify ( this . favoriteEmotes ) ) ) ;
2016-01-07 07:35:40 +01:00
} ;
2017-04-30 03:11:22 +02:00
2017-05-04 17:47:16 +02:00
2017-04-30 03:11:22 +02:00
/ * B e t t e r D i s c o r d A p p U t i l i t i e s J a v a S c r i p t
* Version : 1.0
* Author : Jiiks | http : //jiiks.net
* Date : 26 / 08 / 2015 - 15 : 54
* https : //github.com/Jiiks/BetterDiscordApp
* /
var _hash ;
function Utils ( ) {
}
Utils . prototype . getTextArea = function ( ) {
2017-10-29 21:33:48 +01:00
return $ ( ".channelTextArea-1HTP3C textarea" ) ;
} ;
Utils . prototype . insertText = function ( textarea , text ) {
2017-10-29 21:55:59 +01:00
textarea . focus ( ) ;
2017-10-29 21:33:48 +01:00
textarea . selectionStart = 0 ;
textarea . selectionEnd = textarea . value . length ;
document . execCommand ( "insertText" , false , text ) ;
2017-04-30 03:11:22 +02:00
} ;
Utils . prototype . jqDefer = function ( fnc ) {
if ( window . jQuery ) {
fnc ( ) ;
} else {
setTimeout ( function ( ) {
this . jqDefer ( fnc ) ;
} , 100 ) ;
}
} ;
Utils . prototype . getHash = function ( ) {
2017-11-04 16:04:50 +01:00
$ . getJSON ( "https://api.github.com/repos/Jiiks/BetterDiscordApp/commits/master" , function ( data ) {
2017-04-30 03:11:22 +02:00
_hash = data . sha ;
emoteModule . getBlacklist ( ) ;
} ) ;
} ;
Utils . prototype . loadHtml = function ( html , callback ) {
var container = $ ( "<div/>" , {
class : "bd-container"
} ) . appendTo ( "body" ) ;
//TODO Inject these in next core update
2017-11-04 16:04:50 +01:00
html = '//cdn.rawgit.com/Jiiks/BetterDiscordApp/' + _hash + '/html/' + html + '.html' ;
2017-04-30 03:11:22 +02:00
container . load ( html , callback ( ) ) ;
} ;
Utils . prototype . injectJs = function ( uri ) {
$ ( "<script/>" , {
type : "text/javascript" ,
src : uri
} ) . appendTo ( $ ( "body" ) ) ;
} ;
Utils . prototype . injectCss = function ( uri ) {
$ ( "<link/>" , {
type : "text/css" ,
rel : "stylesheet" ,
href : uri
} ) . appendTo ( $ ( "head" ) ) ;
} ;
2017-10-29 23:23:39 +01:00
Utils . prototype . escapeID = function ( id ) {
return id . replace ( /^[^a-z]+|[^\w-]+/gi , "" ) ;
} ;
2017-04-30 03:11:22 +02:00
Utils . prototype . log = function ( message ) {
2017-10-31 07:35:38 +01:00
console . log ( '%c[BetterDiscord] %c' + message + '' , 'color: #3a71c1; font-weight: 700;' , '' ) ;
2017-04-30 03:11:22 +02:00
} ;
2017-10-31 07:35:38 +01:00
Utils . prototype . err = function ( message , error ) {
console . log ( '%c[BetterDiscord] %c' + message + '' , 'color: red; font-weight: 700;' , '' ) ;
if ( error ) {
console . groupCollapsed ( '%cError: ' + error . message , 'color: red;' ) ;
2017-10-31 10:12:58 +01:00
console . error ( error . stack ) ;
2017-10-31 07:35:38 +01:00
console . groupEnd ( ) ;
}
2017-04-30 03:11:22 +02:00
} ;
2017-11-04 03:43:59 +01:00
2017-04-30 03:11:22 +02:00
/ * B e t t e r D i s c o r d A p p V o i c e M o d e J a v a S c r i p t
* Version : 1.0
* Author : Jiiks | http : //jiiks.net
* Date : 25 / 10 / 2015 - 19 : 10
* https : //github.com/Jiiks/BetterDiscordApp
* /
function VoiceMode ( ) {
}
VoiceMode . prototype . obsCallback = function ( ) {
var self = this ;
if ( settingsCookie [ "bda-gs-4" ] ) {
self . disable ( ) ;
setTimeout ( function ( ) {
self . enable ( ) ;
} , 300 ) ;
}
} ;
VoiceMode . prototype . enable = function ( ) {
$ ( ".scroller.guild-channels ul" ) . first ( ) . css ( "display" , "none" ) ;
$ ( ".scroller.guild-channels header" ) . first ( ) . css ( "display" , "none" ) ;
$ ( ".app.flex-vertical" ) . first ( ) . css ( "overflow" , "hidden" ) ;
$ ( ".chat.flex-vertical.flex-spacer" ) . first ( ) . css ( "visibility" , "hidden" ) . css ( "min-width" , "0px" ) ;
$ ( ".flex-vertical.channels-wrap" ) . first ( ) . css ( "flex-grow" , "100000" ) ;
$ ( ".guild-header .btn.btn-hamburger" ) . first ( ) . css ( "visibility" , "hidden" ) ;
} ;
VoiceMode . prototype . disable = function ( ) {
$ ( ".scroller.guild-channels ul" ) . first ( ) . css ( "display" , "" ) ;
$ ( ".scroller.guild-channels header" ) . first ( ) . css ( "display" , "" ) ;
$ ( ".app.flex-vertical" ) . first ( ) . css ( "overflow" , "" ) ;
$ ( ".chat.flex-vertical.flex-spacer" ) . first ( ) . css ( "visibility" , "" ) . css ( "min-width" , "" ) ;
$ ( ".flex-vertical.channels-wrap" ) . first ( ) . css ( "flex-grow" , "" ) ;
$ ( ".guild-header .btn.btn-hamburger" ) . first ( ) . css ( "visibility" , "" ) ;
} ;
/ * B e t t e r D i s c o r d A p p P l u g i n M o d u l e J a v a S c r i p t
* Version : 1.0
* Author : Jiiks | http : //jiiks.net
* Date : 16 / 12 / 2015
* https : //github.com/Jiiks/BetterDiscordApp
* /
var pluginCookie = { } ;
function PluginModule ( ) {
}
PluginModule . prototype . loadPlugins = function ( ) {
this . loadPluginData ( ) ;
2017-10-31 07:39:42 +01:00
var plugins = Object . keys ( bdplugins ) ;
2017-10-31 07:35:38 +01:00
for ( var i = 0 ; i < plugins . length ; i ++ ) {
2017-10-31 07:58:39 +01:00
var plugin , name ;
2017-10-31 07:35:38 +01:00
2017-10-31 07:58:39 +01:00
try {
plugin = bdplugins [ plugins [ i ] ] . plugin ;
2017-10-29 22:58:35 +01:00
name = plugin . getName ( ) ;
plugin . load ( ) ;
}
2017-10-31 09:26:30 +01:00
catch ( err ) {
pluginCookie [ name ] = false ;
2017-10-31 22:28:49 +01:00
utils . err ( "Plugin " + name + " could not be loaded." , err ) ;
2017-11-03 06:34:04 +01:00
bdpluginErrors . push ( { name : name , file : bdplugins [ plugins [ i ] ] . filename , reason : "load() could not be fired." , error : { message : err . message , stack : err . stack } } ) ;
2017-10-31 22:28:49 +01:00
continue ;
2017-10-31 09:26:30 +01:00
}
2017-04-30 03:11:22 +02:00
2017-10-31 07:58:39 +01:00
if ( ! pluginCookie [ name ] ) pluginCookie [ name ] = false ;
2017-04-30 03:11:22 +02:00
2017-10-31 07:58:39 +01:00
if ( pluginCookie [ name ] ) {
2017-11-03 21:08:53 +01:00
try {
plugin . start ( ) ;
2017-12-24 07:51:24 +01:00
if ( settingsCookie [ "fork-ps-2" ] ) mainCore . showToast ( ` ${ plugin . getName ( ) } v ${ plugin . getVersion ( ) } has started. ` ) ;
2017-11-03 21:08:53 +01:00
}
2017-10-31 09:26:30 +01:00
catch ( err ) {
pluginCookie [ name ] = false ;
utils . err ( "Plugin " + name + " could not be started." , err ) ;
2017-11-03 06:34:04 +01:00
bdpluginErrors . push ( { name : name , file : bdplugins [ plugins [ i ] ] . filename , reason : "start() could not be fired." , error : { message : err . message , stack : err . stack } } ) ;
2017-10-31 09:26:30 +01:00
}
2017-04-30 03:11:22 +02:00
}
2017-10-31 07:35:38 +01:00
}
2017-10-31 09:26:30 +01:00
this . savePluginData ( ) ;
} ;
PluginModule . prototype . startPlugin = function ( plugin ) {
2017-11-03 20:52:35 +01:00
try {
bdplugins [ plugin ] . plugin . start ( ) ;
2017-12-24 07:51:24 +01:00
if ( settingsCookie [ "fork-ps-2" ] ) mainCore . showToast ( ` ${ bdplugins [ plugin ] . plugin . getName ( ) } v ${ bdplugins [ plugin ] . plugin . getVersion ( ) } has started. ` ) ;
2017-11-03 20:52:35 +01:00
}
2017-10-31 09:26:30 +01:00
catch ( err ) {
pluginCookie [ plugin ] = false ;
this . savePluginData ( ) ;
utils . err ( "Plugin " + name + " could not be started." , err ) ;
}
} ;
PluginModule . prototype . stopPlugin = function ( plugin ) {
2017-11-03 20:52:35 +01:00
try {
bdplugins [ plugin ] . plugin . stop ( ) ;
2017-12-24 07:51:24 +01:00
if ( settingsCookie [ "fork-ps-2" ] ) mainCore . showToast ( ` ${ bdplugins [ plugin ] . plugin . getName ( ) } v ${ bdplugins [ plugin ] . plugin . getVersion ( ) } has stopped. ` ) ;
2017-11-03 20:52:35 +01:00
}
catch ( err ) {
utils . err ( "Plugin " + name + " could not be stopped." , err ) ;
}
2017-10-31 09:26:30 +01:00
} ;
PluginModule . prototype . enablePlugin = function ( plugin ) {
pluginCookie [ plugin ] = true ;
this . savePluginData ( ) ;
this . startPlugin ( plugin ) ;
} ;
PluginModule . prototype . disablePlugin = function ( plugin ) {
pluginCookie [ plugin ] = false ;
this . savePluginData ( ) ;
this . stopPlugin ( plugin ) ;
} ;
PluginModule . prototype . togglePlugin = function ( plugin ) {
2017-11-01 18:46:13 +01:00
if ( pluginCookie [ plugin ] ) this . disablePlugin ( plugin ) ;
else this . enablePlugin ( plugin ) ;
2017-04-30 03:11:22 +02:00
} ;
PluginModule . prototype . loadPluginData = function ( ) {
var cookie = $ . cookie ( "bd-plugins" ) ;
if ( cookie != undefined ) {
pluginCookie = JSON . parse ( $ . cookie ( "bd-plugins" ) ) ;
}
} ;
PluginModule . prototype . savePluginData = function ( ) {
$ . cookie ( "bd-plugins" , JSON . stringify ( pluginCookie ) , {
expires : 365 ,
path : '/'
} ) ;
} ;
PluginModule . prototype . newMessage = function ( ) {
2017-10-31 08:28:03 +01:00
var plugins = Object . keys ( bdplugins ) ;
for ( var i = 0 ; i < plugins . length ; i ++ ) {
var plugin = bdplugins [ plugins [ i ] ] . plugin ;
2017-10-31 22:28:49 +01:00
if ( ! pluginCookie [ plugin . getName ( ) ] ) continue ;
2017-10-31 08:28:03 +01:00
if ( typeof plugin . onMessage === "function" ) {
try { plugin . onMessage ( ) ; }
catch ( err ) { utils . err ( "Unable to fire onMessage for " + plugin . getName ( ) + "." , err ) ; }
2017-04-30 03:11:22 +02:00
}
2017-10-31 08:28:03 +01:00
}
2017-04-30 03:11:22 +02:00
} ;
PluginModule . prototype . channelSwitch = function ( ) {
2017-10-31 08:28:03 +01:00
var plugins = Object . keys ( bdplugins ) ;
for ( var i = 0 ; i < plugins . length ; i ++ ) {
var plugin = bdplugins [ plugins [ i ] ] . plugin ;
2017-10-31 22:28:49 +01:00
if ( ! pluginCookie [ plugin . getName ( ) ] ) continue ;
2017-10-31 08:28:03 +01:00
if ( typeof plugin . onSwitch === "function" ) {
try { plugin . onSwitch ( ) ; }
catch ( err ) { utils . err ( "Unable to fire onSwitch for " + plugin . getName ( ) + "." , err ) ; }
2017-04-30 03:11:22 +02:00
}
2017-10-31 08:28:03 +01:00
}
2017-04-30 03:11:22 +02:00
} ;
PluginModule . prototype . rawObserver = function ( e ) {
2017-10-31 08:28:03 +01:00
var plugins = Object . keys ( bdplugins ) ;
for ( var i = 0 ; i < plugins . length ; i ++ ) {
var plugin = bdplugins [ plugins [ i ] ] . plugin ;
2017-10-31 22:28:49 +01:00
if ( ! pluginCookie [ plugin . getName ( ) ] ) continue ;
2017-10-31 08:28:03 +01:00
if ( typeof plugin . observer === "function" ) {
try { plugin . observer ( e ) ; }
catch ( err ) { utils . err ( "Unable to fire observer for " + plugin . getName ( ) + "." , err ) ; }
2017-04-30 03:11:22 +02:00
}
2017-10-31 08:28:03 +01:00
}
2017-04-30 03:11:22 +02:00
} ;
2017-10-30 04:45:07 +01:00
2017-04-30 03:11:22 +02:00
/ * B e t t e r D i s c o r d A p p T h e m e M o d u l e J a v a S c r i p t
* Version : 1.0
* Author : Jiiks | http : //jiiks.net
* Date : 16 / 12 / 2015
* https : //github.com/Jiiks/BetterDiscordApp
* /
var themeCookie = { } ;
function ThemeModule ( ) {
}
ThemeModule . prototype . loadThemes = function ( ) {
this . loadThemeData ( ) ;
2017-10-31 07:58:39 +01:00
var themes = Object . keys ( bdthemes ) ;
2017-10-31 08:28:03 +01:00
for ( var i = 0 ; i < themes . length ; i ++ ) {
var name = bdthemes [ themes [ i ] ] . name ;
if ( ! themeCookie [ name ] ) themeCookie [ name ] = false ;
2017-11-01 18:34:00 +01:00
if ( themeCookie [ name ] ) $ ( "head" ) . append ( $ ( '<style>' , { id : utils . escapeID ( name ) , html : unescape ( bdthemes [ name ] . css ) } ) ) ;
2017-10-31 08:28:03 +01:00
}
2017-04-30 03:11:22 +02:00
} ;
2017-11-01 18:34:00 +01:00
ThemeModule . prototype . enableTheme = function ( theme ) {
themeCookie [ theme ] = true ;
this . saveThemeData ( ) ;
$ ( "head" ) . append ( ` <style id=" ${ utils . escapeID ( bdthemes [ theme ] . name ) } "> ${ unescape ( bdthemes [ theme ] . css ) } </style> ` ) ;
2017-12-24 07:51:24 +01:00
if ( settingsCookie [ "fork-ps-2" ] ) mainCore . showToast ( ` ${ bdthemes [ theme ] . name } v ${ bdthemes [ theme ] . version } has been applied. ` ) ;
2017-11-01 18:34:00 +01:00
} ;
ThemeModule . prototype . disableTheme = function ( theme ) {
themeCookie [ theme ] = false ;
this . saveThemeData ( ) ;
$ ( ` # ${ utils . escapeID ( bdthemes [ theme ] . name ) } ` ) . remove ( ) ;
2017-12-24 07:51:24 +01:00
if ( settingsCookie [ "fork-ps-2" ] ) mainCore . showToast ( ` ${ bdthemes [ theme ] . name } v ${ bdthemes [ theme ] . version } has been removed. ` ) ;
2017-11-01 18:34:00 +01:00
} ;
2017-11-01 18:37:44 +01:00
ThemeModule . prototype . toggleTheme = function ( theme ) {
2017-11-01 18:46:13 +01:00
if ( themeCookie [ theme ] ) this . disableTheme ( theme ) ;
else this . enableTheme ( theme ) ;
2017-11-01 18:34:00 +01:00
} ;
2017-04-30 03:11:22 +02:00
ThemeModule . prototype . loadThemeData = function ( ) {
var cookie = $ . cookie ( "bd-themes" ) ;
if ( cookie != undefined ) {
themeCookie = JSON . parse ( $ . cookie ( "bd-themes" ) ) ;
}
} ;
ThemeModule . prototype . saveThemeData = function ( ) {
$ . cookie ( "bd-themes" , JSON . stringify ( themeCookie ) , {
expires : 365 ,
path : '/'
} ) ;
} ;
/ * B e t t e r D i s c o r d A p p A P I f o r P l u g i n s
* Version : 1.0
* Author : Jiiks | http : //jiiks.net
* Date : 11 / 12 / 2015
* Last Update : 11 / 12 / 2015
* https : //github.com/Jiiks/BetterDiscordApp
*
* Plugin Template : https : //gist.github.com/Jiiks/71edd5af0beafcd08956
* /
function BdApi ( ) { }
//Inject CSS to document head
//id = id of element
//css = custom css
BdApi . injectCSS = function ( id , css ) {
2017-10-29 23:23:39 +01:00
$ ( "head" ) . append ( $ ( '<style>' , { id : utils . escapeID ( id ) , html : css } ) ) ;
2017-04-30 03:11:22 +02:00
} ;
//Clear css/remove any element
//id = id of element
BdApi . clearCSS = function ( id ) {
2017-10-29 23:23:39 +01:00
$ ( "#" + utils . escapeID ( id ) ) . remove ( ) ;
2017-04-30 03:11:22 +02:00
} ;
2017-11-03 18:34:26 +01:00
//Inject CSS to document head
//id = id of element
//css = custom css
BdApi . linkJS = function ( id , url ) {
$ ( "head" ) . append ( $ ( '<script>' , { id : utils . escapeID ( id ) , src : url , type : "text/javascript" } ) ) ;
} ;
//Clear css/remove any element
//id = id of element
BdApi . unlinkJS = function ( id ) {
$ ( "#" + utils . escapeID ( id ) ) . remove ( ) ;
} ;
2017-04-30 03:11:22 +02:00
//Get another plugin
//name = name of plugin
BdApi . getPlugin = function ( name ) {
if ( bdplugins . hasOwnProperty ( name ) ) {
return bdplugins [ name ] [ "plugin" ] ;
}
return null ;
} ;
//Get ipc for reason
BdApi . getIpc = function ( ) {
return betterDiscordIPC ;
} ;
//Get BetterDiscord Core
BdApi . getCore = function ( ) {
return mainCore ;
} ;
2017-11-03 18:34:26 +01:00
//Show modal alert
BdApi . alert = function ( title , content ) {
mainCore . alert ( title , content ) ;
} ;
2017-11-03 20:52:35 +01:00
//Show toast alert
2017-11-03 18:54:47 +01:00
BdApi . showToast = function ( content , options = { } ) {
2017-11-03 20:52:35 +01:00
mainCore . showToast ( content , options ) ;
2017-11-03 18:54:47 +01:00
} ;
2017-11-04 03:43:59 +01:00
2017-04-30 03:11:22 +02:00
/ * B e t t e r D i s c o r d A p p D e v M o d e J a v a S c r i p t
* Version : 1.0
* Author : Jiiks | http : //jiiks.net
* Date : 22 / 05 / 2016
* Last Update : 22 / 05 / 2016
2016-05-24 22:33:24 +02:00
* https : //github.com/Jiiks/BetterDiscordApp
* /
function devMode ( ) { }
2017-12-22 20:29:59 +01:00
devMode . prototype . enable = function ( selectorMode ) {
2016-05-24 22:33:24 +02:00
var self = this ;
2017-10-30 08:39:41 +01:00
this . disable ( ) ;
2016-05-24 22:33:24 +02:00
$ ( window ) . on ( "keydown.bdDevmode" , function ( e ) {
if ( e . which === 119 ) { //F8
2017-11-03 18:34:26 +01:00
console . log ( '%c[%cDevMode%c] %cBreak/Resume' , 'color: red;' , 'color: #303030; font-weight:700;' , 'color:red;' , '' ) ;
2017-11-03 04:05:33 +01:00
debugger ; // eslint-disable-line no-debugger
2016-05-24 22:33:24 +02:00
}
} ) ;
2017-10-30 04:45:07 +01:00
2018-01-09 04:24:00 +01:00
if ( ! selectorMode ) return ;
2017-10-30 05:56:20 +01:00
$ ( document ) . on ( "contextmenu.bdDevmode" , function ( e ) {
2016-05-24 22:33:24 +02:00
var parents = [ ] ;
$ ( e . toElement ) . parents ( ) . addBack ( ) . not ( 'html' ) . each ( function ( ) {
var entry = "" ;
2017-10-30 05:56:20 +01:00
if ( this . classList && this . classList . length ) {
entry += "." + Array . prototype . join . call ( this . classList , '.' ) ;
2016-05-24 22:33:24 +02:00
parents . push ( entry ) ;
}
} ) ;
self . lastSelector = parents . join ( " " ) . trim ( ) ;
2017-04-30 03:11:22 +02:00
function attach ( ) {
var cm = $ ( ".context-menu" ) ;
if ( cm . length <= 0 ) {
2017-10-30 05:56:20 +01:00
cm = $ ( '<div class="context-menu bd-context-menu"></div>' ) ;
cm . addClass ( $ ( '.app' ) . hasClass ( "theme-dark" ) ? "theme-dark" : "theme-light" ) ;
cm . appendTo ( '.app' ) ;
cm . css ( "top" , e . clientY ) ;
cm . css ( "left" , e . clientX ) ;
2017-10-30 06:20:19 +01:00
$ ( document ) . on ( 'click.bdDevModeCtx' , ( ) => {
cm . remove ( ) ;
$ ( document ) . off ( '.bdDevModeCtx' ) ;
} ) ;
$ ( document ) . on ( 'contextmenu.bdDevModeCtx' , ( ) => {
cm . remove ( ) ;
$ ( document ) . off ( '.bdDevModeCtx' ) ;
} ) ;
$ ( document ) . on ( "keyup.bdDevModeCtx" , ( e ) => {
if ( e . keyCode === 27 ) {
cm . remove ( ) ;
$ ( document ) . off ( '.bdDevModeCtx' ) ;
}
} ) ;
2017-04-30 03:11:22 +02:00
}
var cmo = $ ( "<div/>" , {
class : "item-group"
} ) ;
var cmi = $ ( "<div/>" , {
class : "item" ,
click : function ( ) {
var t = $ ( "<textarea/>" , { text : self . lastSelector } ) . appendTo ( "body" ) ;
t . select ( ) ;
document . execCommand ( "copy" ) ;
t . remove ( ) ;
2017-10-30 05:56:20 +01:00
//if (cm.hasClass("bd-context-menu")) cm.remove();
cm . hide ( ) ;
2017-04-30 03:11:22 +02:00
}
} ) . append ( $ ( "<span/>" , { text : "Copy Selector" } ) ) ;
cmo . append ( cmi ) ;
cm . append ( cmo ) ;
2017-10-30 21:53:27 +01:00
cm . css ( "top" , "-=" + cmo . outerHeight ( ) ) ;
2017-04-30 03:11:22 +02:00
}
2017-10-30 08:39:41 +01:00
setImmediate ( attach ) ;
2017-04-30 03:11:22 +02:00
e . stopPropagation ( ) ;
} ) ;
} ;
devMode . prototype . disable = function ( ) {
$ ( window ) . off ( "keydown.bdDevmode" ) ;
2017-10-30 05:56:20 +01:00
$ ( document ) . off ( "contextmenu.bdDevmode" ) ;
2017-10-30 08:35:08 +01:00
$ ( document ) . off ( "contextmenu.bdDevModeCtx" ) ;
2017-04-30 03:11:22 +02:00
} ;
2017-11-03 18:34:26 +01:00
2017-04-30 03:11:22 +02:00
/*V2 Premature*/
window . bdtemp = {
'editorDetached' : false
} ;
class V2 {
constructor ( ) {
2017-12-22 02:02:35 +01:00
this . WebpackModules = ( ( ) => {
const req = webpackJsonp ( [ ] , {
'__extra_id__' : ( module , exports , req ) => exports . default = req
} , [ '__extra_id__' ] ) . default ;
delete req . m [ '__extra_id__' ] ;
delete req . c [ '__extra_id__' ] ;
const find = ( filter , options = { } ) => {
const { cacheOnly = true } = options ;
for ( let i in req . c ) {
if ( req . c . hasOwnProperty ( i ) ) {
let m = req . c [ i ] . exports ;
if ( m && m . _ _esModule && m . default && filter ( m . default ) ) return m . default ;
if ( m && filter ( m ) ) return m ;
}
}
if ( cacheOnly ) {
console . warn ( 'Cannot find loaded module in cache' ) ;
return null ;
}
console . warn ( 'Cannot find loaded module in cache. Loading all modules may have unexpected side effects' ) ;
for ( let i = 0 ; i < req . m . length ; ++ i ) {
try {
let m = req ( i ) ;
if ( m && m . _ _esModule && m . default && filter ( m . default ) ) return m . default ;
if ( m && filter ( m ) ) return m ;
}
catch ( e ) {
console . error ( e ) ;
}
}
console . warn ( 'Cannot find module' ) ;
return null ;
} ;
const findByUniqueProperties = ( propNames , options ) => find ( module => propNames . every ( prop => module [ prop ] !== undefined ) , options ) ;
const findByDisplayName = ( displayName , options ) => find ( module => module . displayName === displayName , options ) ;
return { find , findByUniqueProperties , findByDisplayName } ;
} ) ( ) ;
2017-04-30 03:11:22 +02:00
this . internal = {
2017-12-22 02:02:35 +01:00
'react' : this . WebpackModules . findByUniqueProperties ( [ 'Component' , 'PureComponent' , 'Children' , 'createElement' , 'cloneElement' ] ) ,
'react-dom' : this . WebpackModules . findByUniqueProperties ( [ 'findDOMNode' ] )
2017-04-30 03:11:22 +02:00
} ;
}
get reactComponent ( ) {
return this . internal [ 'react' ] . Component ;
}
get react ( ) {
return this . internal [ 'react' ] ;
}
get reactDom ( ) {
return this . internal [ 'react-dom' ] ;
}
parseSettings ( cat ) {
return Object . keys ( settings ) . reduce ( ( arr , key ) => {
let setting = settings [ key ] ;
if ( setting . cat === cat && setting . implemented && ! setting . hidden ) {
setting . text = key ;
2017-11-03 04:05:33 +01:00
arr . push ( setting ) ;
2017-04-30 03:11:22 +02:00
} return arr ;
} , [ ] ) ;
}
}
2017-11-01 18:12:29 +01:00
2017-04-30 03:11:22 +02:00
window . BDV2 = new V2 ( ) ;
class V2C _SettingsPanel extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
render ( ) {
let { settings } = this . props ;
return BDV2 . react . createElement (
"div" ,
{ className : "content-column default" } ,
2017-12-24 07:51:24 +01:00
BDV2 . react . createElement ( V2Components . SettingsTitle , { text : this . props . title } ) ,
this . props . button && BDV2 . react . createElement ( "button" , { key : "title-button" , className : 'bd-pfbtn' , onClick : this . props . button . onClick } , this . props . button . title ) ,
2017-04-30 03:11:22 +02:00
settings . map ( setting => {
return BDV2 . react . createElement ( V2Components . Switch , { id : setting . id , key : setting . id , data : setting , checked : settingsCookie [ setting . id ] , onChange : ( id , checked ) => {
this . props . onChange ( id , checked ) ;
} } ) ;
} )
) ;
}
}
class V2C _Switch extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
this . setInitialState ( ) ;
this . onChange = this . onChange . bind ( this ) ;
}
setInitialState ( ) {
this . state = {
'checked' : this . props . checked
} ;
}
render ( ) {
let { text , info } = this . props . data ;
let { checked } = this . state ;
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 (
"label" ,
{ className : "ui-switch-wrapper ui-flex-child" , style : { flex : '0 0 auto' } } ,
BDV2 . react . createElement ( "input" , { className : "ui-switch-checkbox" , type : "checkbox" , checked : checked , onChange : e => this . onChange ( e ) } ) ,
2017-06-17 19:08:43 +02:00
BDV2 . react . createElement ( "div" , { className : ` ui-switch ${ checked ? 'checked' : '' } ` } )
2017-04-30 03:11:22 +02:00
)
) ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-form-text style-description margin-top-4" , style : { flex : '1 1 auto' } } ,
info
)
) ;
}
2017-11-03 04:05:33 +01:00
onChange ( ) {
2017-04-30 03:11:22 +02:00
this . props . onChange ( this . props . id , ! this . state . checked ) ;
this . setState ( {
'checked' : ! this . state . checked
} ) ;
}
}
class V2C _Scroller extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
render ( ) {
let wrapperClass = ` scroller-wrap ${ this . props . fade ? ' fade' : '' } ${ this . props . dark ? ' dark' : '' } ` ;
let { children } = this . props ;
return BDV2 . react . createElement (
"div" ,
{ key : "scrollerwrap" , className : wrapperClass } ,
BDV2 . react . createElement (
"div" ,
{ key : "scroller" , ref : "scroller" , className : "scroller" } ,
children
)
) ;
}
}
class V2C _TabBarItem extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
this . setInitialState ( ) ;
this . onClick = this . onClick . bind ( this ) ;
}
setInitialState ( ) {
this . state = {
'selected' : this . props . selected || false
} ;
}
render ( ) {
return BDV2 . react . createElement (
"div" ,
{ className : ` ui-tab-bar-item ${ this . props . selected ? ' selected' : '' } ` , onClick : this . onClick } ,
this . props . text
) ;
}
onClick ( ) {
if ( this . props . onClick ) {
this . props . onClick ( this . props . id ) ;
}
}
}
class V2C _TabBarSeparator extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
render ( ) {
return BDV2 . react . createElement ( "div" , { className : "ui-tab-bar-separator margin-top-8 margin-bottom-8" } ) ;
}
}
class V2C _TabBarHeader extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
render ( ) {
return BDV2 . react . createElement (
"div" ,
{ className : "ui-tab-bar-header" } ,
this . props . text
) ;
}
}
class V2C _SideBar extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
let self = this ;
2017-06-17 19:08:43 +02:00
const si = $ ( "[class*=side] > [class*=selected]" ) ;
if ( si . length ) {
self . scn = si . attr ( "class" ) ;
}
const ns = $ ( "[class*=side] > [class*=notSelected]" ) ;
if ( ns . length ) {
self . nscn = ns . attr ( "class" ) ;
}
2017-11-03 04:05:33 +01:00
$ ( "[class*=side] > [class*=item]" ) . on ( "click" , ( ) => {
2017-04-30 03:11:22 +02:00
self . setState ( {
'selected' : null
} ) ;
} ) ;
self . setInitialState ( ) ;
self . onClick = self . onClick . bind ( self ) ;
}
setInitialState ( ) {
let self = this ;
self . state = {
'selected' : null ,
'items' : self . props . items
} ;
let initialSelection = self . props . items . find ( item => {
return item . selected ;
} ) ;
if ( initialSelection ) {
self . state . selected = initialSelection . id ;
}
}
render ( ) {
let self = this ;
let { headerText } = self . props ;
let { items , selected } = self . state ;
return BDV2 . react . createElement (
"div" ,
null ,
BDV2 . react . createElement ( V2Components . TabBar . Separator , null ) ,
BDV2 . react . createElement ( V2Components . TabBar . Header , { text : headerText } ) ,
items . map ( item => {
let { id , text } = item ;
return BDV2 . react . createElement ( V2Components . TabBar . Item , { key : id , selected : selected === id , text : text , id : id , onClick : self . onClick } ) ;
} )
) ;
}
onClick ( id ) {
let self = this ;
2017-06-17 19:08:43 +02:00
const si = $ ( "[class*=side] > [class*=selected]" ) ;
if ( si . length ) {
si . off ( "click.bdsb" ) . on ( "click.bsb" , e => {
$ ( e . target ) . attr ( "class" , self . scn ) ;
} ) ;
si . attr ( "class" , self . nscn ) ;
}
2017-11-03 04:05:33 +01:00
self . setState ( { 'selected' : null } ) ;
self . setState ( { 'selected' : id } ) ;
2017-04-30 03:11:22 +02:00
if ( self . props . onClick ) self . props . onClick ( id ) ;
}
}
class V2C _XSvg extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
render ( ) {
return BDV2 . react . createElement (
"svg" ,
{ xmlns : "http://www.w3.org/2000/svg" , viewBox : "0 0 12 12" , style : { width : "18px" , height : "18px" } } ,
BDV2 . react . createElement (
"g" ,
2017-10-29 22:20:45 +01:00
{ className : "background" , fill : "none" , "fillRule" : "evenodd" } ,
2017-04-30 03:11:22 +02:00
BDV2 . react . createElement ( "path" , { d : "M0 0h12v12H0" } ) ,
BDV2 . react . createElement ( "path" , { className : "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" } )
)
) ;
}
}
class V2C _Tools extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
this . onClick = this . onClick . bind ( this ) ;
}
render ( ) {
return BDV2 . react . createElement (
"div" ,
{ className : "tools" } ,
BDV2 . react . createElement (
"div" ,
{ className : "btn-close" , onClick : this . onClick } ,
BDV2 . react . createElement ( V2Components . XSvg , null )
) ,
BDV2 . react . createElement (
"div" ,
{ className : "esc-text" } ,
"ESC"
)
) ;
}
onClick ( ) {
if ( this . props . onClick ) {
this . props . onClick ( ) ;
}
$ ( ".btn-close" ) . first ( ) . click ( ) ;
}
}
class V2C _SettingsTitle extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
render ( ) {
return BDV2 . react . createElement (
"h2" ,
{ className : "ui-form-title h2 margin-reset margin-bottom-20" } ,
this . props . text
) ;
}
}
class V2C _Checkbox extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
this . onClick = this . onClick . bind ( this ) ;
this . setInitialState ( ) ;
}
setInitialState ( ) {
this . state = {
'checked' : this . props . checked || false
} ;
}
render ( ) {
return BDV2 . react . createElement (
"li" ,
null ,
BDV2 . react . createElement (
"div" ,
{ className : "checkbox" , onClick : this . onClick } ,
BDV2 . react . createElement (
"div" ,
{ className : "checkbox-inner" } ,
BDV2 . react . createElement ( "input" , { checked : this . state . checked , onChange : ( ) => { } , type : "checkbox" } ) ,
BDV2 . react . createElement ( "span" , null )
) ,
BDV2 . react . createElement (
"span" ,
null ,
this . props . text
)
)
) ;
}
onClick ( ) {
this . props . onChange ( this . props . id , ! this . state . checked ) ;
this . setState ( {
'checked' : ! this . state . checked
} ) ;
}
}
class V2C _CssEditorDetached extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
let self = this ;
self . onClick = self . onClick . bind ( self ) ;
self . updateCss = self . updateCss . bind ( self ) ;
self . saveCss = self . saveCss . bind ( self ) ;
self . onChange = self . onChange . bind ( self ) ;
}
componentDidMount ( ) {
$ ( "#app-mount" ) . addClass ( 'bd-detached-editor' ) ;
window . bdtemp . editorDetached = true ;
2018-01-10 02:08:59 +01:00
// this.updateLineCount();
this . editor = ace . edit ( "bd-customcss-editor-detached" ) ;
this . editor . setTheme ( "ace/theme/monokai" ) ;
this . editor . session . setMode ( "ace/mode/css" ) ;
this . editor . setShowPrintMargin ( false ) ;
this . editor . setFontSize ( 14 ) ;
this . editor . on ( 'change' , ( ) => {
if ( ! settingsCookie [ "bda-css-0" ] ) return ;
this . saveCss ( ) ;
this . updateCss ( ) ;
} ) ;
2017-04-30 03:11:22 +02:00
}
componentWillUnmount ( ) {
$ ( "#app-mount" ) . removeClass ( 'bd-detached-editor' ) ;
window . bdtemp . editorDetached = false ;
2018-01-10 02:08:59 +01:00
this . editor . destroy ( ) ;
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
updateLineCount ( ) {
let lineCount = this . refs . editor . value . split ( '\n' ) . length ;
if ( lineCount == this . props . lines ) return ;
this . refs . lines . textContent = Array . from ( new Array ( lineCount ) , ( _ , i ) => i + 1 ) . join ( ".\n" ) + "." ;
this . props . lines = lineCount ;
}
2017-04-30 03:11:22 +02:00
get options ( ) {
return {
lineNumbers : true ,
mode : 'css' ,
indentUnit : 4 ,
theme : 'material' ,
scrollbarStyle : 'simple'
} ;
}
get css ( ) {
let _ccss = window . bdStorage . get ( "bdcustomcss" ) ;
let ccss = "" ;
if ( _ccss && _ccss !== "" ) {
ccss = atob ( _ccss ) ;
}
return ccss ;
}
get root ( ) {
let _root = $ ( "#bd-customcss-detach-container" ) ;
if ( ! _root . length ) {
if ( ! this . injectRoot ( ) ) return null ;
return this . detachedRoot ;
}
return _root [ 0 ] ;
}
injectRoot ( ) {
if ( ! $ ( ".app" ) . length ) return false ;
$ ( "<div/>" , {
id : 'bd-customcss-detach-container'
} ) . insertAfter ( $ ( ".app" ) ) ;
return true ;
}
render ( ) {
let self = this ;
return BDV2 . react . createElement (
"div" ,
{ className : "bd-detached-css-editor" , id : "bd-customcss-detach-editor" } ,
BDV2 . react . createElement (
"div" ,
{ id : "bd-customcss-innerpane" } ,
2018-01-09 04:24:00 +01:00
BDV2 . react . createElement ( "div" , { className : "editor-wrapper" } ,
2018-01-10 02:08:59 +01:00
BDV2 . react . createElement ( "div" , { id : "bd-customcss-editor-detached" , className : "editor" , ref : "editor" } , self . css )
2018-01-09 04:24:00 +01:00
) ,
2017-04-30 03:11:22 +02:00
BDV2 . react . createElement (
"div" ,
{ id : "bd-customcss-attach-controls" } ,
BDV2 . react . createElement (
"ul" ,
{ className : "checkbox-group" } ,
BDV2 . react . createElement ( V2Components . Checkbox , { id : "live-update" , text : "Live Update" , onChange : self . onChange , checked : settingsCookie [ "bda-css-0" ] } )
) ,
BDV2 . react . createElement (
"div" ,
{ id : "bd-customcss-detach-controls-button" } ,
BDV2 . react . createElement (
"button" ,
{ style : { borderRadius : "3px 0 0 3px" , borderRight : "1px solid #3f4146" } , className : "btn btn-primary" , onClick : ( ) => {
self . onClick ( "update" ) ;
} } ,
"Update"
) ,
BDV2 . react . createElement (
"button" ,
{ style : { borderRadius : "0" , borderLeft : "1px solid #2d2d2d" , borderRight : "1px solid #2d2d2d" } , className : "btn btn-primary" , onClick : ( ) => {
self . onClick ( "save" ) ;
} } ,
"Save"
) ,
BDV2 . react . createElement (
"button" ,
{ style : { borderRadius : "0 3px 3px 0" , borderLeft : "1px solid #3f4146" } , className : "btn btn-primary" , onClick : ( ) => {
self . onClick ( "attach" ) ;
} } ,
"Attach"
) ,
BDV2 . react . createElement (
"span" ,
{ style : { fontSize : "10px" , marginLeft : "5px" } } ,
"Unsaved changes are lost on attach"
)
)
)
)
) ;
}
onChange ( id , checked ) {
switch ( id ) {
case 'live-update' :
settingsCookie [ "bda-css-0" ] = checked ;
mainCore . saveSettings ( ) ;
break ;
}
}
onClick ( id ) {
let self = this ;
switch ( id ) {
case 'attach' :
2017-04-30 04:21:08 +02:00
if ( $ ( "#editor-detached" ) . length ) self . props . attach ( ) ;
2017-04-30 03:11:22 +02:00
BDV2 . reactDom . unmountComponentAtNode ( self . root ) ;
2017-10-31 08:28:03 +01:00
self . root . remove ( ) ;
2017-04-30 03:11:22 +02:00
break ;
case 'update' :
self . updateCss ( ) ;
break ;
case 'save' :
self . saveCss ( ) ;
break ;
}
}
updateCss ( ) {
if ( $ ( "#customcss" ) . length == 0 ) {
$ ( "head" ) . append ( '<style id="customcss"></style>' ) ;
}
2018-01-10 02:08:59 +01:00
$ ( "#customcss" ) . html ( this . editor . session . getValue ( ) ) . detach ( ) . appendTo ( document . head ) ;
2017-04-30 03:11:22 +02:00
}
saveCss ( ) {
2018-01-10 02:08:59 +01:00
window . bdStorage . set ( "bdcustomcss" , btoa ( this . editor . session . getValue ( ) ) ) ;
2017-04-30 03:11:22 +02:00
}
}
class V2C _CssEditor extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
let self = this ;
2018-01-09 04:24:00 +01:00
self . props . lines = 0 ;
2017-04-30 03:11:22 +02:00
self . setInitialState ( ) ;
2017-04-30 04:21:08 +02:00
self . attach = self . attach . bind ( self ) ;
self . detachedEditor = BDV2 . react . createElement ( V2C _CssEditorDetached , { attach : self . attach } ) ;
2017-04-30 03:11:22 +02:00
self . onClick = self . onClick . bind ( self ) ;
self . updateCss = self . updateCss . bind ( self ) ;
self . saveCss = self . saveCss . bind ( self ) ;
self . detach = self . detach . bind ( self ) ;
}
setInitialState ( ) {
this . state = {
'detached' : this . props . detached || window . bdtemp . editorDetached
} ;
}
componentDidMount ( ) {
2018-01-10 02:08:59 +01:00
// this.updateLineCount();
this . editor = ace . edit ( "bd-customcss-editor" ) ;
this . editor . setTheme ( "ace/theme/monokai" ) ;
this . editor . session . setMode ( "ace/mode/css" ) ;
this . editor . setShowPrintMargin ( false ) ;
this . editor . setFontSize ( 14 ) ;
this . editor . on ( 'change' , ( ) => {
if ( ! settingsCookie [ "bda-css-0" ] ) return ;
this . saveCss ( ) ;
this . updateCss ( ) ;
} ) ;
}
componentWillUnmount ( ) {
this . editor . destroy ( ) ;
2017-04-30 03:11:22 +02:00
}
componentDidUpdate ( prevProps , prevState ) {
let self = this ;
if ( prevState . detached && ! self . state . detached ) {
BDV2 . reactDom . unmountComponentAtNode ( self . detachedRoot ) ;
}
}
codeMirror ( ) {
}
get options ( ) {
return {
lineNumbers : true ,
mode : 'css' ,
indentUnit : 4 ,
theme : 'material' ,
scrollbarStyle : 'simple'
} ;
}
get css ( ) {
let _ccss = window . bdStorage . get ( "bdcustomcss" ) ;
let ccss = "" ;
if ( _ccss && _ccss !== "" ) {
ccss = atob ( _ccss ) ;
}
return ccss ;
}
2018-01-09 04:24:00 +01:00
updateLineCount ( ) {
let lineCount = this . refs . editor . value . split ( '\n' ) . length ;
if ( lineCount == this . props . lines ) return ;
this . refs . lines . textContent = Array . from ( new Array ( lineCount ) , ( _ , i ) => i + 1 ) . join ( ".\n" ) + "." ;
this . props . lines = lineCount ;
}
2017-04-30 03:11:22 +02:00
render ( ) {
let self = this ;
let { detached } = self . state ;
return BDV2 . react . createElement (
"div" ,
{ className : "content-column default" , style : { padding : '60px 40px 0px' } } ,
detached && BDV2 . react . createElement (
"div" ,
{ id : "editor-detached" } ,
BDV2 . react . createElement ( V2Components . SettingsTitle , { text : "Custom CSS Editor" } ) ,
BDV2 . react . createElement (
"h3" ,
null ,
"Editor Detached"
) ,
BDV2 . react . createElement (
"button" ,
{ className : "btn btn-primary" , onClick : ( ) => {
self . attach ( ) ;
} } ,
"Attach"
)
) ,
! detached && BDV2 . react . createElement (
"div" ,
null ,
BDV2 . react . createElement ( V2Components . SettingsTitle , { text : "Custom CSS Editor" } ) ,
2018-01-09 04:24:00 +01:00
BDV2 . react . createElement ( "div" , { className : "editor-wrapper" } ,
2018-01-10 02:08:59 +01:00
BDV2 . react . createElement ( "div" , { id : "bd-customcss-editor" , className : "editor" , ref : "editor" } , self . css )
2018-01-09 04:24:00 +01:00
) ,
2017-04-30 03:11:22 +02:00
BDV2 . react . createElement (
"div" ,
{ id : "bd-customcss-attach-controls" } ,
BDV2 . react . createElement (
"ul" ,
{ className : "checkbox-group" } ,
BDV2 . react . createElement ( V2Components . Checkbox , { id : "live-update" , text : "Live Update" , onChange : this . onChange , checked : settingsCookie [ "bda-css-0" ] } )
) ,
BDV2 . react . createElement (
"div" ,
{ id : "bd-customcss-detach-controls-button" } ,
BDV2 . react . createElement (
"button" ,
{ style : { borderRadius : "3px 0 0 3px" , borderRight : "1px solid #3f4146" } , className : "btn btn-primary" , onClick : ( ) => {
self . onClick ( "update" ) ;
} } ,
"Update"
) ,
BDV2 . react . createElement (
"button" ,
{ style : { borderRadius : "0" , borderLeft : "1px solid #2d2d2d" , borderRight : "1px solid #2d2d2d" } , className : "btn btn-primary" , onClick : ( ) => {
self . onClick ( "save" ) ;
} } ,
"Save"
) ,
BDV2 . react . createElement (
"button" ,
{ style : { borderRadius : "0 3px 3px 0" , borderLeft : "1px solid #3f4146" } , className : "btn btn-primary" , onClick : ( ) => {
self . onClick ( "detach" ) ;
} } ,
"Detach"
) ,
BDV2 . react . createElement (
"span" ,
{ style : { fontSize : "10px" , marginLeft : "5px" } } ,
"Unsaved changes are lost on detach"
)
)
)
)
) ;
}
onClick ( arg ) {
let self = this ;
switch ( arg ) {
case 'update' :
self . updateCss ( ) ;
break ;
case 'save' :
self . saveCss ( ) ;
break ;
case 'detach' :
self . detach ( ) ;
break ;
}
}
onChange ( id , checked ) {
switch ( id ) {
case 'live-update' :
settingsCookie [ "bda-css-0" ] = checked ;
mainCore . saveSettings ( ) ;
break ;
}
}
updateCss ( ) {
if ( $ ( "#customcss" ) . length == 0 ) {
$ ( "head" ) . append ( '<style id="customcss"></style>' ) ;
}
2018-01-10 02:08:59 +01:00
$ ( "#customcss" ) . html ( this . editor . session . getValue ( ) ) . detach ( ) . appendTo ( document . head ) ;
2017-04-30 03:11:22 +02:00
}
saveCss ( ) {
2018-01-10 02:08:59 +01:00
window . bdStorage . set ( "bdcustomcss" , btoa ( this . editor . session . getValue ( ) ) ) ;
2017-04-30 03:11:22 +02:00
}
detach ( ) {
let self = this ;
self . setState ( {
'detached' : true
} ) ;
let droot = self . detachedRoot ;
if ( ! droot ) {
console . log ( "FAILED TO INJECT ROOT: .app" ) ;
return ;
}
BDV2 . reactDom . render ( self . detachedEditor , droot ) ;
}
get detachedRoot ( ) {
let _root = $ ( "#bd-customcss-detach-container" ) ;
if ( ! _root . length ) {
if ( ! this . injectDetachedRoot ( ) ) return null ;
return this . detachedRoot ;
}
return _root [ 0 ] ;
}
injectDetachedRoot ( ) {
if ( ! $ ( ".app" ) . length ) return false ;
$ ( "<div/>" , {
id : 'bd-customcss-detach-container'
} ) . insertAfter ( $ ( ".app" ) ) ;
return true ;
}
attach ( ) {
let self = this ;
self . setState ( {
'detached' : false
} ) ;
}
}
class V2C _List extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
render ( ) {
return BDV2 . react . createElement (
"ul" ,
{ className : this . props . className } ,
this . props . children
) ;
}
}
class V2C _ContentColumn extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
render ( ) {
return BDV2 . react . createElement (
"div" ,
{ className : "content-column default" } ,
BDV2 . react . createElement (
"h2" ,
{ className : "ui-form-title h2 margin-reset margin-bottom-20" } ,
this . props . title
) ,
this . props . children
) ;
}
}
class V2C _PluginCard extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
let self = this ;
self . onChange = self . onChange . bind ( self ) ;
self . showSettings = self . showSettings . bind ( self ) ;
self . setInitialState ( ) ;
2017-12-22 20:29:59 +01:00
self . hasSettings = typeof self . props . plugin . getSettingsPanel === "function" ;
2018-01-09 04:24:00 +01:00
self . settingsPanel = "" ;
2017-04-30 03:11:22 +02:00
}
setInitialState ( ) {
this . state = {
'checked' : pluginCookie [ this . props . plugin . getName ( ) ] ,
'settings' : false
} ;
}
componentDidUpdate ( ) {
if ( this . state . settings ) {
2017-04-30 13:02:42 +02:00
if ( typeof this . settingsPanel === "object" ) {
this . refs . settingspanel . appendChild ( this . settingsPanel ) ;
}
2017-12-24 07:51:24 +01:00
if ( ! settingsCookie [ 'fork-ps-3' ] ) return ;
var isHidden = ( container , element ) => {
let cTop = container . scrollTop ;
let cBottom = cTop + container . clientHeight ;
let eTop = element . offsetTop ;
let eBottom = eTop + element . clientHeight ;
return ( eTop < cTop || eBottom > cBottom ) ;
2018-01-09 04:24:00 +01:00
} ;
2017-12-24 07:51:24 +01:00
let self = $ ( BDV2 . reactDom . findDOMNode ( this ) ) ;
let container = self . parents ( '.scroller' ) ;
if ( ! isHidden ( container [ 0 ] , self [ 0 ] ) ) return ;
container . animate ( {
scrollTop : self . offset ( ) . top - container . offset ( ) . top + container . scrollTop ( ) - 30
} , 300 ) ;
2017-04-30 03:11:22 +02:00
}
}
render ( ) {
2017-04-30 13:02:42 +02:00
let self = this ;
2017-04-30 03:11:22 +02:00
let { plugin } = this . props ;
let name = plugin . getName ( ) ;
let author = plugin . getAuthor ( ) ;
let description = plugin . getDescription ( ) ;
let version = plugin . getVersion ( ) ;
2017-11-01 19:52:57 +01:00
let website = bdplugins [ name ] . website ;
let source = bdplugins [ name ] . source ;
2017-12-22 20:29:59 +01:00
//let { settingsPanel } = this;
2017-04-30 03:11:22 +02:00
if ( this . state . settings ) {
2017-12-22 23:06:56 +01:00
try { self . settingsPanel = plugin . getSettingsPanel ( ) ; }
2017-12-22 20:29:59 +01:00
catch ( err ) { utils . err ( "Unable to get settings panel for " + plugin . getName ( ) + "." , err ) ; }
2017-11-01 18:28:04 +01:00
return BDV2 . react . createElement ( "li" , { className : "settings-open ui-switch-item" } ,
BDV2 . react . createElement ( "div" , { style : { float : "right" , cursor : "pointer" } , onClick : ( ) => {
2017-11-01 18:12:29 +01:00
this . refs . settingspanel . innerHTML = "" ;
2017-11-01 18:28:04 +01:00
self . setState ( { 'settings' : false } ) ;
} } ,
2017-04-30 03:11:22 +02:00
BDV2 . react . createElement ( V2Components . XSvg , null )
) ,
2017-12-22 23:06:56 +01:00
typeof self . settingsPanel === 'object' && BDV2 . react . createElement ( "div" , { id : ` plugin-settings- ${ name } ` , className : "plugin-settings" , ref : "settingspanel" } ) ,
typeof self . settingsPanel !== 'object' && BDV2 . react . createElement ( "div" , { id : ` plugin-settings- ${ name } ` , className : "plugin-settings" , ref : "settingspanel" , dangerouslySetInnerHTML : { _ _html : self . settingsPanel } } )
2017-04-30 03:11:22 +02:00
) ;
}
2017-11-01 18:12:29 +01:00
return BDV2 . react . createElement ( "li" , { "data-name" : name , "data-version" : version , className : "settings-closed ui-switch-item" } ,
BDV2 . react . createElement ( "div" , { className : "bda-header" } ,
2017-11-01 17:09:58 +01:00
BDV2 . react . createElement ( "span" , { className : "bda-header-title" } ,
BDV2 . react . createElement ( "span" , { className : "bda-name" } , name ) ,
" v" ,
BDV2 . react . createElement ( "span" , { className : "bda-version" } , version ) ,
" by " ,
BDV2 . react . createElement ( "span" , { className : "bda-author" } , author )
) ,
BDV2 . react . createElement ( "label" , { className : "ui-switch-wrapper ui-flex-child" , style : { flex : '0 0 auto' } } ,
2017-11-01 16:21:55 +01:00
BDV2 . react . createElement ( "input" , { checked : this . state . checked , onChange : this . onChange , className : "ui-switch-checkbox" , type : "checkbox" } ) ,
2017-11-01 18:12:29 +01:00
BDV2 . react . createElement ( "div" , { className : this . state . checked ? "ui-switch checked" : "ui-switch" } )
2017-04-30 03:11:22 +02:00
)
) ,
2017-11-01 18:12:29 +01:00
BDV2 . react . createElement ( "div" , { className : "bda-description-wrap scroller-wrap fade" } ,
BDV2 . react . createElement ( "div" , { className : "bda-description scroller" } , description )
2017-11-01 16:21:55 +01:00
) ,
2017-12-24 07:51:24 +01:00
( website || source || this . hasSettings ) && BDV2 . react . createElement ( "div" , { className : "bda-footer" } ,
2017-11-01 18:12:29 +01:00
BDV2 . react . createElement ( "span" , { className : "bda-links" } ,
website && BDV2 . react . createElement ( "a" , { className : "bda-link" , href : website , target : "_blank" } , "Website" ) ,
website && source && " | " ,
source && BDV2 . react . createElement ( "a" , { className : "bda-link" , href : source , target : "_blank" } , "Source" )
) ,
2017-12-22 20:29:59 +01:00
this . hasSettings && BDV2 . react . createElement ( "button" , { onClick : this . showSettings , className : "bda-settings-button" , disabled : ! this . state . checked } , "Settings" )
2017-04-30 03:11:22 +02:00
)
) ;
}
onChange ( ) {
2017-11-01 18:34:00 +01:00
this . setState ( { 'checked' : ! this . state . checked } ) ;
pluginModule . togglePlugin ( this . props . plugin . getName ( ) ) ;
2017-04-30 03:11:22 +02:00
}
2017-12-22 20:29:59 +01:00
showSettings ( ) {
if ( ! this . hasSettings ) return ;
2017-11-01 18:28:04 +01:00
this . setState ( { 'settings' : true } ) ;
2017-04-30 03:11:22 +02:00
}
}
class V2C _ThemeCard extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
this . setInitialState ( ) ;
this . onChange = this . onChange . bind ( this ) ;
}
setInitialState ( ) {
this . state = {
'checked' : themeCookie [ this . props . theme . name ]
} ;
}
render ( ) {
let { theme } = this . props ;
2017-10-31 10:12:58 +01:00
let name = theme . name ;
2017-04-30 03:11:22 +02:00
let description = theme . description ;
let version = theme . version ;
let author = theme . author ;
2017-11-01 18:12:29 +01:00
let website = bdthemes [ name ] . website ;
let source = bdthemes [ name ] . source ;
2017-11-01 17:09:58 +01:00
2017-11-01 18:28:04 +01:00
return BDV2 . react . createElement ( "li" , { "data-name" : name , "data-version" : version , className : "settings-closed ui-switch-item" } ,
BDV2 . react . createElement ( "div" , { className : "bda-header" } ,
2017-11-01 17:09:58 +01:00
BDV2 . react . createElement ( "span" , { className : "bda-header-title" } ,
BDV2 . react . createElement ( "span" , { className : "bda-name" } , name ) ,
" v" ,
BDV2 . react . createElement ( "span" , { className : "bda-version" } , version ) ,
" by " ,
BDV2 . react . createElement ( "span" , { className : "bda-author" } , author )
) ,
2017-11-01 17:56:51 +01:00
BDV2 . react . createElement ( "label" , { className : "ui-switch-wrapper ui-flex-child" , style : { flex : '0 0 auto' } } ,
BDV2 . react . createElement ( "input" , { checked : this . state . checked , onChange : this . onChange , className : "ui-switch-checkbox" , type : "checkbox" } ) ,
2017-11-01 18:12:29 +01:00
BDV2 . react . createElement ( "div" , { className : this . state . checked ? "ui-switch checked" : "ui-switch" } )
2017-11-01 17:56:51 +01:00
)
2017-04-30 03:11:22 +02:00
) ,
2017-11-01 18:28:04 +01:00
BDV2 . react . createElement ( "div" , { className : "bda-description-wrap scroller-wrap fade" } ,
BDV2 . react . createElement ( "div" , { className : "bda-description scroller" } , description )
2017-11-01 17:09:58 +01:00
) ,
2017-12-24 07:51:24 +01:00
( website || source ) && BDV2 . react . createElement ( "div" , { className : "bda-footer" } ,
2017-11-01 18:12:29 +01:00
BDV2 . react . createElement ( "span" , { className : "bda-links" } ,
website && BDV2 . react . createElement ( "a" , { className : "bda-link" , href : website , target : "_blank" } , "Website" ) ,
website && source && " | " ,
source && BDV2 . react . createElement ( "a" , { className : "bda-link" , href : source , target : "_blank" } , "Source" )
)
2017-04-30 03:11:22 +02:00
)
) ;
}
onChange ( ) {
2017-11-01 18:34:00 +01:00
this . setState ( { 'checked' : ! this . state . checked } ) ;
themeModule . toggleTheme ( this . props . theme . name ) ;
2017-04-30 03:11:22 +02:00
}
}
class V2Cs _TabBar {
static get Item ( ) {
return V2C _TabBarItem ;
}
static get Header ( ) {
return V2C _TabBarHeader ;
}
static get Separator ( ) {
return V2C _TabBarSeparator ;
}
}
2018-01-09 04:24:00 +01:00
class V2Components {
static get SettingsPanel ( ) {
return V2C _SettingsPanel ;
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
static get Switch ( ) {
return V2C _Switch ;
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
static get Scroller ( ) {
return V2C _Scroller ;
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
static get TabBar ( ) {
return V2Cs _TabBar ;
}
static get SideBar ( ) {
return V2C _SideBar ;
}
static get Tools ( ) {
return V2C _Tools ;
}
static get SettingsTitle ( ) {
return V2C _SettingsTitle ;
}
static get CssEditor ( ) {
return V2C _CssEditor ;
}
static get Checkbox ( ) {
return V2C _Checkbox ;
}
static get List ( ) {
return V2C _List ;
}
static get PluginCard ( ) {
return V2C _PluginCard ;
}
static get ThemeCard ( ) {
return V2C _ThemeCard ;
}
static get ContentColumn ( ) {
return V2C _ContentColumn ;
}
static get XSvg ( ) {
return V2C _XSvg ;
}
static get Layer ( ) {
return V2C _Layer ;
}
static get SidebarView ( ) {
return V2C _SidebarView ;
}
static get ServerCard ( ) {
return V2C _ServerCard ;
2017-04-30 03:11:22 +02:00
}
}
2018-01-09 04:24:00 +01:00
class V2 _SettingsPanel _Sidebar {
2017-04-30 03:11:22 +02:00
2018-01-09 04:24:00 +01:00
constructor ( onClick ) {
this . onClick = onClick ;
2017-04-30 03:11:22 +02:00
}
2018-01-09 04:24:00 +01:00
get items ( ) {
return [ { 'text' : 'Core' , 'id' : 'core' } , { 'text' : 'Zere\'s Fork' , 'id' : 'fork' } , { 'text' : 'Emotes' , 'id' : 'emotes' } , { 'text' : 'Custom CSS' , 'id' : 'customcss' } , { 'text' : 'Plugins' , 'id' : 'plugins' } , { 'text' : 'Themes' , 'id' : 'themes' } ] ;
}
get component ( ) {
2017-04-30 03:11:22 +02:00
return BDV2 . react . createElement (
2018-01-09 04:24:00 +01:00
"span" ,
null ,
BDV2 . react . createElement ( V2Components . SideBar , { onClick : this . onClick , headerText : "Bandaged BD" , items : this . items } ) ,
2017-04-30 03:11:22 +02:00
BDV2 . react . createElement (
"div" ,
2018-01-09 04:24:00 +01:00
{ style : { fontSize : "12px" , fontWeight : "600" , color : "#72767d" , padding : "2px 10px" } } ,
` BD v ${ bdVersion } , JS v ${ jsVersion } by ` ,
BDV2 . react . createElement (
"a" ,
{ href : "https://github.com/Jiiks/" , target : "_blank" } ,
"Jiiks"
)
2017-04-30 03:11:22 +02:00
) ,
2018-01-09 04:24:00 +01:00
BDV2 . react . createElement (
2017-04-30 03:11:22 +02:00
"div" ,
2018-01-09 04:24:00 +01:00
{ style : { fontSize : "12px" , fontWeight : "600" , color : "#72767d" , padding : "2px 10px" } } ,
` BBD v ${ bbdVersion } by ` ,
BDV2 . react . createElement (
"a" ,
{ href : "https://github.com/rauenzi/" , target : "_blank" } ,
"Zerebos"
)
2017-04-30 03:11:22 +02:00
)
) ;
}
2018-01-09 04:24:00 +01:00
get root ( ) {
let _root = $ ( "#bd-settings-sidebar" ) ;
if ( ! _root . length ) {
if ( ! this . injectRoot ( ) ) return null ;
return this . root ;
}
return _root [ 0 ] ;
}
injectRoot ( ) {
let changeLog = $ ( "[class*=side] > [class*=item]:not([class*=Danger])" ) . last ( ) ;
if ( ! changeLog . length ) return false ;
$ ( "<span/>" , { 'id' : 'bd-settings-sidebar' } ) . insertBefore ( changeLog . prev ( ) ) ;
return true ;
2017-04-30 03:11:22 +02:00
}
render ( ) {
2018-01-09 04:24:00 +01:00
let root = this . root ;
if ( ! root ) {
console . log ( "FAILED TO LOCATE ROOT: [class*=side] > [class*=item]:not([class*=Danger])" ) ;
return ;
}
BDV2 . reactDom . render ( this . component , root ) ;
}
}
2017-04-30 03:11:22 +02:00
class V2 _SettingsPanel {
constructor ( ) {
let self = this ;
self . sideBarOnClick = self . sideBarOnClick . bind ( self ) ;
self . onChange = self . onChange . bind ( self ) ;
self . updateSettings = this . updateSettings . bind ( self ) ;
self . sidebar = new V2 _SettingsPanel _Sidebar ( self . sideBarOnClick ) ;
}
get root ( ) {
let _root = $ ( "#bd-settingspane-container" ) ;
if ( ! _root . length ) {
if ( ! this . injectRoot ( ) ) return null ;
return this . root ;
}
return _root [ 0 ] ;
}
injectRoot ( ) {
2018-01-10 02:08:59 +01:00
if ( ! $ ( ".layer .ui-standard-sidebar-view, .layer-kosS71 .ui-standard-sidebar-view" ) . length ) return false ;
$ ( ".layer .ui-standard-sidebar-view, .layer-kosS71 .ui-standard-sidebar-view" ) . append ( $ ( "<div/>" , {
2017-04-30 03:11:22 +02:00
class : 'content-region' ,
id : 'bd-settingspane-container'
} ) ) ;
return true ;
}
get coreSettings ( ) {
return this . getSettings ( "core" ) ;
2017-12-24 07:51:24 +01:00
}
get forkSettings ( ) {
return this . getSettings ( "fork" ) ;
2017-04-30 03:11:22 +02:00
}
get emoteSettings ( ) {
return this . getSettings ( "emote" ) ;
}
getSettings ( category ) {
return Object . keys ( settings ) . reduce ( ( arr , key ) => {
let setting = settings [ key ] ;
if ( setting . cat === category && setting . implemented && ! setting . hidden ) {
setting . text = key ;
arr . push ( setting ) ;
}
return arr ;
} , [ ] ) ;
}
sideBarOnClick ( id ) {
let self = this ;
$ ( ".content-region" ) . first ( ) . hide ( ) ;
$ ( self . root ) . show ( ) ;
switch ( id ) {
case 'core' :
self . renderCoreSettings ( ) ;
break ;
2017-12-24 07:51:24 +01:00
case 'fork' :
self . renderForkSettings ( ) ;
break ;
2017-04-30 03:11:22 +02:00
case 'emotes' :
self . renderEmoteSettings ( ) ;
break ;
case 'customcss' :
self . renderCustomCssEditor ( ) ;
break ;
case 'plugins' :
self . renderPluginPane ( ) ;
break ;
case 'themes' :
self . renderThemePane ( ) ;
break ;
}
}
2017-11-03 04:05:33 +01:00
onClick ( ) { }
2017-04-30 03:11:22 +02:00
onChange ( id , checked ) {
settingsCookie [ id ] = checked ;
this . updateSettings ( ) ;
}
updateSettings ( ) {
2017-10-30 22:33:38 +01:00
let _c = settingsCookie ;
if ( _c [ "bda-es-0" ] ) {
$ ( "#twitchcord-button-container" ) . show ( ) ;
} else {
$ ( "#twitchcord-button-container" ) . hide ( ) ;
}
if ( _c [ "bda-gs-b" ] ) {
$ ( "body" ) . addClass ( "bd-blue" ) ;
} else {
$ ( "body" ) . removeClass ( "bd-blue" ) ;
}
if ( _c [ "bda-gs-2" ] ) {
$ ( "body" ) . addClass ( "bd-minimal" ) ;
} else {
$ ( "body" ) . removeClass ( "bd-minimal" ) ;
}
if ( _c [ "bda-gs-3" ] ) {
$ ( "body" ) . addClass ( "bd-minimal-chan" ) ;
} else {
$ ( "body" ) . removeClass ( "bd-minimal-chan" ) ;
}
if ( _c [ "bda-gs-1" ] ) {
$ ( "#bd-pub-li" ) . show ( ) ;
} else {
$ ( "#bd-pub-li" ) . hide ( ) ;
}
if ( _c [ "bda-gs-4" ] ) {
voiceMode . enable ( ) ;
} else {
voiceMode . disable ( ) ;
}
if ( _c [ "bda-gs-5" ] ) {
$ ( "#app-mount" ) . addClass ( "bda-dark" ) ;
} else {
$ ( "#app-mount" ) . removeClass ( "bda-dark" ) ;
}
2017-11-04 06:59:30 +01:00
if ( document . querySelector ( '.messages' ) ) {
let elem = document . querySelector ( '.messages' ) ;
if ( _c [ "bda-gs-6" ] ) {
mainCore . inject24Hour ( elem ) ;
} else {
mainCore . remove24Hour ( elem ) ;
}
if ( _c [ "bda-gs-7" ] && document . querySelector ( '.messages' ) ) {
mainCore . injectColoredText ( elem ) ;
} else {
mainCore . removeColoredText ( elem ) ;
}
}
2017-12-24 07:51:24 +01:00
if ( _c [ "fork-es-2" ] ) {
$ ( '.emote' ) . each ( ( ) => {
2018-01-09 04:24:00 +01:00
$ ( this ) . addClass ( "stop-animation" ) ;
2017-12-24 07:51:24 +01:00
} ) ;
}
else {
$ ( '.emote' ) . each ( ( ) => {
2018-01-09 04:24:00 +01:00
$ ( this ) . removeClass ( "stop-animation" ) ;
2017-12-24 07:51:24 +01:00
} ) ;
}
$ ( document ) . off ( 'mouseover' , '.emote' ) ;
//Pretty emote titles
var emoteNamePopup = $ ( "<div class='tipsy tipsy-se' style='display: block; top: 82px; left: 1630.5px; visibility: visible; opacity: 0.8;'><div class='tipsy-inner'></div></div>" ) ;
$ ( document ) . on ( "mouseover" , ".emote" , function ( ) {
var emote = $ ( this ) ;
if ( _c [ "fork-es-2" ] && _c [ "bda-es-8" ] ) emote . removeClass ( "stop-animation" ) ;
if ( ! _c [ "bda-es-6" ] ) return ;
var x = emote . offset ( ) ;
var title = emote . attr ( "alt" ) ;
2018-01-09 04:24:00 +01:00
var modifier = emote . attr ( "data-modifier" ) ;
2017-12-24 07:51:24 +01:00
if ( modifier && _c [ "fork-es-1" ] ) title = title + ":" + modifier ;
emoteNamePopup . find ( ".tipsy-inner" ) . text ( title ) ;
$ ( ".app" ) . append ( $ ( emoteNamePopup ) ) ;
var nodecenter = x . left + ( emote . outerWidth ( ) / 2 ) ;
emoteNamePopup . css ( "left" , nodecenter - ( emoteNamePopup . outerWidth ( ) / 2 ) ) ;
emoteNamePopup . css ( 'top' , x . top - emoteNamePopup . outerHeight ( ) ) ;
} ) ;
$ ( document ) . on ( "mouseleave" , ".emote" , function ( ) {
if ( _c [ "bda-es-6" ] ) $ ( ".tipsy" ) . remove ( ) ;
if ( _c [ "fork-es-2" ] && _c [ "bda-es-8" ] ) $ ( this ) . addClass ( "stop-animation" ) ;
} ) ;
2017-10-30 22:33:38 +01:00
if ( _c [ "bda-gs-8" ] ) {
2017-12-24 07:51:24 +01:00
dMode . enable ( _c [ "fork-dm-1" ] ) ;
2017-10-30 22:33:38 +01:00
} else {
dMode . disable ( ) ;
}
mainCore . saveSettings ( ) ;
2017-04-30 03:11:22 +02:00
}
renderSidebar ( ) {
let self = this ;
2017-11-03 04:05:33 +01:00
$ ( "[class*=side] > [class*=item]" ) . off ( 'click.v2settingspanel' ) . on ( 'click.v2settingspanel' , ( ) => {
2017-04-30 03:11:22 +02:00
BDV2 . reactDom . unmountComponentAtNode ( self . root ) ;
$ ( self . root ) . hide ( ) ;
$ ( ".content-region" ) . first ( ) . show ( ) ;
} ) ;
self . sidebar . render ( ) ;
}
get coreComponent ( ) {
return BDV2 . react . createElement ( V2Components . Scroller , { fade : true , dark : true , children : [ BDV2 . react . createElement ( V2Components . SettingsPanel , { key : "cspanel" , title : "Core Settings" , onChange : this . onChange , settings : this . coreSettings } ) , BDV2 . react . createElement ( V2Components . Tools , { key : "tools" } ) ] } ) ;
}
2017-12-24 07:51:24 +01:00
get forkComponent ( ) {
return BDV2 . react . createElement ( V2Components . Scroller , {
fade : true ,
dark : true ,
children : [
BDV2 . react . createElement ( V2Components . SettingsPanel , { key : "fspanel" , title : "Zere's Fork Settings" , onChange : this . onChange , settings : this . forkSettings , button : {
2018-01-09 04:24:00 +01:00
title : "Clear Emote Cache" ,
2018-01-09 22:32:02 +01:00
onClick : ( ) => { emoteModule . clearEmoteData ( ) ; emoteModule . init ( ) ; quickEmoteMenu . init ( ) ; }
2017-12-24 07:51:24 +01:00
} } ) ,
BDV2 . react . createElement ( V2Components . Tools , { key : "tools" } )
]
}
) ;
}
2017-04-30 03:11:22 +02:00
get emoteComponent ( ) {
return BDV2 . react . createElement ( V2Components . Scroller , { fade : true , dark : true , children : [ BDV2 . react . createElement ( V2Components . SettingsPanel , { key : "espanel" , title : "Emote Settings" , onChange : this . onChange , settings : this . emoteSettings } ) , BDV2 . react . createElement ( V2Components . Tools , { key : "tools" } ) ] } ) ;
}
get customCssComponent ( ) {
return BDV2 . react . createElement ( V2Components . Scroller , { fade : true , dark : true , children : [ BDV2 . react . createElement ( V2Components . CssEditor , { key : "csseditor" } ) , BDV2 . react . createElement ( V2Components . Tools , { key : "tools" } ) ] } ) ;
}
get pluginsComponent ( ) {
let plugins = Object . keys ( bdplugins ) . reduce ( ( arr , key ) => {
arr . push ( BDV2 . react . createElement ( V2Components . PluginCard , { key : key , plugin : bdplugins [ key ] . plugin } ) ) ; return arr ;
} , [ ] ) ;
let list = BDV2 . react . createElement ( V2Components . List , { key : "plugin-list" , className : "bda-slist" , children : plugins } ) ;
2017-10-29 22:20:45 +01:00
let pfBtn = BDV2 . react . createElement ( "button" , { key : "folder-button" , className : 'bd-pfbtn' , onClick : ( ) => { betterDiscordIPC . send ( 'asynchronous-message' , { 'arg' : 'opendir' , 'path' : 'plugindir' } ) ; } } , "Open Plugin Folder" ) ;
2017-05-12 21:45:19 +02:00
let contentColumn = BDV2 . react . createElement ( V2Components . ContentColumn , { key : "pcolumn" , title : "Plugins" , children : [ pfBtn , list ] } ) ;
2017-04-30 03:11:22 +02:00
return BDV2 . react . createElement ( V2Components . Scroller , { fade : true , dark : true , children : [ contentColumn , BDV2 . react . createElement ( V2Components . Tools , { key : "tools" } ) ] } ) ;
}
get themesComponent ( ) {
let themes = Object . keys ( bdthemes ) . reduce ( ( arr , key ) => {
arr . push ( BDV2 . react . createElement ( V2Components . ThemeCard , { key : key , theme : bdthemes [ key ] } ) ) ; return arr ;
} , [ ] ) ;
let list = BDV2 . react . createElement ( V2Components . List , { key : "theme-list" , className : "bda-slist" , children : themes } ) ;
2017-10-29 22:20:45 +01:00
let tfBtn = BDV2 . react . createElement ( "button" , { key : "folder-button" , className : 'bd-pfbtn' , onClick : ( ) => { betterDiscordIPC . send ( 'asynchronous-message' , { 'arg' : 'opendir' , 'path' : 'themedir' } ) ; } } , "Open Theme Folder" ) ;
2017-05-12 21:45:19 +02:00
let contentColumn = BDV2 . react . createElement ( V2Components . ContentColumn , { key : "tcolumn" , title : "Themes" , children : [ tfBtn , list ] } ) ;
2017-04-30 03:11:22 +02:00
return BDV2 . react . createElement ( V2Components . Scroller , { fade : true , dark : true , children : [ contentColumn , BDV2 . react . createElement ( V2Components . Tools , { key : "tools" } ) ] } ) ;
}
renderCoreSettings ( ) {
let root = this . root ;
if ( ! root ) {
console . log ( "FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view" ) ;
return ;
}
BDV2 . reactDom . render ( this . coreComponent , root ) ;
}
2017-12-24 07:51:24 +01:00
renderForkSettings ( ) {
let root = this . root ;
if ( ! root ) {
console . log ( "FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view" ) ;
return ;
}
BDV2 . reactDom . render ( this . forkComponent , root ) ;
}
2017-04-30 03:11:22 +02:00
renderEmoteSettings ( ) {
let root = this . root ;
if ( ! root ) {
console . log ( "FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view" ) ;
return ;
}
BDV2 . reactDom . render ( this . emoteComponent , root ) ;
}
renderCustomCssEditor ( ) {
let root = this . root ;
if ( ! root ) {
console . log ( "FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view" ) ;
return ;
}
BDV2 . reactDom . render ( this . customCssComponent , root ) ;
}
renderPluginPane ( ) {
let root = this . root ;
if ( ! root ) {
console . log ( "FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view" ) ;
return ;
}
BDV2 . reactDom . render ( this . pluginsComponent , root ) ;
}
renderThemePane ( ) {
let root = this . root ;
if ( ! root ) {
console . log ( "FAILED TO LOCATE ROOT: .layer .ui-standard-sidebar-view" ) ;
return ;
}
BDV2 . reactDom . render ( this . themesComponent , root ) ;
}
}
2018-01-09 04:24:00 +01:00
class V2C _Layer extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
componentDidMount ( ) {
$ ( window ) . on ( ` keyup. ${ this . props . id } ` , e => {
if ( e . which === 27 ) {
BDV2 . reactDom . unmountComponentAtNode ( this . refs . root . parentNode ) ;
}
} ) ;
}
componentWillUnmount ( ) {
$ ( window ) . off ( ` keyup. ${ this . props . id } ` ) ;
$ ( ` # ${ this . props . rootId } ` ) . remove ( ) ;
}
render ( ) {
return BDV2 . react . createElement (
"div" ,
2018-01-10 02:08:59 +01:00
{ className : "layer bd-layer layer-kosS71" , id : this . props . id , ref : "root" } ,
2018-01-09 04:24:00 +01:00
this . props . children
) ;
}
}
class V2C _SidebarView extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
}
render ( ) {
let { sidebar , content , tools } = this . props . children ;
return BDV2 . react . createElement (
"div" ,
{ className : "ui-standard-sidebar-view" } ,
BDV2 . react . createElement (
"div" ,
{ className : "sidebar-region" } ,
BDV2 . react . createElement ( V2Components . Scroller , { key : "sidebarScroller" , ref : "sidebarScroller" , fade : sidebar . fade || true , dark : sidebar . dark || true , children : sidebar . component } )
) ,
BDV2 . react . createElement ( "div" , { className : "content-region" } ,
BDV2 . react . createElement ( "div" , { className : "content-transition-wrap" } ,
BDV2 . react . createElement ( "div" , { className : "scrollerWrap-2uBjct content-region-scroller-wrap scrollerThemed-19vinI themeGhost-10fio9 scrollerTrack-3hhmU0" } ,
BDV2 . react . createElement ( "div" , { className : "scroller-fzNley content-region-scroller" } ,
BDV2 . react . createElement ( "div" , { className : "content-column default" } , content . component ) ,
tools . component
)
)
)
)
) ;
}
}
class V2 _PublicServers {
constructor ( ) { }
get component ( ) {
return BDV2 . react . createElement ( V2Components . Layer , { rootId : "pubslayerroot" , id : "pubslayer" , children : BDV2 . react . createElement ( V2C _PublicServers , { rootId : "pubslayerroot" } ) } ) ;
}
get root ( ) {
let _root = document . getElementById ( "pubslayerroot" ) ;
if ( ! _root ) {
if ( ! this . injectRoot ( ) ) return null ;
return this . root ;
}
return _root ;
}
injectRoot ( ) {
2018-01-10 02:08:59 +01:00
if ( ! $ ( ".layers, .layers-20RVFW" ) . length ) return false ;
$ ( ".layers, .layers-20RVFW" ) . append ( $ ( "<div/>" , {
2018-01-09 04:24:00 +01:00
id : 'pubslayerroot'
} ) ) ;
return true ;
}
render ( ) {
let root = this . root ;
if ( ! root ) {
console . log ( "FAILED TO LOCATE ROOT: .layers" ) ;
return ;
}
BDV2 . reactDom . render ( this . component , root ) ;
}
get button ( ) {
let btn = $ ( "<div/>" , {
class : 'guild' ,
id : 'bd-pub-li' ,
css : {
'height' : '20px' ,
'display' : settingsCookie [ 'bda-gs-1' ] ? "" : "none"
}
} ) . append ( $ ( "<div/>" , {
class : 'guild-inner' ,
css : {
'height' : '20px' ,
'border-radius' : '4px'
}
} ) . append ( $ ( "<a/>" , {
} ) . append ( $ ( "<div/>" , {
text : 'public' ,
id : 'bd-pub-button' ,
css : {
'line-height' : '20px' ,
'font-size' : '12px'
} ,
click : ( ) => { this . render ( ) ; }
} ) ) ) ) ;
return btn ;
}
initialize ( ) {
let guilds = $ ( ".guilds>:first-child" ) ;
guilds . after ( this . button ) ;
}
}
class V2C _ServerCard extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
this . state = {
imageError : false ,
joined : this . props . guildList . includes ( this . props . server . identifier )
} ;
}
render ( ) {
let { server } = this . props ;
return BDV2 . react . createElement (
"div" ,
{ className : ` ui-card ui-card-primary bd-server-card ${ server . pinned ? ' bd-server-card-pinned' : '' } ` , style : { marginTop : "5px" } } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-flex horizontal" , style : { display : "flex" , flexFlow : "row nowrap" , justifyContent : "flex-start" , alignItems : "stretch" , flex : "1 1 auto" } } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-flex-child" , style : { flex : "0 1 auto" , padding : "5px" } } ,
BDV2 . react . createElement ( "img" , { ref : "img" , className : "bd-pubs-server-icon" , src : server . icon , style : { width : "100px" , height : "100px" } , onError : this . handleError . bind ( this ) } )
) ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-flex-child" , style : { flex : "1 1 auto" , padding : "5px" } } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-flex horizontal" } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-form-item" , style : { flex : "1 1 auto" } } ,
BDV2 . react . createElement (
"h5" ,
{ className : "ui-form-title h5 margin-reset" } ,
server . name
)
) ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-form-item" } ,
BDV2 . react . createElement (
"h5" ,
{ className : "ui-form-title h5 margin-reset" } ,
server . online ,
"/" ,
server . members ,
" Members"
)
)
) ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-flex horizontal" } ,
BDV2 . react . createElement (
"div" ,
{ className : "scroller-wrap fade dark" , style : { minHeight : "60px" , maxHeight : "60px" , borderTop : "1px solid #3f4146" , borderBottom : "1px solid #3f4146" , paddingTop : "5px" } } ,
BDV2 . react . createElement (
"div" ,
{ className : "scroller" } ,
BDV2 . react . createElement (
"div" ,
{ style : { fontSize : "13px" , color : "#b9bbbe" } } ,
server . description
)
)
)
) ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-flex horizontal" } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-flex-child bd-server-tags" , style : { flex : "1 1 auto" } } ,
server . categories . join ( ', ' )
) ,
this . state . joined && BDV2 . react . createElement (
"button" ,
{ type : "button" , className : "ui-button filled brand small grow disabled" , style : { minHeight : "12px" , marginTop : "4px" , backgroundColor : "#3ac15c" } } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-button-contents" } ,
"Joined"
)
) ,
server . error && BDV2 . react . createElement (
"button" ,
{ type : "button" , className : "ui-button filled brand small grow disabled" , style : { minHeight : "12px" , marginTop : "4px" , backgroundColor : "#c13a3a" } } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-button-contents" } ,
"Error"
)
) ,
! server . error && ! this . state . joined && server . invite _code && BDV2 . react . createElement (
"button" ,
{ type : "button" , className : "ui-button filled brand small grow" , style : { minHeight : "12px" , marginTop : "4px" } , onClick : ( ) => { this . join ( ) ; } } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-button-contents" } ,
"Join"
)
)
)
)
)
) ;
}
handleError ( ) {
this . props . server . icon = this . props . fallback ;
this . setState ( { imageError : true } ) ;
}
join ( ) {
this . props . join ( this . props . server ) ;
this . setState ( { joined : true } ) ;
}
}
class V2C _PublicServers extends BDV2 . reactComponent {
constructor ( props ) {
super ( props ) ;
this . setInitialState ( ) ;
this . close = this . close . bind ( this ) ;
this . changeCategory = this . changeCategory . bind ( this ) ;
this . search = this . search . bind ( this ) ;
this . searchKeyDown = this . searchKeyDown . bind ( this ) ;
this . checkConnection = this . checkConnection . bind ( this ) ;
this . join = this . join . bind ( this ) ;
this . GuildStore = BDV2 . WebpackModules . findByUniqueProperties ( [ "getGuilds" ] ) ;
this . AvatarDefaults = BDV2 . WebpackModules . findByUniqueProperties ( [ "getUserAvatarURL" , "DEFAULT_AVATARS" ] ) ;
this . InviteActions = BDV2 . WebpackModules . findByUniqueProperties ( [ 'acceptInvite' ] ) ;
}
componentDidMount ( ) {
this . checkConnection ( ) ;
}
setInitialState ( ) {
this . state = {
'selectedCategory' : - 1 ,
'title' : 'Loading...' ,
'loading' : true ,
'servers' : [ ] ,
'next' : null ,
'connection' : {
'state' : 0 ,
'user' : null
}
} ;
}
close ( ) {
BDV2 . reactDom . unmountComponentAtNode ( document . getElementById ( this . props . rootId ) ) ;
}
search ( query , clear ) {
let self = this ;
$ . ajax ( {
method : 'GET' ,
url : ` ${ self . endPoint } ${ query } ` ,
success : data => {
console . log ( data ) ;
let servers = data . results . reduce ( ( arr , server ) => {
server . joined = false ;
arr . push ( server ) ;
// arr.push(<V2Components.ServerCard server={server} join={self.join}/>);
return arr ;
} , [ ] ) ;
if ( ! clear ) {
servers = self . state . servers . concat ( servers ) ;
} else {
//servers.unshift(self.bdServer);
}
let end = data . size + data . from ;
if ( end >= data . total ) {
end = data . total ;
data . next = null ;
}
let title = ` Showing 1- ${ end } of ${ data . total } results in ${ self . categoryButtons [ self . state . selectedCategory ] } ` ;
if ( self . state . term ) title += ` for ${ self . state . term } ` ;
self . setState ( {
'loading' : false ,
'title' : title ,
'servers' : servers ,
'next' : data . next
} ) ;
if ( clear ) {
self . refs . sbv . refs . contentScroller . refs . scroller . scrollTop = 0 ;
}
} ,
error : ( jqXHR ) => {
self . setState ( {
'loading' : false ,
'title' : 'Failed to load servers. Check console for details'
} ) ;
console . log ( jqXHR ) ;
}
} ) ;
}
join ( server ) {
this . InviteActions . acceptInvite ( server . invite _code ) ;
}
// connect() {
// let self = this;
// let options = self.windowOptions;
// options.x = Math.round(window.screenX + window.innerWidth / 2 - options.width / 2);
// options.y = Math.round(window.screenY + window.innerHeight / 2 - options.height / 2);
// self.joinWindow = new (window.require('electron').remote.BrowserWindow)(options);
// let sub = window.location.hostname.split('.')[0];
// let url = self.connectEndPoint + (sub === 'canary' || sub === 'ptb' ? `/${sub}` : '');
// self.joinWindow.webContents.on('did-navigate', (event, url) => {
// if (!url.includes("connect/callback")) return;
// self.joinWindow.close();
// });
// self.joinWindow.loadURL(url);
// console.log(url)
// }
// joinID(identifier) {
// let self = this;
// let options = self.windowOptions;
// options.x = Math.round(window.screenX + window.innerWidth / 2 - options.width / 2);
// options.y = Math.round(window.screenY + window.innerHeight / 2 - options.height / 2);
// self.joinWindow = new (window.require('electron').remote.BrowserWindow)(options);
// let sub = window.location.hostname.split('.')[0];
// let url = self.joinEndPoint + "/" + identifier;
// self.joinWindow.webContents.on('did-navigate', (event, url) => {
// if (!url.includes("connect/callback")) return;
// self.joinWindow.close();
// });
// self.joinWindow.loadURL(url);
// console.log(url)
// }
// get windowOptions() {
// return {
// width: 520,
// height: 710,
// backgroundColor: '#282b30',
// show: true,
// resizable: false,
// maximizable: false,
// minimizable: false,
// alwaysOnTop: true,
// frame: false,
// center: false
// };
// }
get bdServer ( ) {
let server = {
"name" : "BetterDiscord" ,
"online" : "7500+" ,
"members" : "20000+" ,
"categories" : [ "community" , "programming" , "support" ] ,
"description" : "Official BetterDiscord server for support etc" ,
"identifier" : "86004744966914048" ,
"icon" : "https://cdn.discordapp.com/icons/86004744966914048/c8d49dc02248e1f55caeb897c3e1a26e.png" ,
"nativejoin" : true ,
"invite_code" : "0Tmfo5ZbORCRqbAd" ,
"pinned" : true
} ;
let guildList = Object . keys ( this . GuildStore . getGuilds ( ) ) ;
let defaultList = this . AvatarDefaults . DEFAULT _AVATARS ;
return BDV2 . react . createElement ( V2Components . ServerCard , { server : server , pinned : true , join : this . join , guildList : guildList , fallback : defaultList [ Math . floor ( Math . random ( ) * 5 ) ] } ) ;
}
get endPoint ( ) {
return 'https://search.discordservers.com' ;
}
get joinEndPoint ( ) {
return 'https://join.discordservers.com' ;
}
get connectEndPoint ( ) {
return 'https://join.discordservers.com/connect' ;
}
checkConnection ( ) {
let self = this ;
try {
$ . ajax ( {
method : 'GET' ,
url : ` ${ self . endPoint } ` ,
success : data => {
self . setState ( {
'selectedCategory' : 0 ,
'connection' : {
'state' : 2 ,
'user' : data
}
} ) ;
self . search ( "" , true ) ;
} ,
error : jqXHR => {
if ( jqXHR . status === 403 || jqXHR . status === 404 ) {
//Not connected
self . setState ( {
'title' : 'Not connected to discordservers.com!' ,
'loading' : true ,
'selectedCategory' : - 1 ,
'connection' : {
'state' : 1 ,
'user' : null
}
} ) ;
return ;
}
console . log ( jqXHR ) ;
}
} ) ;
}
catch ( error ) {
self . setState ( {
'title' : 'Not connected to discordservers.com!' ,
'loading' : true ,
'selectedCategory' : - 1 ,
'connection' : {
'state' : 1 ,
'user' : null
}
} ) ;
}
}
render ( ) {
return BDV2 . react . createElement ( V2Components . SidebarView , { ref : "sbv" , children : this . component } ) ;
}
get component ( ) {
return {
'sidebar' : {
'component' : this . sidebar
} ,
'content' : {
'component' : this . content
} ,
'tools' : {
'component' : BDV2 . react . createElement ( V2Components . Tools , { key : "pt" , ref : "tools" , onClick : this . close } )
}
} ;
}
get sidebar ( ) {
return BDV2 . react . createElement (
"div" ,
{ className : "sidebar" , key : "ps" } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-tab-bar SIDE" } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-tab-bar-header" , style : { fontSize : "16px" } } ,
"Public Servers"
) ,
BDV2 . react . createElement ( V2Components . TabBar . Separator , null ) ,
this . searchInput ,
BDV2 . react . createElement ( V2Components . TabBar . Separator , null ) ,
BDV2 . react . createElement ( V2Components . TabBar . Header , { text : "Categories" } ) ,
this . categoryButtons . map ( ( value , index ) => {
return BDV2 . react . createElement ( V2Components . TabBar . Item , { id : index , onClick : this . changeCategory , key : index , text : value , selected : this . state . selectedCategory === index } ) ;
} ) ,
BDV2 . react . createElement ( V2Components . TabBar . Separator , null ) ,
this . footer
)
) ;
}
get searchInput ( ) {
return BDV2 . react . createElement (
"div" ,
{ className : "ui-form-item" } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-text-input flex-vertical" , style : { width : "172px" , marginLeft : "10px" } } ,
BDV2 . react . createElement ( "input" , { ref : "searchinput" , onKeyDown : this . searchKeyDown , onChange : ( ) => { } , type : "text" , className : "input default" , placeholder : "Search..." , maxLength : "50" } )
)
) ;
}
searchKeyDown ( e ) {
let self = this ;
if ( self . state . loading || e . which !== 13 ) return ;
self . setState ( {
'loading' : true ,
'title' : 'Loading...' ,
'term' : e . target . value
} ) ;
let query = ` ?term= ${ e . target . value } ` ;
if ( self . state . selectedCategory !== 0 ) {
query += ` &category= ${ self . categoryButtons [ self . state . selectedCategory ] } ` ;
}
self . search ( query , true ) ;
}
get categoryButtons ( ) {
return [ "All" , "FPS Games" , "MMO Games" , "Strategy Games" , "Sports Games" , "Puzzle Games" , "Retro Games" , "Party Games" , "Tabletop Games" , "Sandbox Games" , "Simulation Games" , "Community" , "Language" , "Programming" , "Other" ] ;
}
changeCategory ( id ) {
let self = this ;
if ( self . state . loading ) return ;
self . refs . searchinput . value = "" ;
self . setState ( {
'loading' : true ,
'selectedCategory' : id ,
'title' : 'Loading...' ,
'term' : null
} ) ;
if ( id === 0 ) {
self . search ( "" , true ) ;
return ;
}
self . search ( ` ?category= ${ self . categoryButtons [ id ] } ` , true ) ;
}
get content ( ) {
let self = this ;
let guildList = Object . keys ( this . GuildStore . getGuilds ( ) ) ;
let defaultList = this . AvatarDefaults . DEFAULT _AVATARS ;
if ( self . state . connection . state === 1 ) return self . notConnected ;
return [ BDV2 . react . createElement (
"div" ,
{ ref : "content" , key : "pc" , className : "content-column default" } ,
BDV2 . react . createElement ( V2Components . SettingsTitle , { text : self . state . title } ) ,
self . bdServer ,
self . state . servers . map ( ( server , index ) => {
return BDV2 . react . createElement ( V2Components . ServerCard , { key : index , server : server , join : self . join , guildList : guildList , fallback : defaultList [ Math . floor ( Math . random ( ) * 5 ) ] } ) ;
} ) ,
self . state . next && BDV2 . react . createElement (
"button" ,
{ type : "button" , onClick : ( ) => {
if ( self . state . loading ) return ; self . setState ( { 'loading' : true } ) ; self . search ( self . state . next , false ) ;
} , className : "ui-button filled brand small grow" , style : { width : "100%" , marginTop : "10px" , marginBottom : "10px" } } ,
BDV2 . react . createElement (
"div" ,
{ className : "ui-button-contents" } ,
self . state . loading ? 'Loading' : 'Load More'
)
) ,
self . state . servers . length > 0 && BDV2 . react . createElement ( V2Components . SettingsTitle , { text : self . state . title } )
) ] ;
}
get footer ( ) {
return BDV2 . react . createElement (
"div" ,
{ className : "ui-tab-bar-header" } ,
BDV2 . react . createElement (
"a" ,
{ href : "https://discordservers.com" , target : "_blank" } ,
"Discordservers.com"
)
) ;
}
}