BetterDiscordAddons/Plugins/SpotifyControls/SpotifyControls.plugin.js

740 lines
29 KiB
JavaScript
Raw Normal View History

2020-07-19 16:59:08 +02:00
//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"}*//
var SpotifyControls = (_ => {
2020-08-15 20:27:43 +02:00
var _this, insertPatchCancel;
2020-07-23 20:23:23 +02:00
var controls, lastSong, currentVolume, lastVolume, stopTime, previousIsClicked, previousDoubleTimeout, timelineTimeout, timelineDragging, updateInterval;
2020-07-23 16:12:08 +02:00
var playbackState = {};
2020-08-31 16:38:37 +02:00
var settings = {}, buttonConfigs = {};
2020-07-21 15:08:40 +02:00
2020-07-23 16:12:08 +02:00
const repeatStates = [
"off",
"context",
"track"
];
2020-07-19 16:59:08 +02:00
const SpotifyControlsComponent = class SpotifyControls extends BdApi.React.Component {
componentDidMount() {
controls = this;
}
2020-07-23 16:12:08 +02:00
request(socket, device, type, data) {
2020-07-19 16:59:08 +02:00
return new Promise(callback => {
2020-07-23 16:12:08 +02:00
let method = "PUT";
switch (type) {
case "next":
case "previous":
method = "POST";
break;
case "get":
type = "";
method = "GET";
break;
};
2020-07-19 16:59:08 +02:00
BDFDB.LibraryRequires.request({
2020-07-23 16:12:08 +02:00
url: `https://api.spotify.com/v1/me/player${type ? "/" + type : ""}${Object.entries(Object.assign({}, data)).map(n => `?${n[0]}=${n[1]}`).join("")}`,
method: method,
2020-07-19 16:59:08 +02:00
headers: {
authorization: `Bearer ${socket.accessToken}`
2020-07-23 16:12:08 +02:00
}
2020-07-19 16:59:08 +02:00
}, (error, response, result) => {
2020-07-19 17:58:17 +02:00
if (response.statusCode == 401) {
2020-07-19 16:59:08 +02:00
BDFDB.LibraryModules.SpotifyUtils.getAccessToken(socket.accountId).then(promiseResult => {
let newSocketDevice = BDFDB.LibraryModules.SpotifyTrackUtils.getActiveSocketAndDevice();
2020-07-23 16:12:08 +02:00
this.request(newSocketDevice.socket, newSocketDevice.device, type, data).then(_ => {
try {callback(JSON.parse(result));}
catch (err) {callback({});}
2020-07-19 16:59:08 +02:00
});
});
}
2020-07-23 16:12:08 +02:00
else {
try {callback(JSON.parse(result));}
catch (err) {callback({});}
}
2020-07-19 16:59:08 +02:00
});
});
}
render() {
let socketDevice = BDFDB.LibraryModules.SpotifyTrackUtils.getActiveSocketAndDevice();
2020-07-23 16:12:08 +02:00
if (!socketDevice) return null;
2020-07-19 17:21:45 +02:00
if (this.props.song) {
2020-07-23 16:12:08 +02:00
playbackState.is_playing = true;
2020-08-31 16:38:37 +02:00
let fetchState = !BDFDB.equals(this.props.song, lastSong);
2020-07-19 17:21:45 +02:00
lastSong = this.props.song;
stopTime = null;
2020-07-23 21:51:49 +02:00
if (fetchState) this.request(socketDevice.socket, socketDevice.device, "get").then(response => {
playbackState = Object.assign({}, response);
BDFDB.ReactUtils.forceUpdate(this);
});
2020-07-19 17:21:45 +02:00
}
2020-07-23 16:12:08 +02:00
else if (!stopTime && lastSong) {
playbackState.is_playing = false;
stopTime = new Date();
}
if (!lastSong) return null;
currentVolume = socketDevice.device.volume_percent;
2020-08-31 16:42:18 +02:00
let playerSize = this.props.maximized ? "big" : "small";
2020-07-23 16:12:08 +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),
2020-07-19 16:59:08 +02:00
children: [
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN._spotifycontrolscontainerinner,
children: [
2020-07-23 16:12:08 +02:00
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
})
]
2020-07-19 16:59:08 +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
})
}),
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: [
2020-08-31 16:38:37 +02:00
BDFDB.ReactUtils.createElement(SpotifyControlsButtonComponent, {
type: "share",
2020-08-31 16:42:18 +02:00
playerSize: playerSize,
2020-08-31 16:38:37 +02:00
style: this.props.maximized ? {marginRight: 4} : {},
2020-07-23 20:53:46 +02:00
onClick: _ => {
2020-09-11 19:31:36 +02:00
let url = BDFDB.ObjectUtils.get(playbackState, "item.external_urls.spotify") || BDFDB.ObjectUtils.get(playbackState, "context.external_urls.spotify");
2020-07-23 21:51:49 +02:00
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"});
2020-07-23 20:53:46 +02:00
}
}),
2020-08-31 16:38:37 +02:00
BDFDB.ReactUtils.createElement(SpotifyControlsButtonComponent, {
type: "shuffle",
2020-08-31 16:42:18 +02:00
playerSize: playerSize,
2020-08-31 16:38:37 +02:00
active: playbackState.shuffle_state,
disabled: socketDevice.device.is_restricted,
onClick: _ => {
2020-07-23 16:12:08 +02:00
playbackState.shuffle_state = !playbackState.shuffle_state;
this.request(socketDevice.socket, socketDevice.device, "shuffle", {
state: playbackState.shuffle_state
});
BDFDB.ReactUtils.forceUpdate(this);
}
}),
2020-08-31 16:38:37 +02:00
BDFDB.ReactUtils.createElement(SpotifyControlsButtonComponent, {
type: "previous",
2020-08-31 16:42:18 +02:00
playerSize: playerSize,
2020-08-31 16:38:37 +02:00
disabled: socketDevice.device.is_restricted,
onClick: _ => {
2020-07-23 16:12:08 +02:00
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-19 16:59:08 +02:00
}
}),
2020-08-31 16:38:37 +02:00
BDFDB.ReactUtils.createElement(SpotifyControlsButtonComponent, {
type: "pauseplay",
2020-08-31 16:42:18 +02:00
playerSize: playerSize,
2020-08-31 16:38:37 +02:00
icon: this.props.song ? 0 : 1,
disabled: socketDevice.device.is_restricted,
onClick: _ => {
2020-07-23 16:12:08 +02:00
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-19 16:59:08 +02:00
}
}),
2020-08-31 16:38:37 +02:00
BDFDB.ReactUtils.createElement(SpotifyControlsButtonComponent, {
type: "next",
2020-08-31 16:42:18 +02:00
playerSize: playerSize,
2020-08-31 16:38:37 +02:00
disabled: socketDevice.device.is_restricted,
onClick: _ => {
2020-07-19 16:59:08 +02:00
this.request(socketDevice.socket, socketDevice.device, "next");
}
2020-07-23 16:12:08 +02:00
}),
2020-08-31 16:38:37 +02:00
BDFDB.ReactUtils.createElement(SpotifyControlsButtonComponent, {
type: "repeat",
2020-08-31 16:42:18 +02:00
playerSize: playerSize,
2020-08-31 16:38:37 +02:00
icon: playbackState.repeat_state != repeatStates[2] ? 0 : 1,
active: playbackState.repeat_state != repeatStates[0],
disabled: socketDevice.device.is_restricted,
onClick: _ => {
2020-07-23 16:12:08 +02:00
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);
}
}),
2020-08-31 16:38:37 +02:00
BDFDB.ReactUtils.createElement(SpotifyControlsButtonComponent, {
type: "volume",
2020-08-31 16:42:18 +02:00
playerSize: playerSize,
2020-08-31 16:38:37 +02:00
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
});
2020-07-23 16:12:08 +02:00
}
2020-08-31 16:38:37 +02:00
else {
lastVolume = currentVolume;
this.request(socketDevice.socket, socketDevice.device, "volume", {
volume_percent: 0
});
}
},
2020-07-23 16:12:08 +02:00
renderPopout: instance => {
2020-08-31 16:38:37 +02:00
return BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Slider, {
2020-07-23 16:12:08 +02:00
className: BDFDB.disCN._spotifycontrolsvolumeslider,
2020-07-23 20:23:23 +02:00
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
});
}
2020-07-23 16:12:08 +02:00
});
}
2020-07-19 16:59:08 +02:00
})
2020-07-23 16:12:08 +02:00
].filter(n => n)
2020-07-19 16:59:08 +02:00
})
})
]
}),
2020-07-23 16:12:08 +02:00
this.props.timeline && BDFDB.ReactUtils.createElement(SpotifyControlsTimelineComponent, {
2020-07-23 20:23:23 +02:00
song: lastSong,
socket: socketDevice.socket,
device: socketDevice.device,
controls: this
2020-07-19 16:59:08 +02:00
})
2020-07-21 15:08:40 +02:00
].filter(n => n)
2020-07-19 16:59:08 +02:00
});
}
};
2020-08-31 16:38:37 +02:00
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,
2020-08-31 16:42:55 +02:00
}), "active", "disabled", "renderPopout", "icon", "type", "playerSize"));
2020-08-31 16:38:37 +02:00
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;
}
};
2020-07-19 16:59:08 +02:00
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);
2020-07-23 16:12:08 +02:00
else if (playbackState.is_playing) {
2020-07-21 15:12:43 +02:00
let song = BDFDB.LibraryModules.SpotifyTrackUtils.getActivity(false);
2020-07-19 17:10:13 +02:00
if (!song) BDFDB.ReactUtils.forceUpdate(controls);
2020-07-23 16:12:08 +02:00
else if (playbackState.is_playing) BDFDB.ReactUtils.forceUpdate(this);
2020-07-19 17:10:13 +02:00
}
2020-07-19 16:59:08 +02:00
}, 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;
2020-07-23 16:12:08 +02:00
let currentTime = (!playbackState.is_playing && stopTime ? stopTime : new Date()) - this.props.song.timestamps.start;
2020-07-19 17:10:13 +02:00
currentTime = currentTime > maxTime ? maxTime : currentTime;
2020-07-19 16:59:08 +02:00
return BDFDB.ReactUtils.createElement("div", {
2020-07-21 15:15:26 +02:00
className: BDFDB.disCN._spotifycontrolstimeline,
2020-07-19 16:59:08 +02:00
children: [
BDFDB.ReactUtils.createElement("div", {
className: BDFDB.disCN._spotifycontrolsbar,
2020-07-23 20:23:23 +02:00
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))
});
}
2020-07-19 16:59:08 +02:00
}),
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 {
getName () {return "SpotifyControls";}
2020-08-31 16:38:37 +02:00
getVersion () {return "1.0.8";}
2020-07-19 16:59:08 +02:00
getAuthor () {return "DevilBro";}
getDescription () {return "Adds a control panel to discord when listening to spotify.";}
constructor () {
2020-07-19 17:54:47 +02:00
this.changelog = {
2020-08-31 16:38:37 +02:00
"fixed":[["Button Configuration","You can now enable/disable control buttons for the small and big player version in the plugin settings"]]
2020-07-19 17:54:47 +02:00
};
2020-07-19 16:59:08 +02:00
this.patchedModules = {
2020-08-15 20:27:43 +02:00
before: {
AppView: "render"
2020-07-19 16:59:08 +02:00
}
};
2020-07-19 17:26:50 +02:00
}
initConstructor () {
2020-07-23 16:12:08 +02:00
_this = this;
2020-07-21 15:08:40 +02:00
this.defaults = {
settings: {
2020-08-31 16:38:37 +02:00
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"}
2020-07-21 15:08:40 +02:00
}
};
2020-07-19 16:59:08 +02:00
this.css = `
@font-face {
font-family: glue1-spoticon;
2020-09-10 14:24:55 +02:00
src: url("https://mwittrien.github.io/BetterDiscordAddons/Plugins/SpotifyControls/_res/spoticon.ttf") format("truetype");
2020-07-19 16:59:08 +02:00
font-weight: 400;
font-style: normal
}
${BDFDB.dotCN._spotifycontrolscontainer} {
2020-07-21 15:08:40 +02:00
display: flex;
flex-direction: column;
justify-content: center;
min-height: 52px;
2020-07-19 16:59:08 +02:00
margin-bottom: 1px;
border-bottom: 1px solid var(--background-modifier-accent);
2020-07-21 15:08:40 +02:00
padding: 0 8px;
box-sizing: border-box;
}
${BDFDB.dotCN._spotifycontrolscontainer + BDFDB.dotCN._spotifycontrolscontainerwithtimeline} {
padding-top: 8px;
2020-07-19 16:59:08 +02:00
}
${BDFDB.dotCN._spotifycontrolscontainerinner} {
display: flex;
align-items: center;
font-size: 14px;
2020-07-23 16:12:08 +02:00
width: 100%;
2020-07-19 16:59:08 +02:00
}
2020-07-21 15:15:26 +02:00
${BDFDB.dotCN._spotifycontrolstimeline} {
2020-07-23 20:23:23 +02:00
margin: 6px 0 4px 0;
2020-07-19 16:59:08 +02:00
}
${BDFDB.dotCN._spotifycontrolsbar} {
2020-07-23 20:23:23 +02:00
position: relative;
2020-07-19 16:59:08 +02:00
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;
2020-07-21 15:18:00 +02:00
background: var(--text-normal);
2020-07-19 16:59:08 +02:00
}
2020-07-23 20:23:23 +02:00
${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;
}
2020-07-19 16:59:08 +02:00
${BDFDB.dotCN._spotifycontrolsbartext} {
display: flex;
align-items: center;
justify-content: space-between;
}
2020-07-23 16:12:08 +02:00
${BDFDB.dotCN._spotifycontrolscoverwrapper} {
position: relative;
2020-07-19 16:59:08 +02:00
width: 32px;
2020-07-23 16:12:08 +02:00
min-width: 32px;
2020-07-19 16:59:08 +02:00
height: 32px;
2020-07-23 16:12:08 +02:00
min-height: 32px;
2020-07-19 16:59:08 +02:00
margin-right: 8px;
border-radius: 4px;
2020-07-23 16:12:08 +02:00
overflow: hidden;
transition: width .3s ease, height .3s ease;
}
${BDFDB.dotCN._spotifycontrolscover} {
display: block;
width: 100%;
height: 100%;
2020-07-19 16:59:08 +02:00
object-fit: cover;
}
2020-07-23 16:12:08 +02:00
${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;
}
2020-07-19 16:59:08 +02:00
${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;
}
2020-07-23 16:12:08 +02:00
${BDFDB.dotCN._spotifycontrolsvolumeslider} {
2020-07-23 20:23:23 +02:00
height: 12px;
2020-07-23 16:12:08 +02:00
width: 140px;
margin: 5px;
}
${BDFDB.dotCNS._spotifycontrolsvolumeslider + BDFDB.dotCN.slidergrabber} {
height: 10px;
margin-top: -6px;
border-radius: 50%;
}
2020-07-23 20:23:23 +02:00
${BDFDB.dotCNS._spotifycontrolscontainer + BDFDB.dotCN.accountinfobuttondisabled} {
cursor: no-drop;
}
${BDFDB.dotCNS._spotifycontrolscontainer + BDFDB.dotCNS.accountinfobutton + BDFDB.dotCN.buttoncontents} {
font-family: glue1-spoticon !important;
}
2020-07-23 16:12:08 +02:00
${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);
}
2020-08-31 16:38:37 +02:00
${BDFDB.dotCN._spotifycontrolssettingsicon} {
margin: 4px;
font-size: 16px;
font-family: glue1-spoticon !important;
}
${BDFDB.dotCN._spotifycontrolssettingslabel} {
margin-left: 10px;
}
2020-07-19 16:59:08 +02:00
`;
}
2020-07-23 20:23:23 +02:00
getSettingsPanel (collapseStates = {}) {
if (!window.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded || !this.started) return;
2020-09-04 11:25:48 +02:00
settings = BDFDB.DataUtils.get(this, "settings");
buttonConfigs = BDFDB.DataUtils.get(this, "buttonConfigs");
2020-07-23 20:23:23 +02:00
let settingsPanel, settingsItems = [];
2020-08-31 16:38:37 +02:00
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
title: "Settings",
collapseStates: collapseStates,
children: Object.keys(settings).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
className: BDFDB.disCN.marginbottom8,
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;
}
}))
2020-07-23 20:23:23 +02:00
}));
return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, settingsItems);
}
2020-07-19 16:59:08 +02:00
// Legacy
2020-08-21 16:17:47 +02:00
load () {
if (window.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) BDFDB.PluginUtils.load(this);
}
2020-07-19 16:59:08 +02:00
start () {
if (!window.BDFDB) window.BDFDB = {myPlugins:{}};
if (window.BDFDB && window.BDFDB.myPlugins && typeof window.BDFDB.myPlugins == "object") window.BDFDB.myPlugins[this.getName()] = this;
let libraryScript = document.querySelector("head script#BDFDBLibraryScript");
if (!libraryScript || (performance.now() - libraryScript.getAttribute("date")) > 600000) {
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("id", "BDFDBLibraryScript");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.min.js");
libraryScript.setAttribute("date", performance.now());
libraryScript.addEventListener("load", _ => {this.initialize();});
document.head.appendChild(libraryScript);
}
else if (window.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize();
this.startTimeout = setTimeout(_ => {
try {return this.initialize();}
catch (err) {console.error(`%c[${this.getName()}]%c`, "color: #3a71c1; font-weight: 700;", "", "Fatal Error: Could not initiate plugin! " + err);}
}, 30000);
}
initialize () {
if (window.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) {
if (this.started) return;
BDFDB.PluginUtils.init(this);
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
}
else {
console.error(`%c[${this.getName()}]%c`, 'color: #3a71c1; font-weight: 700;', '', 'Fatal Error: Could not load BD functions!');
}
}
stop () {
if (window.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) {
this.stopping = true;
2020-07-21 15:08:40 +02:00
this.forceUpdateAll();
2020-08-15 20:27:43 +02:00
if (typeof insertPatchCancel == "function") insertPatchCancel();
2020-07-19 16:59:08 +02:00
BDFDB.PluginUtils.clear(this);
}
}
// Begin of own functions
2020-07-21 15:08:40 +02:00
onSettingsClosed () {
if (this.SettingsUpdated) {
delete this.SettingsUpdated;
this.forceUpdateAll();
}
}
2020-08-15 20:27:43 +02:00
processAppView (e) {
if (typeof insertPatchCancel == "function") insertPatchCancel();
2020-09-11 19:31:36 +02:00
insertPatchCancel = BDFDB.PatchUtils.patch(this, e.instance, "renderChannelSidebar", {after: e2 => {
2020-08-15 20:27:43 +02:00
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
2020-08-31 16:38:37 +02:00
}, true));
2020-08-15 20:27:43 +02:00
}}, {force: true, noCache: true});
2020-07-19 16:59:08 +02:00
}
updatePlayer (song) {
if (controls) {
controls.props.song = song;
BDFDB.ReactUtils.forceUpdate(controls);
}
}
2020-07-21 15:08:40 +02:00
forceUpdateAll() {
settings = BDFDB.DataUtils.get(this, "settings");
2020-08-31 16:38:37 +02:00
buttonConfigs = BDFDB.DataUtils.get(this, "buttonConfigs");
2020-07-21 15:08:40 +02:00
2020-09-11 19:31:36 +02:00
BDFDB.PatchUtils.forceAllUpdates(this);
2020-07-21 15:08:40 +02:00
}
2020-07-19 16:59:08 +02:00
}
2020-07-26 17:02:25 +02:00
})();
module.exports = SpotifyControls;