2020-10-20 23:25:34 +02:00
/ * *
* @ name SpotifyControls
* @ authorId 278543574059057154
* @ invite Jx3TjNS
* @ donate https : //www.paypal.me/MircoWittrien
* @ patreon https : //www.patreon.com/MircoWittrien
* @ website https : //github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/SpotifyControls
* @ source https : //raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/SpotifyControls/SpotifyControls.plugin.js
2020-11-12 17:30:48 +01:00
* @ updateUrl https : //raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/SpotifyControls/SpotifyControls.plugin.js
2020-10-20 23:25:34 +02:00
* /
2020-07-19 16:59:08 +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" : "SpotifyControls" ,
"author" : "DevilBro" ,
"version" : "1.0.8" ,
2020-10-16 10:25:30 +02:00
"description" : "Add a control panel to discord when listening to spotify"
2020-07-19 16:59:08 +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-01-14 16:14:44 +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 } ` ; }
2020-09-19 20:49:33 +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 ;
require ( "request" ) . get ( "https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js" , ( e , r , b ) => {
2020-10-20 23:25:34 +02:00
if ( ! e && b && b . indexOf ( ` * @name BDFDB ` ) > - 1 ) require ( "fs" ) . writeFile ( require ( "path" ) . join ( BdApi . Plugins . folder , "0BDFDB.plugin.js" ) , b , _ => { } ) ;
2021-01-14 16:14:44 +01:00
else BdApi . alert ( "Error" , "Could not download BDFDB Library Plugin, try again later or download it manually from GitHub: https://github.com/mwittrien/BetterDiscordAddons/tree/master/Library/" ) ;
2020-09-20 08:15:13 +02:00
} ) ;
}
2020-07-23 21:51:49 +02:00
} ) ;
2020-07-19 17:21:45 +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> ` ;
2020-11-28 23:12:09 +01:00
template . content . firstElementChild . querySelector ( "a" ) . addEventListener ( "click" , _ => {
require ( "request" ) . get ( "https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js" , ( e , r , b ) => {
if ( ! e && b && b . indexOf ( ` * @name BDFDB ` ) > - 1 ) require ( "fs" ) . writeFile ( require ( "path" ) . join ( BdApi . Plugins . folder , "0BDFDB.plugin.js" ) , b , _ => { } ) ;
2021-01-14 16:14:44 +01:00
else BdApi . alert ( "Error" , "Could not download BDFDB Library Plugin, try again later or download it manually from GitHub: https://github.com/mwittrien/BetterDiscordAddons/tree/master/Library/" ) ;
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 _this ;
var insertPatchCancel ;
var controls , starting , lastSong , currentVolume , lastVolume , stopTime , previousIsClicked , previousDoubleTimeout , timelineTimeout , timelineDragging , updateInterval ;
var playbackState = { } ;
var settings = { } , buttonConfigs = { } ;
const repeatStates = [
"off" ,
"context" ,
"track"
] ;
const SpotifyControlsComponent = class SpotifyControls extends BdApi . React . Component {
2021-01-20 16:00:29 +01:00
componentDidMount ( ) {
2020-09-19 20:49:33 +02:00
controls = this ;
}
request ( socket , device , type , data ) {
return new Promise ( callback => {
let method = "PUT" ;
switch ( type ) {
case "next" :
case "previous" :
method = "POST" ;
break ;
case "get" :
type = "" ;
method = "GET" ;
break ;
} ;
BDFDB . LibraryRequires . request ( {
url : ` https://api.spotify.com/v1/me/player ${ type ? "/" + type : "" } ${ Object . entries ( Object . assign ( { } , data)).map(n => ` ? $ { n [ 0 ] } = $ { n [ 1 ] } ` ).join("")} ` ,
method : method ,
headers : {
authorization : ` Bearer ${ socket . accessToken } `
}
} , ( error , response , result ) => {
2020-11-16 10:06:21 +01:00
if ( response && response . statusCode == 401 ) {
2020-09-19 20:49:33 +02:00
BDFDB . LibraryModules . SpotifyUtils . getAccessToken ( socket . accountId ) . then ( promiseResult => {
let newSocketDevice = BDFDB . LibraryModules . SpotifyTrackUtils . getActiveSocketAndDevice ( ) ;
this . request ( newSocketDevice . socket , newSocketDevice . device , type , data ) . then ( _ => {
try { callback ( JSON . parse ( result ) ) ; }
catch ( err ) { callback ( { } ) ; }
} ) ;
} ) ;
}
else {
try { callback ( JSON . parse ( result ) ) ; }
catch ( err ) { callback ( { } ) ; }
}
} ) ;
} ) ;
2020-07-23 16:12:08 +02:00
}
2021-01-20 16:00:29 +01:00
render ( ) {
2020-09-19 20:49:33 +02:00
let socketDevice = BDFDB . LibraryModules . SpotifyTrackUtils . getActiveSocketAndDevice ( ) ;
if ( ! socketDevice ) return null ;
if ( this . props . song ) {
playbackState . is _playing = true ;
let fetchState = ! BDFDB . equals ( this . props . song , lastSong ) ;
lastSong = this . props . song ;
stopTime = null ;
if ( fetchState ) this . request ( socketDevice . socket , socketDevice . device , "get" ) . then ( response => {
playbackState = Object . assign ( { } , response ) ;
BDFDB . ReactUtils . forceUpdate ( this ) ;
} ) ;
}
else if ( ! stopTime && lastSong ) {
playbackState . is _playing = false ;
stopTime = new Date ( ) ;
}
if ( ! lastSong ) return null ;
currentVolume = socketDevice . device . volume _percent ;
let playerSize = this . props . maximized ? "big" : "small" ;
return BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . _spotifycontrolscontainer , this . props . maximized && BDFDB . disCN . _spotifycontrolscontainermaximized , this . props . timeline && BDFDB . disCN . _spotifycontrolscontainerwithtimeline ) ,
children : [
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolscontainerinner ,
children : [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Clickable , {
className : BDFDB . disCN . _spotifycontrolscoverwrapper ,
onClick : _ => {
this . props . maximized = ! this . props . maximized ;
BDFDB . DataUtils . save ( this . props . maximized , _this , "playerState" , "maximized" ) ;
if ( this . props . maximized ) this . request ( socketDevice . socket , socketDevice . device , "get" ) . then ( response => {
playbackState = Object . assign ( { } , response ) ;
BDFDB . ReactUtils . forceUpdate ( this ) ;
} ) ;
else BDFDB . ReactUtils . forceUpdate ( this ) ;
} ,
2020-07-19 16:59:08 +02:00
children : [
2020-09-19 20:49:33 +02:00
BDFDB . ReactUtils . createElement ( "img" , {
className : BDFDB . disCN . _spotifycontrolscover ,
src : BDFDB . LibraryModules . AssetUtils . getAssetImage ( lastSong . application _id , lastSong . assets . large _image )
2020-07-23 20:53:46 +02:00
} ) ,
2020-09-19 20:49:33 +02:00
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SvgIcon , {
className : BDFDB . disCN . _spotifycontrolscovermaximizer ,
name : BDFDB . LibraryComponents . SvgIcon . Names . LEFT _CARET
} )
]
} ) ,
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolsdetails ,
children : [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
className : BDFDB . disCN . _spotifycontrolssong ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextScroller , {
children : lastSong . details
} )
2020-07-23 16:12:08 +02:00
} ) ,
2020-09-19 20:49:33 +02:00
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
className : BDFDB . disCNS . subtext + BDFDB . disCN . _spotifycontrolsinterpret ,
color : BDFDB . LibraryComponents . TextElement . Colors . CUSTOM ,
size : BDFDB . LibraryComponents . TextElement . Sizes . SIZE _12 ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextScroller , {
children : BDFDB . LanguageUtils . LanguageStringsFormat ( "USER_ACTIVITY_LISTENING_ARTISTS" , lastSong . state )
} )
} )
]
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TooltipContainer , {
text : socketDevice . device . is _restricted ? "Can not control Spotify while playing on restricted device" : null ,
tooltipConfig : { color : "red" } ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex , {
grow : 0 ,
children : [
BDFDB . ReactUtils . createElement ( SpotifyControlsButtonComponent , {
type : "share" ,
playerSize : playerSize ,
style : this . props . maximized ? { marginRight : 4 } : { } ,
onClick : _ => {
let url = BDFDB . ObjectUtils . get ( playbackState , "item.external_urls.spotify" ) || BDFDB . ObjectUtils . get ( playbackState , "context.external_urls.spotify" ) ;
if ( url ) {
2020-11-19 16:51:14 +01:00
BDFDB . LibraryRequires . electron . clipboard . write ( { text : url } ) ;
2020-09-19 20:49:33 +02:00
BDFDB . NotificationUtils . toast ( "Song URL was copied to clipboard" , { type : "success" } ) ;
}
else BDFDB . NotificationUtils . toast ( "Could not copy song URL to clipboard" , { type : "error" } ) ;
2020-07-23 16:12:08 +02:00
}
2020-09-19 20:49:33 +02:00
} ) ,
BDFDB . ReactUtils . createElement ( SpotifyControlsButtonComponent , {
type : "shuffle" ,
playerSize : playerSize ,
active : playbackState . shuffle _state ,
disabled : socketDevice . device . is _restricted ,
onClick : _ => {
playbackState . shuffle _state = ! playbackState . shuffle _state ;
this . request ( socketDevice . socket , socketDevice . device , "shuffle" , {
state : playbackState . shuffle _state
} ) ;
BDFDB . ReactUtils . forceUpdate ( this ) ;
2020-07-23 16:12:08 +02:00
}
2020-09-19 20:49:33 +02:00
} ) ,
BDFDB . ReactUtils . createElement ( SpotifyControlsButtonComponent , {
type : "previous" ,
playerSize : playerSize ,
disabled : socketDevice . device . is _restricted ,
onClick : _ => {
if ( previousIsClicked ) {
previousIsClicked = false ;
this . request ( socketDevice . socket , socketDevice . device , "previous" ) ;
}
else {
previousIsClicked = true ;
previousDoubleTimeout = BDFDB . TimeUtils . timeout ( _ => {
previousIsClicked = false ;
this . request ( socketDevice . socket , socketDevice . device , "seek" , {
position _ms : 0
} ) ;
} , 300 ) ;
}
2020-07-23 16:12:08 +02:00
}
2020-09-19 20:49:33 +02:00
} ) ,
BDFDB . ReactUtils . createElement ( SpotifyControlsButtonComponent , {
type : "pauseplay" ,
playerSize : playerSize ,
icon : this . props . song ? 0 : 1 ,
disabled : socketDevice . device . is _restricted ,
onClick : _ => {
if ( this . props . song ) {
playbackState . is _playing = false ;
this . request ( socketDevice . socket , socketDevice . device , "pause" ) ;
}
else {
playbackState . is _playing = true ;
this . request ( socketDevice . socket , socketDevice . device , "play" ) ;
}
2020-07-23 16:12:08 +02:00
}
2020-09-19 20:49:33 +02:00
} ) ,
BDFDB . ReactUtils . createElement ( SpotifyControlsButtonComponent , {
type : "next" ,
playerSize : playerSize ,
disabled : socketDevice . device . is _restricted ,
onClick : _ => {
this . request ( socketDevice . socket , socketDevice . device , "next" ) ;
2020-07-23 16:12:08 +02:00
}
2020-09-19 20:49:33 +02:00
} ) ,
BDFDB . ReactUtils . createElement ( SpotifyControlsButtonComponent , {
type : "repeat" ,
playerSize : playerSize ,
icon : playbackState . repeat _state != repeatStates [ 2 ] ? 0 : 1 ,
active : playbackState . repeat _state != repeatStates [ 0 ] ,
disabled : socketDevice . device . is _restricted ,
onClick : _ => {
playbackState . repeat _state = repeatStates [ repeatStates . indexOf ( playbackState . repeat _state ) + 1 ] || repeatStates [ 0 ] ;
this . request ( socketDevice . socket , socketDevice . device , "repeat" , {
state : playbackState . repeat _state
2020-08-31 16:38:37 +02:00
} ) ;
2020-09-19 20:49:33 +02:00
BDFDB . ReactUtils . forceUpdate ( this ) ;
2020-08-31 16:38:37 +02:00
}
2020-09-19 20:49:33 +02:00
} ) ,
BDFDB . ReactUtils . createElement ( SpotifyControlsButtonComponent , {
type : "volume" ,
playerSize : playerSize ,
icon : Math . ceil ( currentVolume / 34 ) ,
disabled : socketDevice . device . is _restricted ,
style : this . props . maximized ? { marginLeft : 4 } : { } ,
onContextMenu : _ => {
if ( currentVolume == 0 ) {
if ( lastVolume ) this . request ( socketDevice . socket , socketDevice . device , "volume" , {
volume _percent : lastVolume
} ) ;
}
else {
lastVolume = currentVolume ;
2020-07-23 20:23:23 +02:00
this . request ( socketDevice . socket , socketDevice . device , "volume" , {
2020-09-19 20:49:33 +02:00
volume _percent : 0
2020-07-23 20:23:23 +02:00
} ) ;
}
2020-09-19 20:49:33 +02:00
} ,
renderPopout : instance => {
return BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Slider , {
className : BDFDB . disCN . _spotifycontrolsvolumeslider ,
defaultValue : currentVolume ,
digits : 0 ,
barStyles : { height : 6 , top : 3 } ,
fillStyles : { backgroundColor : BDFDB . DiscordConstants . Colors . SPOTIFY } ,
onValueRender : value => {
return value + "%" ;
} ,
onValueChange : value => {
currentVolume = value ;
this . request ( socketDevice . socket , socketDevice . device , "volume" , {
volume _percent : currentVolume
} ) ;
}
} ) ;
}
} )
] . filter ( n => n )
} )
2020-07-19 16:59:08 +02:00
} )
2020-09-19 20:49:33 +02:00
]
} ) ,
this . props . timeline && BDFDB . ReactUtils . createElement ( SpotifyControlsTimelineComponent , {
song : lastSong ,
socket : socketDevice . socket ,
device : socketDevice . device ,
controls : this
} )
] . filter ( n => n )
} ) ;
}
} ;
const SpotifyControlsButtonComponent = class SpotifyControlsButton extends BdApi . React . Component {
2021-01-20 16:00:29 +01:00
render ( ) {
2020-09-19 20:49:33 +02:00
if ( ! this . props . playerSize || ! buttonConfigs [ this . props . type ] || ! buttonConfigs [ this . props . type ] [ this . props . playerSize ] ) return null ;
let button = BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Button , BDFDB . ObjectUtils . exclude ( Object . assign ( { } , this . props , {
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . accountinfobutton , this . props . disabled ? BDFDB . disCN . accountinfobuttondisabled : BDFDB . disCN . accountinfobuttonenabled , this . props . active && BDFDB . disCN . _spotifycontrolsbuttonactive ) ,
look : BDFDB . LibraryComponents . Button . Looks . BLANK ,
size : BDFDB . LibraryComponents . Button . Sizes . NONE ,
children : _this . defaults . buttonConfigs [ this . props . type ] && _this . defaults . buttonConfigs [ this . props . type ] . icons ? ( _this . defaults . buttonConfigs [ this . props . type ] . icons [ this . props . icon ] || _this . defaults . buttonConfigs [ this . props . type ] . icons [ 0 ] ) : "?" ,
onClick : this . props . disabled ? _ => { } : this . props . onClick ,
onContextMenu : this . props . disabled ? _ => { } : this . props . onContextMenu ,
} ) , "active" , "disabled" , "renderPopout" , "icon" , "type" , "playerSize" ) ) ;
return ! this . props . disabled && typeof this . props . renderPopout == "function" ? BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . PopoutContainer , {
children : button ,
animation : BDFDB . LibraryComponents . PopoutContainer . Animation . SCALE ,
position : BDFDB . LibraryComponents . PopoutContainer . Positions . TOP ,
align : BDFDB . LibraryComponents . PopoutContainer . Align . CENTER ,
arrow : true ,
shadow : true ,
renderPopout : this . props . renderPopout
} ) : button ;
}
} ;
const SpotifyControlsTimelineComponent = class SpotifyControlsTimeline extends BdApi . React . Component {
2021-01-20 16:00:29 +01:00
componentDidMount ( ) {
2020-09-19 20:49:33 +02:00
BDFDB . TimeUtils . clear ( updateInterval ) ;
updateInterval = BDFDB . TimeUtils . interval ( _ => {
if ( ! this . updater || typeof this . updater . isMounted != "function" || ! this . updater . isMounted ( this ) ) BDFDB . TimeUtils . clear ( updateInterval ) ;
else if ( playbackState . is _playing ) {
let song = BDFDB . LibraryModules . SpotifyTrackUtils . getActivity ( false ) ;
if ( ! song ) BDFDB . ReactUtils . forceUpdate ( controls ) ;
else if ( playbackState . is _playing ) BDFDB . ReactUtils . forceUpdate ( this ) ;
}
} , 1000 ) ;
}
formatTime ( time ) {
let seconds = Math . floor ( ( time / 1000 ) % 60 ) ;
let minutes = Math . floor ( ( time / ( 1000 * 60 ) ) % 60 ) ;
let hours = Math . floor ( ( time / ( 1000 * 60 * 60 ) ) % 24 ) ;
return ` ${ hours > 0 ? hours + ":" : "" } ${ hours > 0 && minutes < 10 ? "0" + minutes : minutes } : ${ seconds < 10 ? "0" + seconds : seconds } `
}
2021-01-20 16:00:29 +01:00
render ( ) {
2020-09-19 20:49:33 +02:00
let maxTime = this . props . song . timestamps . end - this . props . song . timestamps . start ;
let currentTime = ( ! playbackState . is _playing && stopTime ? stopTime : new Date ( ) ) - this . props . song . timestamps . start ;
currentTime = currentTime > maxTime ? maxTime : currentTime ;
return BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolstimeline ,
children : [
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolsbar ,
children : [
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolsbarfill ,
style : { width : ` ${ currentTime / maxTime * 100 } % ` }
} ) ,
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolsbargrabber ,
style : { left : ` ${ currentTime / maxTime * 100 } % ` }
} )
] ,
onClick : event => {
let rects = BDFDB . DOMUtils . getRects ( BDFDB . DOMUtils . getParent ( BDFDB . dotCN . _spotifycontrolsbar , event . target ) ) ;
this . props . controls . request ( this . props . socket , this . props . device , "seek" , {
position _ms : Math . round ( BDFDB . NumberUtils . mapRange ( [ rects . left , rects . left + rects . width ] , [ 0 , maxTime ] , event . clientX ) )
} ) ;
}
} ) ,
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolsbartext ,
children : [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
className : BDFDB . disCN . height12 ,
size : BDFDB . LibraryComponents . TextElement . Sizes . SIZE _12 ,
children : this . formatTime ( currentTime )
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
className : BDFDB . disCN . height12 ,
size : BDFDB . LibraryComponents . TextElement . Sizes . SIZE _12 ,
children : this . formatTime ( maxTime )
} )
]
} )
]
} ) ;
}
} ;
2020-07-19 16:59:08 +02:00
2020-10-09 21:09:35 +02:00
return class SpotifyControls extends Plugin {
2021-01-06 12:38:36 +01:00
onLoad ( ) {
2020-09-19 20:49:33 +02:00
_this = this ;
this . defaults = {
settings : {
2020-11-19 16:51:14 +01:00
addTimeline : { value : true , description : "Show the song timeline in the controls" }
2020-09-19 20:49:33 +02:00
} ,
buttonConfigs : {
2020-11-19 16:51:14 +01:00
share : { value : { small : false , big : true } , icons : [ "" ] , description : "Share" } ,
shuffle : { value : { small : false , big : true } , icons : [ "" ] , description : "Shuffle" } ,
previous : { value : { small : true , big : true } , icons : [ "" ] , description : "Previous" } ,
pauseplay : { value : { small : true , big : true } , icons : [ "" , "" ] , description : "Pause/Play" } ,
next : { value : { small : true , big : true } , icons : [ "" ] , description : "Next" } ,
repeat : { value : { small : false , big : true } , icons : [ "" , "" ] , description : "Repeat" } ,
volume : { value : { small : false , big : true } , icons : [ "" , "" , "" , "" ] , description : "Volume" }
2020-09-19 20:49:33 +02:00
}
} ;
this . patchedModules = {
before : {
AppView : "render"
}
} ;
this . css = `
@ font - face {
font - family : glue1 - spoticon ;
src : url ( "https://mwittrien.github.io/BetterDiscordAddons/Plugins/SpotifyControls/_res/spoticon.ttf" ) format ( "truetype" ) ;
font - weight : 400 ;
font - style : normal
}
$ { BDFDB . dotCN . _spotifycontrolscontainer } {
display : flex ;
flex - direction : column ;
justify - content : center ;
min - height : 52 px ;
margin - bottom : 1 px ;
border - bottom : 1 px solid var ( -- background - modifier - accent ) ;
padding : 0 8 px ;
box - sizing : border - box ;
}
$ { BDFDB . dotCN . _spotifycontrolscontainer + BDFDB . dotCN . _spotifycontrolscontainerwithtimeline } {
padding - top : 8 px ;
}
$ { BDFDB . dotCN . _spotifycontrolscontainerinner } {
display : flex ;
align - items : center ;
font - size : 14 px ;
width : 100 % ;
}
$ { BDFDB . dotCN . _spotifycontrolstimeline } {
margin : 6 px 0 4 px 0 ;
}
$ { BDFDB . dotCN . _spotifycontrolsbar } {
position : relative ;
border - radius : 2 px ;
background - color : rgba ( 79 , 84 , 92 , 0.16 ) ;
height : 4 px ;
margin - bottom : 4 px ;
}
$ { BDFDB . dotCN . _spotifycontrolsbarfill } {
border - radius : 2 px ;
height : 100 % ;
min - width : 4 px ;
border - radius : 2 px ;
background : var ( -- text - normal ) ;
}
$ { BDFDB . dotCN . _spotifycontrolstimeline } : hover $ { BDFDB . dotCN . _spotifycontrolsbarfill } {
background : $ { BDFDB . DiscordConstants . Colors . SPOTIFY } ;
}
$ { BDFDB . dotCN . _spotifycontrolsbargrabber } {
display : none ;
position : absolute ;
top : 0 ;
left : 0 ;
width : 8 px ;
height : 8 px ;
margin - top : - 2 px ;
margin - left : - 2 px ;
background : var ( -- text - normal ) ;
border - radius : 50 % ;
}
$ { BDFDB . dotCN . _spotifycontrolstimeline } : hover $ { BDFDB . dotCN . _spotifycontrolsbargrabber } {
display : block ;
}
$ { BDFDB . dotCN . _spotifycontrolsbartext } {
display : flex ;
align - items : center ;
justify - content : space - between ;
}
$ { BDFDB . dotCN . _spotifycontrolscoverwrapper } {
position : relative ;
width : 32 px ;
min - width : 32 px ;
height : 32 px ;
min - height : 32 px ;
margin - right : 8 px ;
border - radius : 4 px ;
overflow : hidden ;
transition : width . 3 s ease , height . 3 s ease ;
}
$ { BDFDB . dotCN . _spotifycontrolscover } {
display : block ;
width : 100 % ;
height : 100 % ;
object - fit : cover ;
}
$ { BDFDB . dotCN . _spotifycontrolscovermaximizer } {
visibility : hidden ;
position : absolute ;
background - color : rgba ( 0 , 0 , 0 , 0.5 ) ;
color : rgba ( 255 , 255 , 255 , 0.5 ) ;
top : 0 ;
right : 0 ;
border - radius : 50 % ;
width : 12 px ;
height : 12 px ;
padding : 3 px ;
transform : rotate ( 90 deg ) ;
transition : width . 3 s ease , height . 3 s ease , transform . 3 s ease ;
pointer - events : none ;
}
$ { BDFDB . dotCN . _spotifycontrolscoverwrapper } : hover $ { BDFDB . dotCN . _spotifycontrolscovermaximizer } {
visibility : visible ;
}
$ { BDFDB . dotCN . _spotifycontrolsdetails } {
user - select : text ;
flex - grow : 1 ;
margin - right : 4 px ;
min - width : 0 ;
}
$ { BDFDB . dotCN . _spotifycontrolssong } {
font - weight : 500 ;
}
$ { BDFDB . dotCN . _spotifycontrolsinterpret } {
font - weight : 300 ;
}
$ { BDFDB . dotCN . _spotifycontrolsvolumeslider } {
height : 12 px ;
width : 140 px ;
margin : 5 px ;
}
$ { BDFDB . dotCNS . _spotifycontrolsvolumeslider + BDFDB . dotCN . slidergrabber } {
height : 10 px ;
margin - top : - 6 px ;
border - radius : 50 % ;
}
$ { BDFDB . dotCNS . _spotifycontrolscontainer + BDFDB . dotCN . accountinfobuttondisabled } {
cursor : no - drop ;
}
$ { BDFDB . dotCNS . _spotifycontrolscontainer + BDFDB . dotCNS . accountinfobutton + BDFDB . dotCN . buttoncontents } {
font - family : glue1 - spoticon ! important ;
}
$ { BDFDB . dotCNS . _spotifycontrolscontainer + BDFDB . dotCN . accountinfobutton + BDFDB . dotCN . _spotifycontrolsbuttonactive } {
color : $ { BDFDB . DiscordConstants . Colors . SPOTIFY } ;
}
$ { BDFDB . dotCN . _spotifycontrolscontainer + BDFDB . dotCN . _spotifycontrolscontainermaximized } {
padding - top : 0 ;
}
$ { BDFDB . dotCN . _spotifycontrolscontainer + BDFDB . dotCNS . _spotifycontrolscontainermaximized + BDFDB . dotCN . _spotifycontrolscontainerinner } {
flex - direction : column ;
}
$ { BDFDB . dotCN . _spotifycontrolscontainer + BDFDB . dotCNS . _spotifycontrolscontainermaximized + BDFDB . dotCN . _spotifycontrolsdetails } {
margin : 0 0 4 px 0 ;
width : 100 % ;
text - align : center ;
}
$ { BDFDB . dotCN . _spotifycontrolscontainer + BDFDB . dotCNS . _spotifycontrolscontainermaximized + BDFDB . dotCN . _spotifycontrolscoverwrapper } {
width : calc ( 100 % + 16 px ) ;
height : 100 % ;
margin : 0 0 8 px 0 ;
border - radius : 0 ;
}
$ { BDFDB . dotCN . _spotifycontrolscontainer + BDFDB . dotCNS . _spotifycontrolscontainermaximized + BDFDB . dotCN . _spotifycontrolscovermaximizer } {
top : 4 px ;
right : 4 px ;
width : 22 px ;
height : 22 px ;
padding : 5 px ;
transform : rotate ( - 90 deg ) ;
}
$ { BDFDB . dotCN . _spotifycontrolssettingsicon } {
margin : 4 px ;
font - size : 16 px ;
font - family : glue1 - spoticon ! important ;
}
$ { BDFDB . dotCN . _spotifycontrolssettingslabel } {
margin - left : 10 px ;
}
` ;
2020-07-19 16:59:08 +02:00
}
2020-09-19 20:49:33 +02:00
2021-01-06 12:38:36 +01:00
onStart ( ) {
2020-09-11 19:31:36 +02:00
BDFDB . PatchUtils . patch ( this , BDFDB . LibraryModules . SpotifyTrackUtils , "getActivity" , { after : e => {
2020-07-21 15:12:43 +02:00
if ( e . methodArguments [ 0 ] !== false ) {
if ( e . returnValue && e . returnValue . name == "Spotify" ) this . updatePlayer ( e . returnValue ) ;
else if ( ! e . returnValue ) this . updatePlayer ( null ) ;
}
2020-07-19 16:59:08 +02:00
} } ) ;
2020-09-11 19:31:36 +02:00
BDFDB . PatchUtils . patch ( this , BDFDB . LibraryModules . SpotifyTrackUtils , "wasAutoPaused" , { instead : e => {
2020-07-19 16:59:08 +02:00
return false ;
} } ) ;
2020-09-11 19:31:36 +02:00
BDFDB . PatchUtils . patch ( this , BDFDB . LibraryModules . SpotifyUtils , "pause" , { instead : e => {
2020-07-19 16:59:08 +02:00
return false ;
} } ) ;
2020-07-26 19:05:14 +02:00
if ( ! BDFDB . LibraryModules . SpotifyTrackUtils . hasConnectedAccount ( ) ) BDFDB . ModalUtils . open ( this , {
size : "SMALL" ,
header : this . name + ": Something is missing..." ,
subheader : "You need to connect a Spotify account" ,
text : "You are missing a connected Spotify account, without a connected account you won't be able to use Spotify Controls. To connect a Spotify account with your discord account click the button below." ,
buttons : [ {
contents : BDFDB . LanguageUtils . LanguageStrings . CONNECT ,
color : "BRAND" ,
close : true ,
click : modal => {
BDFDB . LibraryModules . UserSettingsUtils . open ( BDFDB . DiscordConstants . UserSettingsSections . CONNECTIONS )
}
} ]
} ) ;
2020-07-21 15:08:40 +02:00
this . forceUpdateAll ( ) ;
2020-07-19 16:59:08 +02:00
}
2020-09-19 20:49:33 +02:00
2021-01-06 12:38:36 +01:00
onStop ( ) {
2020-07-21 15:08:40 +02:00
this . forceUpdateAll ( ) ;
2020-08-15 20:27:43 +02:00
if ( typeof insertPatchCancel == "function" ) insertPatchCancel ( ) ;
2020-09-19 20:49:33 +02:00
}
2020-07-19 16:59:08 +02:00
2020-09-19 20:49:33 +02:00
getSettingsPanel ( collapseStates = { } ) {
let settingsPanel , settingsItems = [ ] ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : "Settings" ,
collapseStates : collapseStates ,
children : Object . keys ( settings ) . map ( key => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
type : "Switch" ,
plugin : this ,
keys : [ "settings" , key ] ,
label : this . defaults . settings [ key ] . description ,
value : settings [ key ]
} ) )
} ) ) ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : "Button Settings" ,
collapseStates : collapseStates ,
children : [ BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . FormComponents . FormTitle , {
className : BDFDB . disCN . marginbottom4 ,
tag : BDFDB . LibraryComponents . FormComponents . FormTitle . Tags . H3 ,
2020-11-19 16:51:14 +01:00
children : "Add control buttons in small and/or big player version: "
2020-09-19 20:49:33 +02:00
} ) ] . concat ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsList , {
settings : Object . keys ( this . defaults . buttonConfigs [ Object . keys ( this . defaults . buttonConfigs ) [ 0 ] ] . value ) ,
data : Object . keys ( buttonConfigs ) . map ( key => Object . assign ( { } , buttonConfigs [ key ] , {
key : key ,
label : this . defaults . buttonConfigs [ key ] . description ,
icons : this . defaults . buttonConfigs [ key ] . icons
} ) ) ,
noRemove : true ,
renderLabel : data => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex , {
align : BDFDB . LibraryComponents . Flex . Align . CENTER ,
children : [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex , {
justify : BDFDB . LibraryComponents . Flex . Justify . CENTER ,
wrap : BDFDB . LibraryComponents . Flex . Wrap . WRAP ,
basis : 50 ,
grow : 0 ,
children : data . icons . map ( icon => BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolssettingsicon ,
children : icon
} ) )
} ) ,
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolssettingslabel ,
children : data . label
} )
]
} ) ,
onCheckboxChange : ( value , instance ) => {
buttonConfigs [ instance . props . cardId ] [ instance . props . settingId ] = value ;
BDFDB . DataUtils . save ( buttonConfigs , this , "buttonConfigs" ) ;
this . SettingsUpdated = true ;
}
} ) )
} ) ) ;
return settingsPanel = BDFDB . PluginUtils . createSettingsPanel ( this , settingsItems ) ;
2020-07-19 16:59:08 +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 ( ) ;
}
}
2020-07-19 16:59:08 +02:00
2021-01-06 12:38:36 +01:00
forceUpdateAll ( ) {
2020-09-19 20:49:33 +02:00
settings = BDFDB . DataUtils . get ( this , "settings" ) ;
buttonConfigs = BDFDB . DataUtils . get ( this , "buttonConfigs" ) ;
BDFDB . PatchUtils . forceAllUpdates ( this ) ;
2020-07-21 15:08:40 +02:00
}
2020-09-19 20:49:33 +02:00
processAppView ( e ) {
if ( typeof insertPatchCancel == "function" ) insertPatchCancel ( ) ;
insertPatchCancel = BDFDB . PatchUtils . patch ( this , e . instance , "renderChannelSidebar" , { after : e2 => {
let [ children , index ] = BDFDB . ReactUtils . findParent ( e2 . returnValue , { props : [ [ "section" , BDFDB . DiscordConstants . AnalyticsSections . ACCOUNT _PANEL ] ] } ) ;
if ( index > - 1 ) children . splice ( index - 1 , 0 , BDFDB . ReactUtils . createElement ( SpotifyControlsComponent , {
song : BDFDB . LibraryModules . SpotifyTrackUtils . getActivity ( false ) ,
maximized : BDFDB . DataUtils . load ( this , "playerState" , "maximized" ) ,
timeline : settings . addTimeline
} , true ) ) ;
} } , { force : true , noCache : true } ) ;
2020-07-19 16:59:08 +02:00
}
2020-07-21 15:08:40 +02:00
2020-09-19 20:49:33 +02:00
updatePlayer ( song ) {
if ( controls ) {
controls . props . song = song ;
BDFDB . ReactUtils . forceUpdate ( controls ) ;
}
}
} ;
2020-10-09 21:09:35 +02:00
} ) ( window . BDFDB _Global . PluginUtils . buildPlugin ( config ) ) ;
2020-09-19 20:49:33 +02:00
} ) ( ) ;