2020-10-20 23:25:34 +02:00
/ * *
* @ name SpotifyControls
2021-03-05 13:26:41 +01:00
* @ author DevilBro
2020-10-20 23:25:34 +02:00
* @ authorId 278543574059057154
2021-05-18 19:50:28 +02:00
* @ version 1.1 . 6
2021-03-05 13:26:41 +01:00
* @ description Adds a Control Panel while listening to Spotify on a connected Account
2020-10-20 23:25:34 +02:00
* @ invite Jx3TjNS
* @ 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/SpotifyControls/
2021-03-10 09:17:37 +01:00
* @ updateUrl https : //mwittrien.github.io/BetterDiscordAddons/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" ,
2021-05-18 19:50:28 +02:00
"version" : "1.1.6" ,
2021-03-05 11:21:21 +01:00
"description" : "Adds a Control Panel while listening to Spotify on a connected Account"
2021-01-27 18:18:25 +01:00
} ,
"changeLog" : {
2021-05-12 11:16:22 +02:00
"improved" : {
2021-05-18 19:50:28 +02:00
"Activity Toggle" : "Added Activity Status Toggle Button"
2021-01-27 18:18:25 +01:00
}
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-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-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 ;
2021-02-01 17:13:13 +01:00
this . downloadLibrary ( ) ;
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> ` ;
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 _this ;
2021-05-03 21:22:44 +02:00
var controls ;
2021-05-18 19:50:28 +02:00
var starting , lastSong , showActivity , currentVolume , lastVolume , stopTime , previousIsClicked , previousDoubleTimeout ;
2021-05-03 21:22:44 +02:00
var timelineTimeout , timelineDragging , updateInterval ;
2020-09-19 20:49:33 +02:00
var playbackState = { } ;
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 ;
2021-05-18 19:50:28 +02:00
2020-09-19 20:49:33 +02:00
let playerSize = this . props . maximized ? "big" : "small" ;
2021-04-09 17:15:09 +02:00
let coverSrc = BDFDB . LibraryModules . AssetUtils . getAssetImage ( lastSong . application _id , lastSong . assets . large _image ) ;
2021-05-18 19:50:28 +02:00
let account = BDFDB . LibraryModules . ConnectionStore . getAccounts ( ) . find ( n => n . type == "spotify" ) ;
showActivity = showActivity != undefined ? showActivity : account . show _activity ;
currentVolume = this . props . draggingVolume ? currentVolume : socketDevice . device . volume _percent ;
2020-09-19 20:49:33 +02:00
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 : [
2021-04-09 17:15:09 +02:00
coverSrc ? BDFDB . ReactUtils . createElement ( "img" , {
2020-09-19 20:49:33 +02:00
className : BDFDB . disCN . _spotifycontrolscover ,
2021-04-09 17:15:09 +02:00
src : coverSrc
} ) : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SvgIcon , {
className : BDFDB . disCN . _spotifycontrolscover ,
width : "100%" ,
height : "100%" ,
name : BDFDB . LibraryComponents . SvgIcon . Names . QUESTIONMARK _ACTIVITY
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
2021-05-18 19:50:28 +02:00
} ) ,
this . props . maximized && this . props . activityToggle && BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TooltipContainer , {
text : _ => ` ${ BDFDB . LanguageUtils . LanguageStringsFormat ( "DISPLAY_ACTIVITY" , "Spotify" ) } ( ${ showActivity ? BDFDB . LanguageUtils . LanguageStrings . REPLY _MENTION _ON : BDFDB . LanguageUtils . LanguageStrings . REPLY _MENTION _OFF } ) ` ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SvgIcon , {
className : BDFDB . disCN . _spotifycontrolsactivitybutton ,
width : 20 ,
height : 20 ,
foreground : BDFDB . disCN . accountinfobuttonstrikethrough ,
name : showActivity ? BDFDB . LibraryComponents . SvgIcon . Names . ACTIVITY : BDFDB . LibraryComponents . SvgIcon . Names . ACTIVITY _DISABLED ,
onClick : event => {
BDFDB . ListenerUtils . stopEvent ( event ) ;
showActivity = ! showActivity ;
BDFDB . LibraryModules . ConnectionUtils . setShowActivity ( "spotify" , account . id , showActivity ) ;
}
} )
2020-09-19 20:49:33 +02:00
} )
]
} ) ,
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 , {
2021-01-23 21:47:04 +01:00
text : socketDevice . device . is _restricted ? _this . labels . restricted _device : null ,
2020-09-19 20:49:33 +02:00
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 } ) ;
2021-01-29 07:55:45 +01:00
BDFDB . NotificationUtils . toast ( _this . labels . toast _copyurl _success , { type : "success" } ) ;
2020-09-19 20:49:33 +02:00
}
2021-01-29 07:55:45 +01:00
else BDFDB . NotificationUtils . toast ( _this . labels . toast _copyurl _fail , { type : "danger" } ) ;
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 : _ => {
2021-05-03 21:22:44 +02:00
if ( previousIsClicked || ! _this . settings . general . doubleBack ) {
2020-09-19 20:49:33 +02:00
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 => {
2021-05-12 11:16:22 +02:00
let changeTimeout ;
2020-09-19 20:49:33 +02:00
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 => {
2021-05-12 11:16:22 +02:00
this . props . draggingVolume = true ;
currentVolume = value ;
BDFDB . TimeUtils . clear ( changeTimeout ) ;
changeTimeout = BDFDB . TimeUtils . timeout ( _ => this . props . draggingVolume && this . request ( socketDevice . socket , socketDevice . device , "volume" , {
volume _percent : currentVolume
} ) , 500 ) ;
2020-09-19 20:49:33 +02:00
return value + "%" ;
} ,
onValueChange : value => {
2021-05-12 11:16:22 +02:00
this . props . draggingVolume = false ;
2020-09-19 20:49:33 +02:00
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 ( ) {
2021-05-03 21:22:44 +02:00
if ( ! this . props . playerSize || ! _this . settings . buttons [ this . props . type ] || ! _this . settings . buttons [ this . props . type ] [ this . props . playerSize ] ) return null ;
2020-09-19 20:49:33 +02:00
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 ,
2021-05-03 21:22:44 +02:00
children : _this . defaults . buttons [ this . props . type ] && _this . defaults . buttons [ this . props . type ] . icons ? ( _this . defaults . buttons [ this . props . type ] . icons [ this . props . icon ] || _this . defaults . buttons [ this . props . type ] . icons [ 0 ] ) : "?" ,
2020-09-19 20:49:33 +02:00
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 = {
2021-05-03 21:22:44 +02:00
general : {
2021-05-18 19:50:28 +02:00
addTimeline : { value : true , description : "Shows the Song Timeline in the Controls" } ,
addActivityButton : { value : true , description : "Shows the Activity Status Toggle Button in the Controls" } ,
2021-01-27 18:18:25 +01:00
doubleBack : { value : true , description : "Requires the User to press the Back Button twice to go to previous Track" }
2020-09-19 20:49:33 +02:00
} ,
2021-05-03 21:22:44 +02:00
buttons : {
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 = {
2021-01-30 12:36:34 +01:00
after : {
AppView : "default"
2020-09-19 20:49:33 +02:00
}
} ;
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 ;
2021-05-17 12:57:34 +02:00
transition : border - radius . 3 s ease , margin . 3 s ease , width . 3 s ease , height . 3 s ease ;
2020-09-19 20:49:33 +02:00
}
$ { BDFDB . dotCN . _spotifycontrolscover } {
display : block ;
width : 100 % ;
height : 100 % ;
2021-05-03 21:22:44 +02:00
color : var ( -- header - primary ) ;
2020-09-19 20:49:33 +02:00
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 ;
}
2021-05-18 19:50:28 +02:00
$ { BDFDB . dotCN . _spotifycontrolsactivitybutton } {
visibility : hidden ;
position : absolute ;
background - color : rgba ( 0 , 0 , 0 , 0.5 ) ;
color : rgba ( 255 , 255 , 255 , 0.5 ) ;
border - radius : 50 % ;
bottom : 4 px ;
right : 4 px ;
width : 22 px ;
height : 22 px ;
padding : 5 px ;
}
$ { BDFDB . dotCN . _spotifycontrolsactivitybutton } : hover {
color : rgb ( 255 , 255 , 255 ) ;
}
$ { BDFDB . dotCN . _spotifycontrolscoverwrapper } : hover $ { BDFDB . dotCN . _spotifycontrolsactivitybutton } {
visibility : visible ;
}
2020-09-19 20:49:33 +02:00
$ { BDFDB . dotCN . _spotifycontrolsdetails } {
flex - grow : 1 ;
margin - right : 4 px ;
min - width : 0 ;
2021-05-18 19:50:28 +02:00
user - select : text ;
2020-09-19 20:49:33 +02:00
}
$ { 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 ;
}
2021-04-09 17:33:04 +02:00
$ { BDFDB . dotCNS . _bdminimalmode + BDFDB . dotCN . _spotifycontrolsbar } {
height : 3 px ;
}
$ { BDFDB . dotCNS . _bdminimalmode + BDFDB . dotCNS . _spotifycontrolscontainer + BDFDB . dotCN . accountinfobutton } {
width : 26 px ;
height : 26 px ;
}
$ { BDFDB . dotCNS . _bdminimalmode + BDFDB . dotCNS . _spotifycontrolscontainer + BDFDB . dotCN . size14 } {
font - size : 13 px ;
line - height : 13 px ;
}
$ { BDFDB . dotCNS . _bdminimalmode + BDFDB . dotCNS . _spotifycontrolscontainer + BDFDB . dotCN . size12 } {
font - size : 11 px ;
line - height : 11 px ;
}
2020-09-19 20:49:33 +02:00
` ;
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 ( ) {
2021-05-03 21:22:44 +02:00
// REMOVE 24.04.2021
let oldData = BDFDB . DataUtils . load ( this ) ;
if ( oldData . settings ) {
this . settings . general = oldData . settings ;
BDFDB . DataUtils . save ( this . settings . general , this , "general" ) ;
BDFDB . DataUtils . remove ( this , "settings" ) ;
}
if ( oldData . buttonConfigs ) {
this . settings . buttons = oldData . buttonConfigs ;
BDFDB . DataUtils . save ( this . settings . buttons , this , "buttons" ) ;
BDFDB . DataUtils . remove ( this , "buttonConfigs" ) ;
}
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-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-09-19 20:49:33 +02:00
}
2020-07-19 16:59:08 +02:00
2021-04-27 14:03:05 +02:00
getSettingsPanel ( collapseStates = { } ) {
let settingsPanel ;
return settingsPanel = BDFDB . PluginUtils . createSettingsPanel ( this , {
2020-09-19 20:49:33 +02:00
collapseStates : collapseStates ,
2021-04-27 14:03:05 +02:00
children : _ => {
let settingsItems = [ ] ;
if ( ! BDFDB . LibraryModules . SpotifyTrackUtils . hasConnectedAccount ( ) ) BDFDB . ModalUtils . open ( this , {
size : "SMALL" ,
header : ` ${ this . name } : ${ this . labels . noaccount _header } ... ` ,
subHeader : this . labels . noaccount _subheader ,
text : this . labels . noaccount _text ,
buttons : [ {
contents : BDFDB . LanguageUtils . LanguageStrings . CONNECT ,
color : "BRAND" ,
close : true ,
onClick : _ => BDFDB . LibraryModules . UserSettingsUtils . open ( BDFDB . DiscordConstants . UserSettingsSections . CONNECTIONS )
} ]
} ) ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : "Settings" ,
collapseStates : collapseStates ,
2021-05-03 21:22:44 +02:00
children : Object . keys ( this . defaults . general ) . map ( key => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
2021-04-27 14:03:05 +02:00
type : "Switch" ,
plugin : this ,
2021-05-03 21:22:44 +02:00
keys : [ "general" , key ] ,
label : this . defaults . general [ key ] . description ,
value : this . settings . general [ key ]
2021-04-27 14:03:05 +02:00
} ) )
} ) ) ;
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 ,
2021-05-18 19:50:28 +02:00
children : "Add Control Buttons in small and/or big Player Version: "
2021-04-27 14:03:05 +02:00
} ) ] . concat ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsList , {
2021-05-03 21:22:44 +02:00
settings : Object . keys ( this . defaults . buttons [ Object . keys ( this . defaults . buttons ) [ 0 ] ] . value ) ,
data : Object . keys ( this . defaults . buttons ) . map ( key => Object . assign ( { } , this . settings . buttons [ key ] , {
2021-04-27 14:03:05 +02:00
key : key ,
2021-05-03 21:22:44 +02:00
label : this . defaults . buttons [ key ] . description ,
icons : this . defaults . buttons [ key ] . icons
2021-04-27 14:03:05 +02:00
} ) ) ,
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
} )
]
2020-09-19 20:49:33 +02:00
} ) ,
2021-04-27 14:03:05 +02:00
onCheckboxChange : ( value , instance ) => {
2021-05-03 21:22:44 +02:00
this . settings . buttons [ instance . props . cardId ] [ instance . props . settingId ] = value ;
BDFDB . DataUtils . save ( this . settings . buttons , this , "buttons" ) ;
2021-04-27 14:03:05 +02:00
this . SettingsUpdated = true ;
}
} ) )
} ) ) ;
return 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-05-03 21:22:44 +02:00
forceUpdateAll ( ) {
2020-09-19 20:49:33 +02:00
BDFDB . PatchUtils . forceAllUpdates ( this ) ;
2021-01-30 12:36:34 +01:00
BDFDB . DiscordUtils . rerenderAll ( ) ;
2020-07-21 15:08:40 +02:00
}
2020-09-19 20:49:33 +02:00
processAppView ( e ) {
2021-04-06 09:37:54 +02:00
let injected = this . injectPlayer ( e . returnvalue ) ;
if ( ! injected ) {
let channels = BDFDB . ReactUtils . findChild ( e . returnvalue , { name : "ChannelSidebar" } ) ;
if ( channels ) {
let type = channels . type ;
channels . type = ( ... args ) => {
let appliedType = type ( ... args ) ;
this . injectPlayer ( appliedType ) ;
return appliedType ;
} ;
}
}
}
injectPlayer ( parent ) {
let [ children , index ] = BDFDB . ReactUtils . findParent ( parent , { props : [ [ "section" , BDFDB . DiscordConstants . AnalyticsSections . ACCOUNT _PANEL ] ] } ) ;
2021-01-30 12:36:34 +01:00
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" ) ,
2021-05-18 19:50:28 +02:00
timeline : this . settings . general . addTimeline ,
activityToggle : this . settings . general . addActivityButton
2021-01-30 12:36:34 +01:00
} , true ) ) ;
2021-04-06 09:37:54 +02:00
return index > - 1 ;
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 ) ;
}
}
2021-01-23 21:47:04 +01:00
setLabelsByLanguage ( ) {
switch ( BDFDB . LanguageUtils . getLanguage ( ) . id ) {
case "bg" : // Bulgarian
return {
noaccount _header : "Нещо липсва" ,
noaccount _subheader : "Трябва да свържете акаунт в Spotify" ,
noaccount _text : "Липсва ви свързан акаунт в Spotify, без акаунт няма да можете да използвате Spotify Controls. З а да свържете акаунт в Spotify с вашия акаунт в Discord, кликнете върху бутона по-долу." ,
restricted _device : "Н е може да контролира Spotify, докато възпроизвежда музика на ограничено устройство" ,
toast _copyurl _fail : "URL адресът на песента не може да бъде копиран в клипборда" ,
toast _copyurl _success : "URL адресът на песента беше копиран в клипборда"
} ;
case "da" : // Danish
return {
noaccount _header : "Noget mangler" ,
noaccount _subheader : "Du skal oprette forbindelse til en Spotify-konto" ,
noaccount _text : "Du mangler en tilsluttet Spotify-konto, uden en konto kan du ikke bruge Spotify Controls. For at forbinde en Spotify-konto med din Discord-konto skal du klikke på knappen nedenfor." ,
restricted _device : "Kan ikke kontrollere Spotify, mens du spiller musik på en begrænset enhed" ,
toast _copyurl _fail : "Sang-URL kunne ikke kopieres til udklipsholderen" ,
toast _copyurl _success : "Sang-URL blev kopieret til udklipsholderen"
} ;
case "de" : // German
return {
noaccount _header : "Etwas fehlt" ,
noaccount _subheader : "Sie müssen ein Spotify-Konto verbinden" ,
noaccount _text : "Ihnen fehlt ein verbundenes Spotify-Konto. Ohne ein Konto können Sie Spotify Controls nicht verwenden. Um ein Spotify-Konto mit Ihrem Discord-Konto zu verbinden, klicken Sie auf die Schaltfläche unten." ,
restricted _device : "Spotify kann nicht gesteuert werden, während Musik auf einem eingeschränkten Gerät abgespielt wird" ,
toast _copyurl _fail : "Die Song-URL konnte nicht in die Zwischenablage kopiert werden" ,
toast _copyurl _success : "Die Song-URL wurde in die Zwischenablage kopiert"
} ;
case "el" : // Greek
return {
noaccount _header : "Κάτι λείπει" ,
noaccount _subheader : "Πρέπει ν α συνδέσετε έναν λογαριασμό Spotify" ,
noaccount _text : "Λείπει ένας συνδεδεμένος λογαριασμός Spotify, χωρίς λογαριασμό δεν θα μπορείτε ν α χρησιμοποιήσετε το Spotify Controls. Για ν α συνδέσετε έναν λογαριασμό Spotify με τον λογαριασμό σας Discord κάντε κλικ στο παρακάτω κουμπί." ,
restricted _device : "Δεν είναι δυνατή ο έλεγχος του Spotify κατά την αναπαραγωγή μουσικής σε περιορισμένη συσκευή" ,
toast _copyurl _fail : "Δεν ήταν δυνατή η αντιγραφή του URL τραγουδιού στο πρόχειρο" ,
toast _copyurl _success : "Η διεύθυνση URL του τραγουδιού αντιγράφηκε στο πρόχειρο"
} ;
case "es" : // Spanish
return {
noaccount _header : "Algo falta" ,
noaccount _subheader : "Necesitas conectar una cuenta de Spotify" ,
noaccount _text : "Falta una cuenta de Spotify conectada, sin una cuenta no podrá usar Spotify Controls. Para conectar una cuenta de Spotify con su cuenta de Discord, haga clic en el botón de abajo." ,
restricted _device : "No se puede controlar Spotify mientras se reproduce música en un dispositivo restringido" ,
toast _copyurl _fail : "No se pudo copiar la URL de la canción al portapapeles" ,
toast _copyurl _success : "La URL de la canción se copió al portapapeles"
} ;
case "fi" : // Finnish
return {
noaccount _header : "Jotain puuttuu" ,
noaccount _subheader : "Sinun on yhdistettävä Spotify-tili" ,
noaccount _text : "Sinulta puuttuu yhdistetty Spotify-tili. Ilman tiliä et voi käyttää Spotify Controls. Yhdistä Spotify-tili Discord-tili napsauttamalla alla olevaa painiketta." ,
restricted _device : "Spotify ä ei voi hallita musiikkia toistettaessa rajoitetulla laitteella" ,
toast _copyurl _fail : "Kappaleen URL-osoitetta ei voitu kopioida leikepöydälle" ,
toast _copyurl _success : "Kappaleen URL-osoite kopioitiin leikepöydälle"
} ;
case "fr" : // French
return {
noaccount _header : "Quelque chose manque" ,
noaccount _subheader : "Vous devez connecter un compte Spotify" ,
noaccount _text : "Il vous manque un compte Spotify connecté, sans compte, vous ne pourrez pas utiliser Spotify Controls. Pour connecter un compte Spotify à votre compte Discord, cliquez sur le bouton ci-dessous." ,
restricted _device : "Impossible de contrôler Spotify lors de la lecture de musique sur un appareil restreint" ,
toast _copyurl _fail : "L'URL de la chanson n'a pas pu être copiée dans le presse-papiers" ,
toast _copyurl _success : "L'URL de la chanson a été copiée dans le presse-papiers"
} ;
case "hr" : // Croatian
return {
noaccount _header : "Nešto nedostaje" ,
noaccount _subheader : "Morate povezati Spotify račun" ,
noaccount _text : "Nedostaje vam povezani Spotify račun, bez računa nećete moći koristiti Spotify Controls. Da biste povezali Spotify račun sa svojim Discord računom, kliknite gumb u nastavku." ,
restricted _device : "Ne može kontrolirati Spotify tijekom reprodukcije glazbe na ograničenom uređaju" ,
toast _copyurl _fail : "URL pjesme nije se mogao kopirati u međuspremnik" ,
toast _copyurl _success : "URL pjesme kopiran je u međuspremnik"
} ;
case "hu" : // Hungarian
return {
noaccount _header : "Valami hiányzik" ,
noaccount _subheader : "Csatlakoztatnia kell egy Spotify-fiókot" ,
2021-01-28 14:18:17 +01:00
noaccount _text : "Hiányzik egy csatlakoztatott Spotify-fiók, fiók nélkül nem fogja tudni használni a Spotify Controls szolgáltatást. Ha Spotify-fiókot szeretne összekapcsolni Discord-fiókot, kattintson az alábbi gombra." ,
2021-01-23 21:47:04 +01:00
restricted _device : "Nem lehet irányítani a Spotify szolgáltatást, miközben zenét játszik le korlátozott eszközön" ,
toast _copyurl _fail : "A dal URL-jét nem sikerült átmásolni a vágólapra" ,
toast _copyurl _success : "A dal URL-jét a vágólapra másolta"
} ;
case "it" : // Italian
return {
noaccount _header : "Manca qualcosa" ,
noaccount _subheader : "Devi collegare un account Spotify" ,
noaccount _text : "Ti manca un account Spotify collegato, senza un account non sarai in grado di utilizzare Spotify Controls. Per collegare un account Spotify al tuo account Discord, fai clic sul pulsante in basso." ,
restricted _device : "Non è possibile controllare Spotify durante la riproduzione di musica su un dispositivo limitato" ,
toast _copyurl _fail : "L'URL del brano non può essere copiato negli appunti" ,
toast _copyurl _success : "L'URL del brano è stato copiato negli appunti"
} ;
case "ja" : // Japanese
return {
noaccount _header : "何かが欠けています" ,
noaccount _subheader : "Spotify アカウントを接続する必要があります" ,
noaccount _text : "接続されている Spotify アカウントがありません。アカウントがないと、 Spotify Controls を使用できません。 Spotify アカウントを Discord アカウントに接続するには、下のボタンをクリックしてください。" ,
restricted _device : "制限されたデバイスで音楽を再生している間は Spotify を制御できません" ,
toast _copyurl _fail : "曲のURLをクリップボードにコピーできませんでした" ,
toast _copyurl _success : "曲のURLがクリップボードにコピーされました"
} ;
case "ko" : // Korean
return {
noaccount _header : "무언가가 빠졌어" ,
noaccount _subheader : "Spotify 계정을 연결해야합니다" ,
noaccount _text : "연결된 Spotify 계정이 없습니다. 계정이 없으면 Spotify Controls 을 사용할 수 없습니다. Spotify 계정을 Discord 계정과 연결하려면 아래 버튼을 클릭하세요." ,
restricted _device : "제한된 장치에서 음악을 재생하는 동안 Spotify 를 제어 할 수 없습니다." ,
toast _copyurl _fail : "노래 URL을 클립 보드에 복사 할 수 없습니다." ,
toast _copyurl _success : "노래 URL이 클립 보드에 복사되었습니다. "
} ;
case "lt" : // Lithuanian
return {
noaccount _header : "Kažko trūksta" ,
noaccount _subheader : "Turite prijungti „ Spotify “ paskyrą" ,
noaccount _text : "Trūksta prijungtos „ Spotify “ paskyros, be paskyros negalėsite naudoti Spotify Controls. Norėdami susieti „ Spotify “ paskyrą su Discord paskyra, spustelėkite toliau pateiktą mygtuką." ,
restricted _device : "Nepavyksta valdyti „ Spotify “ grojant muziką ribotame įrenginyje" ,
toast _copyurl _fail : "Dainos URL nepavyko nukopijuoti į iškarpinę" ,
toast _copyurl _success : "Dainos URL buvo nukopijuotas į iškarpinę"
} ;
case "nl" : // Dutch
return {
noaccount _header : "Er mist iets" ,
noaccount _subheader : "U moet een Spotify-account verbinden" ,
noaccount _text : "U mist een verbonden Spotify-account. Zonder account kunt u Spotify Controls niet gebruiken. Om een Spotify-account aan uw Discord-account te koppelen, klikt u op de onderstaande knop." ,
restricted _device : "Kan Spotify niet bedienen tijdens het afspelen van muziek op een beperkt apparaat" ,
toast _copyurl _fail : "Nummer-URL kan niet naar klembord worden gekopieerd" ,
toast _copyurl _success : "Nummer-URL is naar klembord gekopieerd"
} ;
case "no" : // Norwegian
return {
noaccount _header : "Noe mangler" ,
noaccount _subheader : "Du må koble til en Spotify-konto" ,
noaccount _text : "Du mangler en tilkoblet Spotify-konto, uten en konto kan du ikke bruke Spotify Controls. For å koble en Spotify-konto til Discord-konto din, klikk på knappen nedenfor." ,
restricted _device : "Kan ikke kontrollere Spotify mens du spiller musikk på begrenset enhet" ,
toast _copyurl _fail : "Sangens URL kunne ikke kopieres til utklippstavlen" ,
toast _copyurl _success : "Sang-URL ble kopiert til utklippstavlen"
} ;
case "pl" : // Polish
return {
noaccount _header : "Czegoś brakuje" ,
noaccount _subheader : "Musisz połączyć konto Spotify" ,
noaccount _text : "Brakuje połączonego konta Spotify, bez konta nie będziesz mógł korzystać z Spotify Controls. Aby połączyć konto Spotify z kontem Discord, kliknij przycisk poniżej." ,
restricted _device : "Nie można sterować Spotify podczas odtwarzania muzyki na urządzeniu z ograniczeniami" ,
toast _copyurl _fail : "Nie udało się skopiować adresu URL utworu do schowka" ,
toast _copyurl _success : "URL utworu został skopiowany do schowka"
} ;
case "pt-BR" : // Portuguese (Brazil)
return {
noaccount _header : "Algo está faltando" ,
noaccount _subheader : "Você precisa conectar uma conta Spotify" ,
noaccount _text : "Está faltando uma conta Spotify conectada, sem uma conta você não poderá usar Spotify Controls. Para conectar uma conta Spotify à sua conta Discord, clique no botão abaixo." ,
restricted _device : "Não é possível controlar o Spotify enquanto reproduz música em dispositivo restrito" ,
toast _copyurl _fail : "O URL da música não pôde ser copiado para a área de transferência" ,
toast _copyurl _success : "O URL da música foi copiado para a área de transferência"
} ;
case "ro" : // Romanian
return {
noaccount _header : "Ceva lipseste" ,
noaccount _subheader : "Trebuie să vă conectați un cont Spotify" ,
noaccount _text : "Vă lipsește un cont Spotify conectat, fără un cont pe care nu îl veți putea folosi Spotify Controls. Pentru a conecta un cont Spotify la contul dvs. Discord faceți clic pe butonul de mai jos." ,
restricted _device : "Nu pot controla Spotify în timp ce redați muzică pe dispozitiv restricționat" ,
toast _copyurl _fail : "Adresa URL a melodiei nu a putut fi copiată în clipboard" ,
toast _copyurl _success : "Adresa URL a melodiei a fost copiată în clipboard"
} ;
case "ru" : // Russian
return {
noaccount _header : "Что-то пропало" ,
noaccount _subheader : "Вам необходимо подключить учетную запись Spotify" ,
noaccount _text : "У вас отсутствует подключенная учетная запись Spotify, без нее вы не сможете использовать Spotify Controls. Чтобы связать учетную запись Spotify с о своей учетной записью Discord, нажмите кнопку ниже." ,
restricted _device : "Невозможно управлять Spotify во время воспроизведения музыки на ограниченном устройстве" ,
toast _copyurl _fail : "URL-адрес песни не может быть скопирован в буфер обмена" ,
toast _copyurl _success : "URL песни скопирован в буфер обмена"
} ;
case "sv" : // Swedish
return {
noaccount _header : "Något saknas" ,
noaccount _subheader : "Du måste ansluta ett Spotify-konto" ,
noaccount _text : "Du saknar ett anslutet Spotify-konto utan ett konto kan du inte använda Spotify Controls. För att ansluta ett Spotify-konto till ditt Discord-konto, klicka på knappen nedan." ,
restricted _device : "Kan inte styra Spotify när du spelar musik på en begränsad enhet" ,
toast _copyurl _fail : "Låtens URL kunde inte kopieras till Urklipp" ,
toast _copyurl _success : "Låtens URL kopierades till Urklipp"
} ;
case "th" : // Thai
return {
noaccount _header : "มีบางอย่างหายไป" ,
noaccount _subheader : "คุณต้องเชื่อมต่อบัญชี Spotify" ,
noaccount _text : "คุณไม่มีบัญชี Spotify ที่เชื่อมต่อหากไม่มีบัญชีคุณจะไม่สามารถใช้ Spotify Controls ได้หากต้องการเชื่อมต่อบัญชี Spotify กับบัญชี Discord ของคุณให้คลิกปุ่มด้านล่าง" ,
restricted _device : "ไม่สามารถควบคุม Spotify ขณะเล่นเพลงบนอุปกรณ์ที่ จำกัด" ,
toast _copyurl _fail : "ไม่สามารถคัดลอก URL ของเพลงไปยังคลิปบอร์ด" ,
toast _copyurl _success : "คัดลอก URL ของเพลงไปยังคลิปบอร์ดแล้ว"
} ;
case "tr" : // Turkish
return {
noaccount _header : "Bir şey eksik" ,
noaccount _subheader : "Spotify Hesabı bağlamanı z gerekiyor" ,
noaccount _text : "Bağlı bir Spotify Hesabı nı z yok, bir Hesap olmadan Spotify Controls kullanamazsı nı z. Bir Spotify Hesabı nı Discord Hesabı nı za bağlamak için aşağı daki düğmeyi tı klayı n." ,
restricted _device : "Kı sı tlı Cihazda Müzik çalarken Spotify 'ı kontrol edemez" ,
toast _copyurl _fail : "Şarkı URL'si panoya kopyalanamadı " ,
toast _copyurl _success : "Şarkı URL'si panoya kopyalandı "
} ;
case "uk" : // Ukrainian
return {
noaccount _header : "Щось не вистачає" ,
noaccount _subheader : "Вам потрібно підключити акаунт Spotify" ,
noaccount _text : "У вас відсутній підключений обліковий запис Spotify, без якого ви не зможете використовувати Spotify Controls. Щоб підключити обліковий запис Spotify до свого облікового запису Discord, натисніть кнопку нижче." ,
restricted _device : "Н е вдається керувати Spotify під час відтворення музики на обмеженому пристрої" ,
toast _copyurl _fail : "URL-адресу пісні не вдалося скопіювати в буфер обміну" ,
toast _copyurl _success : "URL-адресу пісні скопійовано в буфер обміну"
} ;
case "vi" : // Vietnamese
return {
noaccount _header : "Thiêu một thư gi đo" ,
noaccount _subheader : "Bạn cần kết nối Tài khoản Spotify" ,
noaccount _text : "Bạn đang thiếu Tài khoản Spotify được kết nối, nếu không có Tài khoản, bạn sẽ không thể sử dụng Spotify Controls. Để kết nối Tài khoản Spotify với Tài khoản Discord của bạn, hãy nhấp vào nút bên dưới." ,
restricted _device : "Không thể điều khiển Spotify khi phát Nhạc trên Thiết bị bị hạn chế" ,
toast _copyurl _fail : "Không thể sao chép URL bài hát vào khay nhớ tạm" ,
toast _copyurl _success : "URL bài hát đã được sao chép vào khay nhớ tạm"
} ;
case "zh-CN" : // Chinese (China)
return {
noaccount _header : "缺了点什么" ,
noaccount _subheader : "您需要连接一个 Spotify 帐户" ,
noaccount _text : "您缺少关联的 Spotify 帐户,如果没有帐户,将无法使用 Spotify Controls。要将 Spotify 帐户与您的 Discord 帐户关联,请单击下面的按钮。" ,
restricted _device : "在受限设备上播放音乐时无法控制 Spotify" ,
toast _copyurl _fail : "歌曲网址无法复制到剪贴板" ,
toast _copyurl _success : "歌曲网址已复制到剪贴板"
} ;
case "zh-TW" : // Chinese (Taiwan)
return {
noaccount _header : "缺了點什麼" ,
noaccount _subheader : "您需要連接一個 Spotify 帳戶" ,
noaccount _text : "您缺少關聯的 Spotify 帳戶,如果沒有帳戶,將無法使用 Spotify Controls。要將 Spotify 帳戶與您的 Discord 帳戶關聯,請單擊下面的按鈕。" ,
restricted _device : "在受限設備上播放音樂時無法控制 Spotify" ,
toast _copyurl _fail : "歌曲網址無法複製到剪貼板" ,
toast _copyurl _success : "歌曲網址已復製到剪貼板"
} ;
default : // English
return {
noaccount _header : "Something is missing" ,
noaccount _subheader : "You need to connect a Spotify Account" ,
noaccount _text : "You are missing a connected Spotify Account, without an Account you won't be able to use Spotify Controls. To connect a Spotify Account with your Discord Account click the button below." ,
restricted _device : "Can not control Spotify while playing Music on restricted Device" ,
toast _copyurl _fail : "Song URL could not be copied to clipboard" ,
toast _copyurl _success : "Song URL was copied to clipboard"
} ;
}
}
2020-09-19 20:49:33 +02:00
} ;
2020-10-09 21:09:35 +02:00
} ) ( window . BDFDB _Global . PluginUtils . buildPlugin ( config ) ) ;
2021-01-29 07:55:45 +01:00
} ) ( ) ;