Spotify Chrome Extension - Merging the Front-end & Back-end
This is Phase Six of a multi-phase project where we build a Spotify Chrome Extension powered by ReactJS that allows us to control the user's Spotify session
Phase One can be found here.
This tutorial assumes you know how Google Chrome Extensions work. Learn more here.
Like any Chrome Extension, we need to inject the foreground page into the User's browser.
We, of course, inject from our Background.js script.
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status === 'complete' && tab.url.includes('http')) {
active_tabId = tabId;
chrome.tabs.executeScript(tabId, { file: './inject_script.js' }, function () {
chrome.tabs.executeScript(tabId, { file: './foreground.bundle.js' }, function () {
console.log("INJECTED AND EXECUTED");
});
});
}
});
chrome.tabs.onActivated.addListener(activeInfo => {
chrome.tabs.get(activeInfo.tabId, function (tab) {
if (tab.url.includes('http')) active_tabId = activeInfo.tabId;
});
});
Now that we've done that, let create GET and SET state functions for our entire App.
Staying in our Background.js file, we'll create those two functions...
function get_state() {
return new Promise((resolve, reject) => {
chrome.storage.local.get('chrome-ext-Spotify-controller', item => {
if (chrome.runtime.lastError) {
reject('fail');
} else {
const state = item['chrome-ext-Spotify-controller'] ? item['chrome-ext-Spotify-controller'] : "{}";
resolve(JSON.parse(state));
}
});
});
}
function set_state(_state) {
return new Promise((resolve, reject) => {
get_state()
.then(res => {
const updated_state = {
...res,
..._state
}
chrome.storage.local.set({ 'chrome-ext-Spotify-controller': JSON.stringify(updated_state) }, () => {
if (chrome.runtime.lastError) {
reject('fail');
} else {
resolve('success');
}
});
});
});
}
All that's left to do is pair our Spotify API logic in the Background script to the function calls in our Foreground script.
We won't go into every function pairing here, we'll show you one.
See the video tutorial for a detailed walk-through.
In the Foreground.js component we have our start_pause function message our Background.js script.
start_pause = () => {
chrome.runtime.sendMessage({ message: this.state.isPlaying ? 'pause' : 'play', payload: { isPlaying: !this.state.isPlaying } }, response => {
if (response.message === 'success') {
this.setState(_state => {
return {
isPlaying: !_state.isPlaying,
current_track: response.current_track
}
});
}
});
}
In our Background.js script, we catch that message, call the Spotify API, and send back a response to the Foreground.js component.
...
if (request.message === 'play') {
player.play()
.then(res => set_state(request.payload))
.then(res => player.current())
.then(res => sendResponse({ message: 'success', current_track: res.current_track }))
.catch(err => sendResponse({ message: 'fail' }));
return true;
} else if (request.message === 'pause') {
player.pause()
.then(res => set_state(request.payload))
.then(res => player.current())
.then(res => sendResponse({ message: 'success', current_track: res.current_track }))
.catch(err => sendResponse({ message: 'fail' }));
return true;
...
After merging our Background and Foreground, we handle the Login System.
If you want to see how that's done see the video tutorial below.
You can find the final source files for this project here.
If you want a more in-depth guide, check out my full video tutorial on YouTube, An Object Is A.
Build a Cyberpunk 2077-inspired Spotify Controller - Phase 6
Top comments (0)