33 * @author programmer2514
44 * @authorId 563652755814875146
55 * @description A feature-rich BetterDiscord plugin that reworks the Discord UI to be significantly more modular
6- * @version 12.3.2
6+ * @version 12.3.3
77 * @donate https://ko-fi.com/benjaminpryor
88 * @patreon https://www.patreon.com/BenjaminPryor
99 * @website https://github.com/programmer2514/BetterDiscord-CollapsibleUI
@@ -155,14 +155,17 @@ const settings = {
155155const config = {
156156 changelog : [
157157 {
158- title : '12.3.2 ' ,
158+ title : '12.3.3 ' ,
159159 type : 'added' ,
160160 items : [
161- 'Fixed profile panel visual glitches on resize' ,
161+ 'Fixed plugin crash on Discord startup' ,
162+ 'Fixed profile panel styling issue' ,
163+ 'Fixed inconsistent toolbar injection' ,
164+ 'Minor performance improvements' ,
162165 ] ,
163166 } ,
164167 {
165- title : '1.0.0 - 12.3.1 ' ,
168+ title : '1.0.0 - 12.3.2 ' ,
166169 type : 'added' ,
167170 items : [
168171 'See the full changelog here: https://programmer2514.github.io/?l=cui-changelog' ,
@@ -1146,11 +1149,10 @@ const modules = {
11461149 get channels ( ) { return this . _channels ?? ( this . _channels = runtime . api . Webpack . getByKeys ( 'channel' , 'closeIcon' , 'dm' ) ) ; } ,
11471150 get activity ( ) { return this . _activity ?? ( this . _activity = runtime . api . Webpack . getByKeys ( 'itemCard' , 'emptyCard' , 'emptyText' ) ) ; } ,
11481151 get game ( ) { return this . _game ?? ( this . _game = runtime . api . Webpack . getByKeys ( 'openOnHover' , 'userSection' , 'thumbnail' ) ) ; } ,
1149- get callIcons ( ) { return this . _callIcons ?? ( this . _callIcons = runtime . api . Webpack . getByKeys ( 'button' , 'speaker' , 'last' , 'lastButton' ) ) ; } ,
11501152 get callButtons ( ) { return this . _callButtons ?? ( this . _callButtons = runtime . api . Webpack . getByKeys ( 'controlButton' , 'wrapper' , 'buttonContainer' ) ) ; } ,
1151- get userAreaButtons ( ) { return this . _userAreaButtons ?? ( this . _userAreaButtons = runtime . api . Webpack . getByKeys ( 'actionButtons ' , 'micTestButton ' , 'buttonIcon' ) ) ; } ,
1153+ get userAreaButtons ( ) { return this . _userAreaButtons ?? ( this . _userAreaButtons = runtime . api . Webpack . getByKeys ( 'krispLogo ' , 'actionButtons ' , 'buttonIcon' ) ) ; } ,
11521154 get scroller ( ) { return this . _scroller ?? ( this . _scroller = runtime . api . Webpack . getByKeys ( 'wrapper' , 'scroller' , 'discoveryIcon' ) ) ; } ,
1153- get profileWrappers ( ) { return this . _profileWrappers ?? ( this . _profileWrappers = runtime . api . Webpack . getByKeys ( 'header' , 'footerButton' , 'widgetBreadcrumb ' , 'wishlistBreadcrumb' ) ) ; } ,
1155+ get profileWrappers ( ) { return this . _profileWrappers ?? ( this . _profileWrappers = runtime . api . Webpack . getByKeys ( 'header' , 'footerButton' , 'backdrop ' , 'wishlistBreadcrumb' ) ) ; } ,
11541156} ;
11551157
11561158const elements = {
@@ -1203,7 +1205,8 @@ const runtime = {
12031205 toolbar : null ,
12041206 dragging : null ,
12051207 interval : null ,
1206- threadsLoaded : false ,
1208+ loaded : Object . fromEntries ( Object . keys ( modules ) . filter ( key => ! key . startsWith ( '_' ) ) . map ( key => [ key , false ] ) ) ,
1209+ allModulesLoaded : false ,
12071210 collapsed : [ false , false , false , false , false , false , false , false , false , false , false ] ,
12081211 keys : new Set ( ) ,
12091212 lastKeypress : Date . now ( ) ,
@@ -1217,46 +1220,53 @@ const runtime = {
12171220 // Scans for changes that require a toolbar/style reload
12181221 get observer ( ) {
12191222 return this . _observer ?? ( this . _observer = new MutationObserver ( ( mutationList ) => {
1220- mutationList . forEach ( ( mutation ) => {
1221- mutation . addedNodes . forEach ( ( node ) => {
1222- if ( node . classList ?. contains ( modules . panel ?. outer )
1223+ for ( let mutation of mutationList ) {
1224+ for ( let node of mutation . addedNodes ) {
1225+ if ( ( node . nodeName === 'ASIDE' )
12231226 || node . classList ?. contains ( modules . search ?. searchResultsWrap )
1224- || node . classList ?. contains ( modules . popout ?. chatLayerWrapper ) ) {
1227+ || node . classList ?. contains ( modules . popout ?. chatLayerWrapper )
1228+ || node . classList ?. contains ( modules . calls ?. wrapper ) ) {
12251229 this . plugin . partialReload ( ) ;
1230+ return ;
12261231 }
12271232
12281233 if ( runtime . api . Plugins . isEnabled ( 'BetterAnimations' ) ) {
1229- node . classList ?. forEach ( ( className ) => {
1234+ for ( let className of node . classList ?? [ ] ) {
12301235 if ( className . startsWith ( 'BA__' ) ) {
12311236 this . plugin . partialReload ( ) ;
1237+ return ;
12321238 }
1233- } ) ;
1239+ }
12341240 }
1235- } ) ;
1236- mutation . removedNodes . forEach ( ( node ) => {
1237- if ( node . classList ?. contains ( modules . panel ?. outer )
1241+ }
1242+ for ( let node of mutation . removedNodes ) {
1243+ if ( ( node . nodeName === 'ASIDE' )
12381244 || node . classList ?. contains ( modules . search ?. searchResultsWrap )
1239- || node . classList ?. contains ( modules . popout ?. chatLayerWrapper ) ) {
1245+ || node . classList ?. contains ( modules . popout ?. chatLayerWrapper )
1246+ || node . classList ?. contains ( modules . calls ?. wrapper ) ) {
12401247 this . plugin . partialReload ( ) ;
1248+ return ;
12411249 }
12421250
12431251 if ( runtime . api . Plugins . isEnabled ( 'BetterAnimations' ) ) {
1244- node . classList ?. forEach ( ( className ) => {
1252+ for ( let className of node . classList ?? [ ] ) {
12451253 if ( className . startsWith ( 'BA__' ) ) {
12461254 this . plugin . partialReload ( ) ;
1255+ return ;
12471256 }
1248- } ) ;
1257+ }
12491258 }
1250- } ) ;
1259+ }
12511260
12521261 if ( runtime . api . Plugins . isEnabled ( 'BetterAnimations' ) ) {
1253- mutation . target . classList . forEach ( ( className ) => {
1262+ for ( let className of mutation . target . classList ) {
12541263 if ( className . startsWith ( 'BA__' ) ) {
12551264 this . plugin . partialReload ( ) ;
1265+ return ;
12561266 }
1257- } ) ;
1267+ }
12581268 }
1259- } ) ;
1269+ }
12601270 } ) ) ;
12611271 } ,
12621272} ;
@@ -2128,12 +2138,6 @@ const styles = {
21282138 border-radius: 0 !important;
21292139 }
21302140
2131- .${ modules . callIcons ?. button } ,
2132- .${ modules . callIcons ?. lastButton } {
2133- margin-left: 8px !important;
2134- margin-right: 8px !important;
2135- }
2136-
21372141 div:has(> .${ modules . callButtons ?. wrapper } ) {
21382142 flex-shrink: 0 !important;
21392143 max-width: 100% !important;
@@ -2521,7 +2525,7 @@ const styles = {
25212525 }
25222526
25232527 // Init button group styles
2524- this . buttons . forEach ( group => group . init ( ) ) ;
2528+ for ( let group of this . buttons ) group . init ( ) ;
25252529
25262530 // Init dynamic styles
25272531 this . update ( ) ;
@@ -2550,13 +2554,13 @@ const styles = {
25502554
25512555 // Remove and re-add some element styles
25522556 reinit : function ( ) {
2553- this . collapse . forEach ( ( panel ) => {
2557+ for ( let panel of this . collapse ) {
25542558 if ( panel . _clear ) {
25552559 panel . clear ( ) ;
25562560 panel . init ( ) ;
25572561 if ( ! settings . buttonsActive [ panel . _index ] ) panel . toggle ( ) ;
25582562 }
2559- } ) ;
2563+ }
25602564 } ,
25612565
25622566 // Remove all added element styles
@@ -2566,10 +2570,10 @@ const styles = {
25662570 runtime . api . DOM . removeStyle ( `${ runtime . meta . name } -vars` ) ;
25672571
25682572 // Clear panel styles
2569- this . collapse . forEach ( panel => panel . clear ( ) ) ;
2573+ for ( let panel of this . collapse ) panel . clear ( ) ;
25702574
25712575 // Clear button group styles
2572- this . buttons . forEach ( group => group . clear ( ) ) ;
2576+ for ( let group of this . buttons ) group . clear ( ) ;
25732577 } ,
25742578} ;
25752579
@@ -2773,7 +2777,7 @@ module.exports = class CollapsibleUI {
27732777 // Terminate the plugin
27742778 terminate = ( ) => {
27752779 styles . clear ( ) ;
2776- runtime . toolbar . remove ( ) ;
2780+ runtime . toolbar ? .remove ( ) ;
27772781 } ;
27782782
27792783 // Reload the plugin
@@ -2785,7 +2789,7 @@ module.exports = class CollapsibleUI {
27852789 // Reload the toolbar after a short delay
27862790 reloadToolbar = ( ) => {
27872791 setTimeout ( ( ) => {
2788- runtime . toolbar . remove ( ) ;
2792+ runtime . toolbar ? .remove ( ) ;
27892793 this . createToolbarContainer ( ) ;
27902794 } , 250 ) ;
27912795 } ;
@@ -2806,25 +2810,27 @@ module.exports = class CollapsibleUI {
28062810 // Insert the toolbar container into the correct spot
28072811 try {
28082812 if ( elements . inviteToolbar || elements . searchBar ) {
2809- elements . toolbar . insertBefore ( toolbar , ( elements . inviteToolbar )
2810- ? elements . inviteToolbar . nextElementSibling
2813+ elements . toolbar ? .insertBefore ( toolbar , ( elements . inviteToolbar )
2814+ ? elements . inviteToolbar ? .nextElementSibling
28112815 : elements . searchBar ) ;
28122816 }
28132817 else
2814- elements . toolbar . insertBefore ( toolbar , elements . toolbar . childNodes [ elements . toolbar . childNodes . length - 2 ] ) ;
2818+ elements . toolbar ? .insertBefore ( toolbar , elements . toolbar ? .childNodes [ elements . toolbar ? .childNodes . length - 2 ] ) ;
28152819 }
28162820 catch ( e ) {
2817- elements . toolbar . appendChild ( toolbar ) ;
2821+ elements . toolbar ? .appendChild ( toolbar ) ;
28182822 }
28192823
28202824 // Get toolbar container reference
28212825 runtime . toolbar = document . querySelector ( '.cui-toolbar' ) ;
28222826
28232827 // Insert toolbar buttons
2824- for ( var i = 1 ; i <= settings . buttonIndexes . length ; i ++ ) {
2825- for ( var j = 0 ; j < settings . buttonIndexes . length ; j ++ ) {
2826- if ( i === settings . buttonIndexes [ j ] && elements . index [ j ] )
2827- this . createToolbarButton ( j ) ;
2828+ if ( runtime . toolbar ) {
2829+ for ( var i = 1 ; i <= settings . buttonIndexes . length ; i ++ ) {
2830+ for ( var j = 0 ; j < settings . buttonIndexes . length ; j ++ ) {
2831+ if ( i === settings . buttonIndexes [ j ] && elements . index [ j ] )
2832+ this . createToolbarButton ( j ) ;
2833+ }
28282834 }
28292835 }
28302836 } ;
@@ -2861,7 +2867,7 @@ module.exports = class CollapsibleUI {
28612867 // Toggles the button at the specified index
28622868 toggleButton = ( index ) => {
28632869 styles . collapse [ index ] . toggle ( ) ;
2864- runtime . toolbar . querySelector ( `#cui-icon-${ index } ` ) ?. classList . toggle ( modules . icons ?. selected ) ;
2870+ runtime . toolbar ? .querySelector ( `#cui-icon-${ index } ` ) ?. classList . toggle ( modules . icons ?. selected ) ;
28652871 this . updateSettingsArray ( 'buttonsActive' , index , ! settings . buttonsActive [ index ] ) ;
28662872 } ;
28672873
@@ -2890,7 +2896,7 @@ module.exports = class CollapsibleUI {
28902896 if ( e . target . classList . contains ( modules . popout ?. chatLayerWrapper ) ) {
28912897 elements . chatWrapper ?. style . setProperty ( '--transition' , 'none' ) ;
28922898 elements . noChat ?. style . setProperty ( '--transition' , 'none' ) ;
2893- e . target . childNodes . forEach ( e => e . style . setProperty ( 'transition' , 'none' ) ) ;
2899+ for ( let e of e . target . childNodes ) e . style . setProperty ( 'transition' , 'none' ) ;
28942900 }
28952901 }
28962902 } , { passive : true , signal : runtime . controller . signal } ) ;
@@ -2999,7 +3005,7 @@ module.exports = class CollapsibleUI {
29993005 elements . chatWrapper ?. style . removeProperty ( '--width' ) ;
30003006 elements . noChat ?. style . removeProperty ( '--width' ) ;
30013007 target . style . removeProperty ( '--uirr-forum-panel-width' ) ;
3002- target . childNodes . forEach ( e => e . style . removeProperty ( 'transition' ) ) ;
3008+ for ( let e of target . childNodes ) e . style . removeProperty ( 'transition' ) ;
30033009 // Timeout to avoid transition flash
30043010 setTimeout ( ( ) => {
30053011 elements . chatWrapper ?. style . removeProperty ( '--transition' ) ;
@@ -3093,10 +3099,16 @@ module.exports = class CollapsibleUI {
30933099 // Add intervals to periodically check for changes
30943100 addIntervals = ( ) => {
30953101 runtime . interval = setInterval ( ( ) => {
3096- // Wait for lazy-loaded threads module
3097- if ( ( ! runtime . threadsLoaded ) && modules . threads ) {
3098- runtime . threadsLoaded = true ;
3099- runtime . api . Logger . info ( 'Loaded threads module' ) ;
3102+ // Wait for lazy-loaded modules and load them as they become available
3103+ let modulesLoaded = [ ] ;
3104+ for ( const module of Object . keys ( runtime . loaded ) ) {
3105+ if ( ! runtime . loaded [ module ] && modules [ module ] ) {
3106+ runtime . loaded [ module ] = true ;
3107+ modulesLoaded . push ( module ) ;
3108+ }
3109+ }
3110+ if ( modulesLoaded . length > 0 ) {
3111+ runtime . api . Logger . info ( `Loaded new module${ modulesLoaded . length > 1 ? 's' : '' } : ${ modulesLoaded . join ( ', ' ) } ` ) ;
31003112 this . reload ( ) ;
31013113 }
31023114
0 commit comments