text: //META{"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"}*//
  
  module.exports = (_ => {
  	const config = {
  		"info": {
  			"name": "SpotifyControls",
  			"author": "DevilBro",
  			"version": "1.0.8",
  			"description": "Add a control panel to discord when listening to spotify"
  		}
  	};
  	return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
  		getName () {return config.info.name;}
  		getAuthor () {return config.info.author;}
  		getVersion () {return config.info.version;}
  		getDescription () {return config.info.description;}
  		
  		load() {
  			if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue:[]});
  			if (!window.BDFDB_Global.downloadModal) {
  				window.BDFDB_Global.downloadModal = true;
  				BdApi.showConfirmationModal("Library Missing", `The library plugin needed for ${config.info.name} is missing. Please click "Download Now" to install it.`, {
  					confirmText: "Download Now",
  					cancelText: "Cancel",
  					onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
  					onConfirm: _ => {
  						delete window.BDFDB_Global.downloadModal;
  						require("request").get("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js", (e, r, b) => {
  							if (!e && b && b.indexOf(`//META{"name":"`) > -1) require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => {});
  							else BdApi.alert("Error", "Could not download BDFDB library plugin, try again some time later.");
  						});
  					}
  				});
  			}
  			if (!window.BDFDB_Global.pluginQueue.includes(config.info.name)) window.BDFDB_Global.pluginQueue.push(config.info.name);
  		}
  		start() {this.load();}
  		stop() {}
  	} : (([Plugin, BDFDB]) => {
  		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 {
  			componentDidMount() {
  				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) => {
  						if (response.statusCode == 401) {
  							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({});}
  						}
  					});
  				});
  			}
  			render() {
  				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);
  									},
  									children: [
  										BDFDB.ReactUtils.createElement("img", {
  											className: BDFDB.disCN._spotifycontrolscover,
  											src: BDFDB.LibraryModules.AssetUtils.getAssetImage(lastSong.application_id, lastSong.assets.large_image)
  										}),
  										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
  											})
  										}),
  										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) {
  														BDFDB.LibraryRequires.electron.clipboard.write({text:url});
  														BDFDB.NotificationUtils.toast("Song URL was copied to clipboard", {type: "success"});
  													}
  													else BDFDB.NotificationUtils.toast("Could not copy song URL to clipboard", {type: "error"});
  												}
  											}),
  											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);
  												}
  											}),
  											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);
  													}
  												}
  											}),
  											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");
  													}
  												}
  											}),
  											BDFDB.ReactUtils.createElement(SpotifyControlsButtonComponent, {
  												type: "next",
  												playerSize: playerSize,
  												disabled: socketDevice.device.is_restricted,
  												onClick: _ => {
  													this.request(socketDevice.socket, socketDevice.device, "next");
  												}
  											}),
  											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
  													});
  													BDFDB.ReactUtils.forceUpdate(this);
  												}
  											}),
  											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;
  														this.request(socketDevice.socket, socketDevice.device, "volume", {
  															volume_percent: 0
  														});
  													}
  												},
  												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)
  									})
  								})
  							]
  						}),
  						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 {
  			render() {
  				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 {
  			componentDidMount() {
  				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}`
  			}
  			render() {
  				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)
  								})
  							]
  						})
  					]
  				});
  			}
  		};
  	
  		return class SpotifyControls extends Plugin {
  			onLoad() {
  				_this = this;
  				
  				this.defaults = {
  					settings: {
  						addTimeline: 		{value:true,		description:"Show the song timeline in the controls"}
  					},
  					buttonConfigs: {
  						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"}
  					}
  				};
  				
  				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: 52px;
  						margin-bottom: 1px;
  						border-bottom: 1px solid var(--background-modifier-accent);
  						padding: 0 8px;
  						box-sizing: border-box;
  					}
  					${BDFDB.dotCN._spotifycontrolscontainer + BDFDB.dotCN._spotifycontrolscontainerwithtimeline} {
  						padding-top: 8px;
  					}
  					${BDFDB.dotCN._spotifycontrolscontainerinner} {
  						display: flex;
  						align-items: center;
  						font-size: 14px;
  						width: 100%;
  					}
  					${BDFDB.dotCN._spotifycontrolstimeline} {
  						margin: 6px 0 4px 0;
  					}
  					${BDFDB.dotCN._spotifycontrolsbar} {
  						position: relative;
  						border-radius: 2px;
  						background-color: rgba(79, 84, 92, 0.16);
  						height: 4px;
  						margin-bottom: 4px;
  					}
  					${BDFDB.dotCN._spotifycontrolsbarfill} {
  						border-radius: 2px;
  						height: 100%;
  						min-width: 4px;
  						border-radius: 2px;
  						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: 8px;
  						height: 8px;
  						margin-top: -2px;
  						margin-left: -2px;
  						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: 32px;
  						min-width: 32px;
  						height: 32px;
  						min-height: 32px;
  						margin-right: 8px;
  						border-radius: 4px;
  						overflow: hidden;
  						transition: width .3s ease, height .3s 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: 12px;
  						height: 12px;
  						padding: 3px;
  						transform: rotate(90deg);
  						transition: width .3s ease, height .3s ease, transform .3s ease;
  						pointer-events: none;
  					}
  					${BDFDB.dotCN._spotifycontrolscoverwrapper}:hover ${BDFDB.dotCN._spotifycontrolscovermaximizer} {
  						visibility: visible;
  					}
  					${BDFDB.dotCN._spotifycontrolsdetails} {
  						user-select: text;
  						flex-grow: 1;
  						margin-right: 4px;
  						min-width: 0;
  					}
  					${BDFDB.dotCN._spotifycontrolssong} {
  						font-weight: 500;
  					}
  					${BDFDB.dotCN._spotifycontrolsinterpret} {
  						font-weight: 300;
  					}
  					${BDFDB.dotCN._spotifycontrolsvolumeslider} {
  						height: 12px;
  						width: 140px;
  						margin: 5px;
  					}
  					${BDFDB.dotCNS._spotifycontrolsvolumeslider + BDFDB.dotCN.slidergrabber} {
  						height: 10px;
  						margin-top: -6px;
  						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 4px 0;
  						width: 100%;
  						text-align: center;
  					}
  					${BDFDB.dotCN._spotifycontrolscontainer + BDFDB.dotCNS._spotifycontrolscontainermaximized + BDFDB.dotCN._spotifycontrolscoverwrapper} {
  						width: calc(100% + 16px);
  						height: 100%;
  						margin: 0 0 8px 0;
  						border-radius: 0;
  					}
  					${BDFDB.dotCN._spotifycontrolscontainer + BDFDB.dotCNS._spotifycontrolscontainermaximized + BDFDB.dotCN._spotifycontrolscovermaximizer} {
  						top: 4px;
  						right: 4px;
  						width: 22px;
  						height: 22px;
  						padding: 5px;
  						transform: rotate(-90deg);
  					}
  					${BDFDB.dotCN._spotifycontrolssettingsicon} {
  						margin: 4px;
  						font-size: 16px;
  						font-family: glue1-spoticon !important;
  					}
  					${BDFDB.dotCN._spotifycontrolssettingslabel} {
  						margin-left: 10px;
  					}
  				`;
  			}
  			
  			onStart() {
  				BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.SpotifyTrackUtils, "getActivity", {after: e => {
  					if (e.methodArguments[0] !== false) {
  						if (e.returnValue && e.returnValue.name == "Spotify") this.updatePlayer(e.returnValue);
  						else if (!e.returnValue) this.updatePlayer(null);
  					}
  				}});
  
  				BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.SpotifyTrackUtils, "wasAutoPaused", {instead: e => {
  					return false;
  				}});
  
  				BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.SpotifyUtils, "pause", {instead: e => {
  					return false;
  				}});
  				
  				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)
  						}
  					}]
  				});
  				
  				this.forceUpdateAll();
  			}
  			
  			onStop() {
  				this.forceUpdateAll();
  				
  				if (typeof insertPatchCancel == "function") insertPatchCancel();
  			}
  
  			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,
  						children: "Add control buttons in small and/or big player version:"
  					})].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);
  			}
  
  			onSettingsClosed () {
  				if (this.SettingsUpdated) {
  					delete this.SettingsUpdated;
  					this.forceUpdateAll();
  				}
  			}
  		
  			forceUpdateAll() {
  				settings = BDFDB.DataUtils.get(this, "settings");
  				buttonConfigs = BDFDB.DataUtils.get(this, "buttonConfigs");
  				
  				BDFDB.PatchUtils.forceAllUpdates(this);
  			}
  
  			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});
  			}
  			
  			updatePlayer (song) {
  				if (controls) {
  					controls.props.song = song;
  					BDFDB.ReactUtils.forceUpdate(controls);
  				}
  			}
  		};
  	})(window.BDFDB_Global.PluginUtils.buildPlugin(config));
  })();