2020-10-20 23:25:34 +02:00
/ * *
* @ name BetterFriendList
2021-03-05 13:26:41 +01:00
* @ author DevilBro
2020-10-20 23:25:34 +02:00
* @ authorId 278543574059057154
2021-03-05 13:26:41 +01:00
* @ version 1.3 . 2
* @ description Adds extra Controls to the Friends Page , for example sort by Name / Status , Search and All / Request / Blocked Amount
2020-10-20 23:25:34 +02:00
* @ invite Jx3TjNS
2020-11-19 16:45:36 +01:00
* @ donate https : //www.paypal.me/MircoWittrien
* @ patreon https : //www.patreon.com/MircoWittrien
2021-03-09 15:10:55 +01:00
* @ website https : //mwittrien.github.io/
* @ source https : //github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/BetterFriendList/
2021-03-10 09:17:37 +01:00
* @ updateUrl https : //mwittrien.github.io/BetterDiscordAddons/Plugins/BetterFriendList/BetterFriendList.plugin.js
2020-10-20 23:25:34 +02:00
* /
2020-08-26 12:10:17 +02:00
2020-09-19 20:49:33 +02:00
module . exports = ( _ => {
2020-10-09 21:09:35 +02:00
const config = {
2020-09-19 20:49:33 +02:00
"info" : {
"name" : "BetterFriendList" ,
"author" : "DevilBro" ,
2020-11-27 17:53:50 +01:00
"version" : "1.3.2" ,
2021-03-04 11:31:05 +01:00
"description" : "Adds extra Controls to the Friends Page, for example sort by Name/Status, Search and All/Request/Blocked Amount"
2020-11-16 09:51:45 +01:00
} ,
"changeLog" : {
"fixed" : {
2020-11-27 17:53:50 +01:00
"Mutual Guilds" : "Visible again"
2020-11-16 09:51:45 +01:00
}
2020-08-26 20:07:49 +02:00
}
2020-09-19 20:49:33 +02:00
} ;
2020-11-13 19:47:44 +01:00
2020-10-09 21:09:35 +02:00
return ! window . BDFDB _Global || ( ! window . BDFDB _Global . loaded && ! window . BDFDB _Global . started ) ? class {
2021-01-06 12:38:36 +01:00
getName ( ) { return config . info . name ; }
getAuthor ( ) { return config . info . author ; }
getVersion ( ) { return config . info . version ; }
2021-02-01 17:13:13 +01:00
getDescription ( ) { return ` The Library Plugin needed for ${ config . info . name } is missing. Open the Plugin Settings to download it. \n \n ${ config . info . description } ` ; }
downloadLibrary ( ) {
require ( "request" ) . get ( "https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js" , ( e , r , b ) => {
2021-03-05 13:14:18 +01:00
if ( ! e && b && r . statusCode == 200 ) require ( "fs" ) . writeFile ( require ( "path" ) . join ( BdApi . Plugins . folder , "0BDFDB.plugin.js" ) , b , _ => BdApi . showToast ( "Finished downloading BDFDB Library" , { type : "success" } ) ) ;
2021-03-06 14:59:48 +01:00
else BdApi . alert ( "Error" , "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library" ) ;
2021-02-01 17:13:13 +01:00
} ) ;
}
2020-08-26 20:07:49 +02:00
2021-01-06 12:38:36 +01:00
load ( ) {
2020-11-19 16:51:14 +01:00
if ( ! window . BDFDB _Global || ! Array . isArray ( window . BDFDB _Global . pluginQueue ) ) window . BDFDB _Global = Object . assign ( { } , window . BDFDB _Global , { pluginQueue : [ ] } ) ;
2020-09-19 20:49:33 +02:00
if ( ! window . BDFDB _Global . downloadModal ) {
window . BDFDB _Global . downloadModal = true ;
2021-01-14 16:14:44 +01:00
BdApi . showConfirmationModal ( "Library Missing" , ` The Library Plugin needed for ${ config . info . name } is missing. Please click "Download Now" to install it. ` , {
2020-09-19 20:49:33 +02:00
confirmText : "Download Now" ,
cancelText : "Cancel" ,
onCancel : _ => { delete window . BDFDB _Global . downloadModal ; } ,
2020-09-20 08:15:13 +02:00
onConfirm : _ => {
delete window . BDFDB _Global . downloadModal ;
2021-02-01 17:13:13 +01:00
this . downloadLibrary ( ) ;
2020-09-20 08:15:13 +02:00
}
2020-09-19 20:49:33 +02:00
} ) ;
2020-08-26 12:10:17 +02:00
}
2020-09-19 20:49:33 +02:00
if ( ! window . BDFDB _Global . pluginQueue . includes ( config . info . name ) ) window . BDFDB _Global . pluginQueue . push ( config . info . name ) ;
2020-10-09 21:09:35 +02:00
}
2021-01-06 12:38:36 +01:00
start ( ) { this . load ( ) ; }
stop ( ) { }
getSettingsPanel ( ) {
2020-11-28 23:12:09 +01:00
let template = document . createElement ( "template" ) ;
2021-01-14 16:14:44 +01:00
template . innerHTML = ` <div style="color: var(--header-primary); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${ config . info . name } is missing. \n Please click <a style="font-weight: 500;">Download Now</a> to install it.</div> ` ;
2021-02-01 17:13:13 +01:00
template . content . firstElementChild . querySelector ( "a" ) . addEventListener ( "click" , this . downloadLibrary ) ;
2020-11-28 23:12:09 +01:00
return template . content . firstElementChild ;
}
2020-10-09 21:09:35 +02:00
} : ( ( [ Plugin , BDFDB ] ) => {
2020-09-19 20:49:33 +02:00
var rerenderTimeout , sortKey , sortReversed , searchQuery , searchTimeout ;
var settings = { } ;
const placeHolderId = "PLACEHOLDER_BETTERFRIENDLIST" ;
const statusSortOrder = {
online : 0 ,
streaming : 1 ,
idle : 2 ,
dnd : 3 ,
offline : 4 ,
invisible : 5 ,
unknown : 6
} ;
2020-10-09 21:09:35 +02:00
return class BetterFriendList extends Plugin {
2021-01-06 12:38:36 +01:00
onLoad ( ) {
2020-09-19 20:49:33 +02:00
this . defaults = {
settings : {
2020-11-19 16:51:14 +01:00
addTotalAmount : { value : true , description : "Add total amount for all/requested/blocked" } ,
addSortOptions : { value : true , description : "Add sort options" } ,
addSearchbar : { value : true , description : "Add searchbar" } ,
addMutualGuild : { value : true , description : "Add mutual servers in friend list" }
2020-09-19 20:49:33 +02:00
}
} ;
2020-08-26 12:10:17 +02:00
2020-09-19 20:49:33 +02:00
this . patchedModules = {
before : {
PeopleListSectionedLazy : "default" ,
2020-10-25 18:15:18 +01:00
PeopleListSectionedNonLazy : "default"
2020-09-19 20:49:33 +02:00
} ,
after : {
TabBar : "render" ,
PeopleListSectionedLazy : "default" ,
2020-10-25 18:15:18 +01:00
PeopleListSectionedNonLazy : "default" ,
2020-09-19 20:49:33 +02:00
FriendRow : "render" ,
PendingRow : "default" ,
BlockedRow : "render" ,
PeopleListItem : [ "render" , "componentDidMount" , "componentWillUnmount" ]
}
} ;
this . css = `
$ { BDFDB . dotCN . peoplewrapper } > * {
justify - content : unset ;
}
$ { BDFDB . dotCNS . peoplewrapper + BDFDB . dotCN . userinfo } {
flex : 1 1 auto ;
}
$ { BDFDB . dotCN . _betterfriendlistmutualguilds } {
margin - left : 13 px ;
width : 200 px ;
}
$ { BDFDB . dotCN . _betterfriendlisttitle } {
width : 200 px ;
}
$ { BDFDB . dotCN . _betterfriendlistnamecell } {
width : 150 px ;
}
` ;
}
2021-01-06 12:38:36 +01:00
onStart ( ) {
2020-09-19 20:49:33 +02:00
sortKey = null ;
sortReversed = false ;
searchQuery = "" ;
2020-08-26 12:10:17 +02:00
2020-08-26 15:21:49 +02:00
this . forceUpdateAll ( ) ;
2020-08-26 12:10:17 +02:00
}
2020-09-19 20:49:33 +02:00
2021-01-06 12:38:36 +01:00
onStop ( ) {
2020-08-26 15:21:49 +02:00
this . forceUpdateAll ( ) ;
2020-08-26 12:10:17 +02:00
}
2020-09-19 20:49:33 +02:00
getSettingsPanel ( collapseStates = { } ) {
let settingsPanel , settingsItems = [ ] ;
for ( let key in settings ) settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
type : "Switch" ,
plugin : this ,
keys : [ "settings" , key ] ,
label : this . defaults . settings [ key ] . description ,
value : settings [ key ]
} ) ) ;
return settingsPanel = BDFDB . PluginUtils . createSettingsPanel ( this , settingsItems ) ;
}
2020-08-26 12:10:17 +02:00
2021-01-06 12:38:36 +01:00
onSettingsClosed ( ) {
2020-09-19 20:49:33 +02:00
if ( this . SettingsUpdated ) {
delete this . SettingsUpdated ;
this . forceUpdateAll ( ) ;
}
}
2021-01-06 12:38:36 +01:00
forceUpdateAll ( ) {
2020-09-19 20:49:33 +02:00
settings = BDFDB . DataUtils . get ( this , "settings" ) ;
2020-08-26 12:10:17 +02:00
2020-09-19 20:49:33 +02:00
BDFDB . PatchUtils . forceAllUpdates ( this ) ;
this . rerenderList ( ) ;
2020-08-26 15:21:49 +02:00
}
2020-09-19 20:49:33 +02:00
processTabBar ( e ) {
if ( settings . addTotalAmount && e . returnvalue . props . children ) for ( let checkChild of e . returnvalue . props . children ) if ( checkChild && checkChild . props . id == "ADD_FRIEND" ) {
2021-03-15 13:52:24 +01:00
let relationships = BDFDB . LibraryModules . RelationshipStore . getRelationships ( ) , relationshipCount = { } ;
2020-09-19 20:49:33 +02:00
for ( let type in BDFDB . DiscordConstants . RelationshipTypes ) relationshipCount [ type ] = 0 ;
for ( let id in relationships ) relationshipCount [ relationships [ id ] ] ++ ;
for ( let child of e . returnvalue . props . children ) if ( child && child . props . id != "ADD_FRIEND" ) {
let newChildren = [ child . props . children ] . flat ( ) . filter ( child => BDFDB . ObjectUtils . get ( child , "type.displayName" ) != "NumberBadge" ) ;
switch ( child . props . id ) {
case "ALL" :
newChildren . push ( this . createBadge ( relationshipCount [ BDFDB . DiscordConstants . RelationshipTypes . FRIEND ] ) ) ;
break ;
case "ONLINE" :
newChildren . push ( this . createBadge ( BDFDB . LibraryModules . StatusMetaUtils . getOnlineFriendCount ( ) ) ) ;
break ;
case "PENDING" :
2021-03-01 10:37:57 +01:00
newChildren . push ( this . createBadge ( relationshipCount [ BDFDB . DiscordConstants . RelationshipTypes . PENDING _INCOMING ] , this . labels . incoming ) ) ;
newChildren . push ( this . createBadge ( relationshipCount [ BDFDB . DiscordConstants . RelationshipTypes . PENDING _OUTGOING ] , this . labels . outgoing ) ) ;
2020-09-19 20:49:33 +02:00
break ;
case "BLOCKED" :
newChildren . push ( this . createBadge ( relationshipCount [ BDFDB . DiscordConstants . RelationshipTypes . BLOCKED ] ) ) ;
break ;
}
child . props . children = newChildren ;
2020-08-26 12:10:17 +02:00
}
2020-09-19 20:49:33 +02:00
break ;
2020-08-26 12:10:17 +02:00
}
}
2020-09-19 20:49:33 +02:00
processPeopleListSectionedLazy ( e ) {
if ( sortKey || searchQuery ) {
e . instance . props . statusSections = [ ] . concat ( e . instance . props . statusSections ) . map ( section => {
let newSection = [ ] . concat ( section ) ;
if ( searchQuery ) {
let usedSearchQuery = searchQuery . toLowerCase ( ) ;
newSection = newSection . filter ( user => user && typeof user . usernameLower == "string" && user . usernameLower . indexOf ( usedSearchQuery ) > - 1 ) ;
}
if ( sortKey ) {
newSection = BDFDB . ArrayUtils . keySort ( newSection . map ( user => Object . assign ( { } , user , { statusIndex : statusSortOrder [ user . status ] } ) ) , sortKey ) ;
if ( sortReversed ) newSection . reverse ( ) ;
}
if ( ! newSection . length ) {
let placeholder = new BDFDB . DiscordObjects . User ( {
id : placeHolderId ,
username : placeHolderId
} ) ;
if ( placeholder ) newSection . push ( new BDFDB . DiscordObjects . Relationship ( {
activities : [ ] ,
applicationStream : null ,
isMobile : false ,
key : placeHolderId ,
mutualGuilds : [ ] ,
mutualGuildsLength : 0 ,
status : "offline" ,
type : BDFDB . DiscordConstants . RelationshipTypes . NONE ,
user : placeholder ,
usernameLower : placeholder . usernameNormalized
} ) ) ;
}
return newSection ;
} ) ;
}
2020-11-16 09:51:45 +01:00
if ( ! BDFDB . PatchUtils . isPatched ( this , e . instance . props , "getSectionTitle" ) ) BDFDB . PatchUtils . patch ( this , e . instance . props , "getSectionTitle" , { after : e2 => {
if ( typeof e2 . returnValue == "string" ) {
let users = e . instance . props . statusSections . flat ( 10 ) ;
return BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex , {
align : BDFDB . LibraryComponents . Flex . Align . CENTER ,
children : [
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _betterfriendlisttitle ,
children : e2 . returnValue . replace ( users . length , users . filter ( u => u && u . key != placeHolderId ) . length )
2020-09-19 20:49:33 +02:00
} ) ,
2020-11-16 09:51:45 +01:00
settings . addSortOptions && [
{ key : "usernameLower" , label : BDFDB . LanguageUtils . LanguageStrings . FRIENDS _COLUMN _NAME } ,
{ key : "statusIndex" , label : BDFDB . LanguageUtils . LanguageStrings . FRIENDS _COLUMN _STATUS }
] . filter ( n => n ) . map ( data => BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . tableheadercellwrapper , BDFDB . disCN . tableheadercell , BDFDB . disCN . _betterfriendlistnamecell , sortKey == data . key && BDFDB . disCN . tableheadercellsorted , BDFDB . disCN . tableheadercellclickable ) ,
children : BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . tableheadercellcontent ,
children : [
data . label ,
sortKey == data . key && BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SvgIcon , {
className : BDFDB . disCN . tableheadersorticon ,
name : BDFDB . LibraryComponents . SvgIcon . Names [ sortReversed ? "ARROW_UP" : "ARROW_DOWN" ]
} )
] . filter ( n => n )
} ) ,
onClick : event => {
if ( sortKey == data . key ) {
if ( ! sortReversed ) sortReversed = true ;
else {
sortKey = null ;
sortReversed = false ;
}
}
2020-09-19 20:49:33 +02:00
else {
2020-11-16 09:51:45 +01:00
sortKey = data . key ;
2020-09-19 20:49:33 +02:00
sortReversed = false ;
}
this . rerenderList ( ) ;
}
2020-11-16 09:51:45 +01:00
} ) ) ,
settings . addSearchbar && BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex . Child , {
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SearchBar , {
query : searchQuery ,
onChange : value => {
BDFDB . TimeUtils . clear ( searchTimeout ) ;
searchTimeout = BDFDB . TimeUtils . timeout ( _ => {
searchQuery = value ;
this . rerenderList ( ) ;
} , 1000 ) ;
} ,
onClear : _ => {
searchQuery = "" ;
this . rerenderList ( ) ;
}
} )
2020-09-19 20:49:33 +02:00
} )
2020-11-16 09:51:45 +01:00
] . flat ( 10 ) . filter ( n => n )
} ) ;
}
} } , { force : true , noCache : true } ) ;
2020-09-19 20:49:33 +02:00
}
2020-10-25 18:15:18 +01:00
processPeopleListSectionedNonLazy ( e ) {
this . processPeopleListSectionedLazy ( e ) ;
}
2020-09-19 20:49:33 +02:00
processFriendRow ( e ) {
e . returnvalue . props . mutualGuilds = e . instance . props . mutualGuilds ;
}
processPendingRow ( e ) {
this . processFriendRow ( e ) ;
}
processBlockedRow ( e ) {
this . processFriendRow ( e ) ;
2020-08-29 00:48:29 +02:00
}
2020-09-19 20:49:33 +02:00
processPeopleListItem ( e ) {
if ( e . node ) {
BDFDB . TimeUtils . clear ( rerenderTimeout ) ;
rerenderTimeout = BDFDB . TimeUtils . timeout ( _ => { BDFDB . PatchUtils . forceAllUpdates ( this , "TabBar" ) ; } , 1000 ) ;
}
else {
if ( e . instance . props . user . id == placeHolderId ) return null ;
else if ( settings . addMutualGuild && e . instance . props . mutualGuilds && e . instance . props . mutualGuilds . length ) {
2020-11-27 17:53:50 +01:00
if ( typeof e . returnvalue . props . children == "function" ) {
let childrenRender = e . returnvalue . props . children ;
e . returnvalue . props . children = ( ... args ) => {
let children = childrenRender ( ... args ) ;
this . injectMutualGuilds ( children , e . instance . props . mutualGuilds ) ;
return children ;
} ;
}
else this . injectMutualGuilds ( e . returnvalue , e . instance . props . mutualGuilds ) ;
2020-09-19 20:49:33 +02:00
}
2020-08-29 08:55:29 +02:00
}
2020-08-29 00:48:29 +02:00
}
2020-09-19 20:49:33 +02:00
2020-11-27 17:53:50 +01:00
injectMutualGuilds ( returnvalue , mutualGuilds ) {
let [ children , index ] = BDFDB . ReactUtils . findParent ( returnvalue , { name : "UserInfo" } ) ;
if ( index > - 1 ) children . splice ( index + 1 , 0 , BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . GuildSummaryItem , {
className : BDFDB . disCN . _betterfriendlistmutualguilds ,
guilds : mutualGuilds ,
showTooltip : true ,
max : 10
} , true ) ) ;
}
2021-03-01 10:37:57 +01:00
createBadge ( amount , text ) {
let badge = BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Badges . NumberBadge , {
2020-09-19 20:49:33 +02:00
className : BDFDB . disCN . peoplesbadge ,
count : amount ,
style : { marginLeft : 6 }
} ) ;
2021-03-01 10:37:57 +01:00
return text ? BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TooltipContainer , {
text : text ,
tooltipConfig : {
type : "bottom"
} ,
children : badge
} ) : badge ;
2020-09-19 20:49:33 +02:00
}
2021-01-06 12:38:36 +01:00
rerenderList ( ) {
2020-09-19 20:49:33 +02:00
let selectedButton = document . querySelector ( BDFDB . dotCNS . peoplestabbar + BDFDB . dotCN . settingsitemselected ) ;
if ( selectedButton ) selectedButton . click ( ) ;
}
2021-03-01 10:37:57 +01:00
setLabelsByLanguage ( ) {
switch ( BDFDB . LanguageUtils . getLanguage ( ) . id ) {
case "bg" : // Bulgarian
return {
incoming : "Входящи" ,
outgoing : "Изходящи"
} ;
case "da" : // Danish
return {
incoming : "Indgående" ,
outgoing : "Udgående"
} ;
case "de" : // German
return {
incoming : "Eingehend" ,
outgoing : "Ausgehend"
} ;
case "el" : // Greek
return {
incoming : "Εισερχόμενος" ,
outgoing : "Εξερχόμενος"
} ;
case "es" : // Spanish
return {
incoming : "Entrante" ,
outgoing : "Saliente"
} ;
case "fi" : // Finnish
return {
incoming : "Saapuva" ,
outgoing : "Lähtevä"
} ;
case "fr" : // French
return {
incoming : "Entrant" ,
outgoing : "Sortant"
} ;
case "hr" : // Croatian
return {
incoming : "Dolazni" ,
outgoing : "Odlazni"
} ;
case "hu" : // Hungarian
return {
incoming : "Beérkező" ,
outgoing : "Kimenő"
} ;
case "it" : // Italian
return {
incoming : "In arrivo" ,
outgoing : "Estroverso"
} ;
case "ja" : // Japanese
return {
incoming : "着信" ,
outgoing : "発信"
} ;
case "ko" : // Korean
return {
incoming : "들어오는" ,
outgoing : "나가는"
} ;
case "lt" : // Lithuanian
return {
incoming : "Gaunamasis" ,
outgoing : "Išeinantis"
} ;
case "nl" : // Dutch
return {
incoming : "Inkomend" ,
outgoing : "Uitgaand"
} ;
case "no" : // Norwegian
return {
incoming : "Innkommende" ,
outgoing : "Utgående"
} ;
case "pl" : // Polish
return {
incoming : "Przychodzący" ,
outgoing : "Towarzyski"
} ;
case "pt-BR" : // Portuguese (Brazil)
return {
incoming : "Entrada" ,
outgoing : "Extrovertido"
} ;
case "ro" : // Romanian
return {
incoming : "Primite" ,
outgoing : "De ieșire"
} ;
case "ru" : // Russian
return {
incoming : "Входящий" ,
outgoing : "Исходящий"
} ;
case "sv" : // Swedish
return {
incoming : "Inkommande" ,
outgoing : "Utgående"
} ;
case "th" : // Thai
return {
incoming : "ขาเข้า" ,
outgoing : "ขาออก"
} ;
case "tr" : // Turkish
return {
incoming : "Gelen" ,
outgoing : "Dı şa dönük"
} ;
case "uk" : // Ukrainian
return {
incoming : "Вхідні" ,
outgoing : "Вихідний"
} ;
case "vi" : // Vietnamese
return {
incoming : "Mới đến" ,
outgoing : "Hướng ngoaị"
} ;
case "zh-CN" : // Chinese (China)
return {
incoming : "进来的" ,
outgoing : "外向"
} ;
case "zh-TW" : // Chinese (Taiwan)
return {
incoming : "傳入" ,
outgoing : "外向"
} ;
default : // English
return {
incoming : "Incoming" ,
outgoing : "Outgoing"
} ;
}
}
2020-09-19 20:49:33 +02:00
} ;
2020-10-09 21:09:35 +02:00
} ) ( window . BDFDB _Global . PluginUtils . buildPlugin ( config ) ) ;
2020-09-19 20:49:33 +02:00
} ) ( ) ;