Hi Everyone,
I wanted to share a project I started in April and haven’t gotten around to sharing. It’s called Steem Menu. The proof of concept is available in the Chrome Web Store and the Brave Browser equivalent. In this post I’ll explain the why, the what, and also dive into the code.
Why
The idea behind Steem Menu is simple. There are many Steem dApps out there. For a new Steemian, discovery is challenging. They don’t know what’s out there, and they don’t realize: Steem is much bigger than Steemit!
Even if you do know about all these dApps sometimes you can’t remember the name. You go to sites like stateofthedapps.com or STEEMprojects.com to explore and find the app you’re looking for.
Steem Menu makes it more convenient to access popular Steem dApps. It does this by putting a menu in your browser. It works similar to the Start Menu in Windows which provides handy shortcuts to installed applications. So you can just click on the menu button and click on Steemit Wallet and away you go. Save yourself some keystrokes.
What
Steem Menu is a browser extension for Chrome and other Chromium-based browsers (Brave included). It would be trivial to also support Firefox. If you want to try out Steem Menu, you can find it here:
Steem Menu - Chrome Web Store
The Chrome developer portal provides some anonymized statistics like number of installs. In the below screenshot you will notice a small number of people have tried Steem Menu prior to this announcement. Most of these are people I contacted for feedback, and a few people who randomly discovered it through search.
Shout out to @jongolson,
@ecoinstant,
@niallon11 who all provided very helpful feedback in the early stages.
Next Steps
- Get your feedback.
- Add more apps the menu. What else should be listed?
- Add new features! Things like allowing users to reorder menus or set favorites. What else would you like to see?
Okay, let’s dive into the code. The code is available on GitHub here: https://github.com/torreyblog/steem-start-menu
Code
There isn’t a whole lot of code to dive into. Browser extensions are like glorified web apps. So web development skills like HTML, CSS, and JavaScript come into play.
Web Extensions start with a manifest. This is a JSON-formatted file which contains metadata for the extension. Thinks like it’s name, where to find it’s code, and permissions it needs to do business. Steem Menu is very minimalistic so it doesn’t need ANY permissions.
Below is what the manifest looks like. The most interesting bits are the “browser_action” which describes what to do when the extension menu icon is clicked. And the “background” which describes what code to run behind the scenes. I’ll explain why this necessary in a bit.
{
"manifest_version": 2,
"name": "Steem Menu",
"version": “0.0.0.4”,
"description": "Steem is much bigger than Steemit! Steem menu is a collection of shortcuts to useful Steem blockchain apps.",
"icons": { "128": "steem-menu-icon-3-128.png" },
"browser_action": {
"default_title": "Start",
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"]
}
}
At the moment, there are really only 3 real source files for Steem Menu. They are popup.html, popup.js, and background.js. Popup.js could be even be done as inline javascript inside popup.html, but modern browsers don’t like inline JavaScript for security reasons. All the fancy UI stuff is handled by Bootstrap (bootstrap.min.js, bootstrap.min.css) which depends on another library called JQuery (jquery-3.4.0.min.js). Including the dependencies that’s just 6 files containing code!
Steem Menu uses a library called Bootstrap for all of its UI components. Bootstrap is very useful for getting started quickly and producing something non-ugly. You can use Bootstrap components like buttons out of the box and not have to worry at all about visual styles / design.
Popup.html contains all the markup for the front end of the app. It describes what text and UI elements to show inside the extension’s popup menu. Here’s what it looks like:
<div class="accordion" id="accordionExample">
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
Starters <span class="badge badge-primary">3</span>
</button>
</h5>
</div>
<div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordionExample">
<div class="card-body">
<ul class="list-group">
<li class="list-group-item">
<button class="btn btn-dark dapplink" type="button" value="https://steemit.com">Steemit</button>
<span class="badge badge-light">Your voice is worth something</span>
</li>
<li class="list-group-item">
<button class="btn btn-dark dapplink" type="button" value="https://steemitwallet.com">SteemitWallet</button>
<span class="badge badge-light">Steemit's official Steem blockchain wallet</span>
</li>
</ul>
</div>
</div>
</div>
Popup.js is 25 lines of code which tells the browser what to do when a button or a link is clicked on. If we were only supporting Firefox we wouldn’t even need this because Firefox let’s you click on links in the popup and directly navigate to the link. Chrome, however doesn’t launch new tabs or anything when the links are clicked on, so we need a workaround.
The work around involves the Chrome runtime messaging API. We will use this API to send a message from the popup to the background page whenever one of the buttons/links is clicked on. Conveniently, Firefox supports this API also, even though it has “chrome” in the name.
Here’s what the code looks like for handling button clicks:
function handleClickButton(e) {
if (typeof e.target.value !== 'undefined' && e.target.value != "") {
chrome.runtime.sendMessage({
url: e.target.value
})
}
}
var buttons = document.querySelectorAll('button.dapplink')
buttons.forEach(function(button) {
addEventListener('click', handleClickButton)
})
Basically it says add an event handler to all button elements that have the class ‘dapplink’. When the event handler triggers, send a message to the background page containing the URL for the clicked-on link.
Lastly, we need code to receive this message and do the navigation. We have 11 lines of code in background.js to achieve this.
function createNewTab(url) {
chrome.tabs.create({
url: url
})
}
function handleMessage(request, sender, sendResponse) {
createNewTab(request.url)
}
chrome.runtime.onMessage.addListener(handleMessage)
All this says is: listen for messages. When a message is received, extract the URL, create a new tab to navigate the the URL.
That’s all folks. Thanks for reading, and please leave a comment if:
- I was not clear about code explanation in some part
- You have suggestions or requests for apps or features to be added
- You think Steem Menu is useful and I should keep improving it
Until next time,
Torrey