Compare commits

...

13 Commits

Author SHA1 Message Date
Nathan Parikh
fa54efcec6 Updates for windows and mac builds 2020-06-13 11:29:37 -05:00
Nathan Parikh
53bd6af536 Merge branch 'master' of https://github.com/nathanp/crypto-price-widget 2020-06-13 01:58:58 -05:00
Nathan Parikh
073a483bf2 v1.4.0 - updating packages, coin list, etc. 2020-06-13 01:58:27 -05:00
Nathan Parikh
af39424d7d
Updated README
updated donation addresses
2020-02-21 15:30:28 -06:00
Nathan Parikh
4b795fb375 Version 1.2.0 2017-10-16 13:33:47 -05:00
Nathan Parikh
5112fc8e8d UI updates - new icons 2017-10-13 10:14:37 -05:00
Nathan Parikh
1f381d4c25 more UI/UX improvements. Starting to test price notifications/alerts! 2017-10-12 23:55:20 -05:00
Nathan Parikh
ac6d6861bf UI improvements 2017-10-12 22:23:40 -05:00
Nathan Parikh
649a26299c code cleanup 2017-10-11 09:22:46 -05:00
Nathan Parikh
c0eb800259 The adding and removing of coins is much more smooth now. The app doesn't have to do a full reload. All new coins added are placed at the bottom. Still need to add/remove them from the portfolio screen. Code optimizations. 2017-10-11 09:18:22 -05:00
Nathan Parikh
e4bc240bf2 fonts are now local to help speed up the app load time 2017-10-11 07:52:31 -05:00
Nathan Parikh
03fe34fb08 bug fixes and added an error screen if no internet connection present 2017-10-10 16:26:35 -05:00
nathanp
d7f9c9d2d4 MacOS 1.10 2017-09-16 15:11:21 -05:00
31 changed files with 8257 additions and 6583 deletions

5
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules node_modules
release-builds
out/ out/
*.code-workspace

View File

@ -23,12 +23,14 @@ Crypto Price Widget is an open source project created by [Nathan Parikh](https:/
## Donate ## Donate
Crypto Price Widget is an open source side project. To support development and keep the project running, you can donate using Bitcoin, Ethereum, Litecoin, or Doge: Crypto Price Widget is an open source side project. To support development and keep the project running, you can donate using one of the below options:
- Bitcoin: `17iENfaJkEpxGXW7mgdFh9hGMZV65R2zVL` - PayPal: https://www.paypal.me/nathanp
- Ethereum: `0x68b99868700b33A248de4A62a038a9e3b03DCA21` - CashApp: https://cash.app/$ndzynes
- Litecoin: `La8eCVjzLq8zrJV3LgyU6WtnyQnjs76LFY` - Bitcoin: `bc1qkzrkkhmufjuyslh92mfne5yfe6trhf2u258wl4`
- Doge: `DFHBdwUbcvGezfgHHbWmH8eLWjAjUhFSZ2` - Ethereum: `0x0606405c03F381EF187C413438E7efE705ec64AA`
- Litecoin: `LNBBr1iutwMCTfGcPps2Qhg66vSkAbZWhE`
- Doge: `DG1twgxAJa4Tj42e4aoHVnh654Ro8ftDGi`
## FAQ ## FAQ

1
coinlist.json Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

1579
css/animate.css vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,62 @@
/*Fonts*/
@font-face {
font-family: 'heeboregular';
src: url('../fonts/heebo-regular-webfont.woff2') format('woff2'),
url('../fonts/heebo-regular-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'heebothin';
src: url('../fonts/heebo-thin-webfont.woff2') format('woff2'),
url('../fonts/heebo-thin-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'inconsolataregular';
src: url('../fonts/inconsolata-regular-webfont.woff2') format('woff2'),
url('../fonts/inconsolata-regular-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
}
body,
button,
#myInput,
#saveCoins,
#saveQuantities {
font-family: 'inconsolataregular', monospace;
}
.coin-list li .sym {
font-family: 'heeboregular', sans-serif;
}
body { body {
background: rgba(0, 0, 0, 0.95); background: rgba(0, 0, 0, 0.95);
font-family: 'Inconsolata', monospace;
color: #fff; color: #fff;
margin-top: 5px; margin-top: 35px;
} }
ul { ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
img {
max-width: 100%;
}
.titlebar { .titlebar {
-webkit-user-select: none; -webkit-user-select: none;
-webkit-app-region: drag; -webkit-app-region: drag;
opacity: 0; opacity: 0;
position: fixed;
width: 94%;
z-index: 100;
background: rgba(0, 0, 0, 0.95);
top: 0;
left: 0;
padding: 8px 3% 3px;
} }
.titlebar:hover { .titlebar:hover {
opacity: 1; opacity: 1;
@ -20,12 +65,20 @@ ul {
float: right; float: right;
line-height: 0; line-height: 0;
} }
button { button {
-webkit-app-region: no-drag; -webkit-app-region: no-drag;
background: none; background-color: #000000;
border: none; color: #fff;
outline: none; border: 1px solid #252525;
padding: 5px 10px;
margin: -1px 0px 0px 0px;
} }
header button {
background: none;
border: none;
outline: none;
}
#close-btn, #close-btn,
#min-btn { #min-btn {
@ -37,6 +90,11 @@ button {
-webkit-border-radius: 50px; -webkit-border-radius: 50px;
border-radius: 50px; border-radius: 50px;
padding: 0; padding: 0;
-webkit-transition: all 150ms ease;
-moz-transition: all 150ms ease;
-ms-transition: all 150ms ease;
-o-transition: all 150ms ease;
transition: all 150ms ease;
} }
#close-btn { #close-btn {
border-color: #ff2626; border-color: #ff2626;
@ -57,10 +115,17 @@ button {
.tabs button, .tabs button,
.tabs button.active { .tabs button.active {
display: inline-block; display: inline-block;
vertical-align: top;
} }
.tabs button img { .tabs button img {
width: 19px; width: 16px;
height: 16px;
opacity: 0.5; opacity: 0.5;
-webkit-transition: all 150ms ease;
-moz-transition: all 150ms ease;
-ms-transition: all 150ms ease;
-o-transition: all 150ms ease;
transition: all 150ms ease;
} }
.tabs button:hover img, .tabs button:hover img,
.tabs button.active img { .tabs button.active img {
@ -133,11 +198,18 @@ ul {
border: 1px solid #252525; border: 1px solid #252525;
border-left-width: 2px; border-left-width: 2px;
padding: 0px 5px 0px; padding: 0px 5px 0px;
font-family: 'Heebo', sans-serif;
font-size: 12px; font-size: 12px;
} }
.coin-list li .sym:hover { .coin-list li .sym:hover {
cursor: -webkit-grab; cursor: -webkit-grab;
border-top-color: #4c4c4c;
border-right-color: #4c4c4c;
border-bottom-color: #4c4c4c;
-webkit-transition: all 250ms ease;
-moz-transition: all 250ms ease;
-ms-transition: all 250ms ease;
-o-transition: all 250ms ease;
transition: all 250ms ease;
} }
/*Symbol Colors*/ /*Symbol Colors*/
.coin-list li#coin-BTC .sym { .coin-list li#coin-BTC .sym {
@ -200,7 +272,7 @@ ul {
} }
.coin-list li .change { .coin-list li .change {
padding: 2px 3px 2px; padding: 2px 3px 2px;
font-size: 12px; font-size: 14px;
float: right; float: right;
margin: 10px 0px 0px; margin: 10px 0px 0px;
background: #000; background: #000;
@ -224,7 +296,6 @@ ul {
margin-top: 5px; margin-top: 5px;
} }
#myInput { #myInput {
font-family: 'Inconsolata', monospace;
border: none; border: none;
padding: 0px 0px 10px; padding: 0px 0px 10px;
font-size: 14px; font-size: 14px;
@ -242,7 +313,6 @@ ul {
border: 1px solid #252525; border: 1px solid #252525;
padding: 5px 10px; padding: 5px 10px;
margin: -1px 0px 0px 0px; margin: -1px 0px 0px 0px;
font-family: 'Inconsolata', monospace;
} }
#coinlist { #coinlist {
margin: 15px 0px 0px 0px; margin: 15px 0px 0px 0px;
@ -263,15 +333,18 @@ ul {
#coinlist label, #coinlist label,
.checkbox-styled-label { .checkbox-styled-label {
height: auto; height: 18px;
width: 100%;
z-index: 0; z-index: 0;
display: inline-block; display: inline-block;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
text-indent: 24px; text-indent: 24px;
overflow: hidden;
} }
#coinlist label {
cursor: pointer;
}
#coinlist label div, #coinlist label div,
.checkbox-styled-label div { .checkbox-styled-label div {
height: 12px; height: 12px;
@ -283,6 +356,11 @@ ul {
transition: all 0ms ease-in-out, border 0ms ease 0ms; transition: all 0ms ease-in-out, border 0ms ease 0ms;
position: absolute; position: absolute;
top: 0; top: 0;
-webkit-transition: all 250ms ease;
-moz-transition: all 250ms ease;
-ms-transition: all 250ms ease;
-o-transition: all 250ms ease;
transition: all 250ms ease;
} }
#coinlist input:hover + label div, #coinlist input:hover + label div,
.checkbox-styled:hover + label div { .checkbox-styled:hover + label div {
@ -358,9 +436,12 @@ ul {
::-webkit-scrollbar-thumb:window-inactive, ::-webkit-scrollbar-thumb:window-inactive,
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
background: #252525; background-color: #252525;
-webkit-border-radius: 100px; -webkit-border-radius: 100px;
} }
::-webkit-scrollbar-thumb:hover {
background-color: #4c4c4c;
}
/*Select Boxes*/ /*Select Boxes*/
.custom-select { .custom-select {
@ -405,4 +486,20 @@ ul {
background: #252525; background: #252525;
color: white; color: white;
pointer-events: none; pointer-events: none;
} }
/*Offline*/
.error {
text-align: center;
}
.error h2,
.error h4 {
font-family: Arial,Helvetica,sans-serif;
}
.error button.refresh {
cursor: pointer;
background: #41BB2E;
border: none;
color: #000;
font-weight: bold;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
images/appbar.alert.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

BIN
images/appbar.pie.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
images/appbar.settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/appbar.stock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
images/offline_doge.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -2,9 +2,7 @@
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Latest Crypto Prices</title> <title>Crypto Price Widget</title>
<link href="https://fonts.googleapis.com/css?family=Heebo:100,400" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet">
<link href="css/app.css" rel="stylesheet"> <link href="css/app.css" rel="stylesheet">
</head> </head>
@ -15,9 +13,9 @@
<button id="close-btn"></button> <button id="close-btn"></button>
</div><!-- .controls --> </div><!-- .controls -->
<div class="tabs"> <div class="tabs">
<button id="main-btn" href="#main"><img src="images/icons8-Home-64.png"></button> <button id="main-btn" href="#main"><img src="images/appbar.stock.png"></button>
<button id="portfolio-btn" href="#portfolio"><img src="images/icons8-Rebalance Portfolio-100.png"></button> <button id="portfolio-btn" href="#portfolio"><img src="images/appbar.pie.png"></button>
<button id="settings-btn" href="#settings"><img src="images/icons8-Settings.png"></button> <button id="settings-btn" href="#settings"><img src="images/appbar.settings.png"></button>
</div><!-- .tabs --> </div><!-- .tabs -->
</header> </header>
@ -71,7 +69,6 @@
</label> </label>
</div> </div>
<h3>Tip Jar</h3> <h3>Tip Jar</h3>
<ul id="tips"> <ul id="tips">
<li>BTC: 17iENfaJkEpxGXW7mgdFh9hGMZV65R2zVL</li> <li>BTC: 17iENfaJkEpxGXW7mgdFh9hGMZV65R2zVL</li>
@ -80,9 +77,11 @@
<li>DOGE: DFHBdwUbcvGezfgHHbWmH8eLWjAjUhFSZ2</li> <li>DOGE: DFHBdwUbcvGezfgHHbWmH8eLWjAjUhFSZ2</li>
</ul> </ul>
<div class="creds"> <h4>Build Info</h4>
<div>Icons made by <a href="https://www.flaticon.com/authors/madebyoliver" title="Madebyoliver">Madebyoliver</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div> node <script>document.write(process.versions.node)</script>,
</div> Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</div><!-- #settings --> </div><!-- #settings -->
<div id="portfolio" class="panel"> <div id="portfolio" class="panel">
@ -98,10 +97,6 @@
<div id="portfolio-total-value">Total Value: <span class="value"></span></div> <div id="portfolio-total-value">Total Value: <span class="value"></span></div>
<div class="chart-container" style="position: relative; height:40vh; width:94vw">
<canvas id="portfolioChart" width="360" height="360"></canvas>
</div>
<!-- show what % each coin is of portfolio --> <!-- show what % each coin is of portfolio -->
<!-- Enter avg. purchase price for each coin --> <!-- Enter avg. purchase price for each coin -->
@ -112,9 +107,8 @@
<script> <script>
// You can also require other files to run in this process // You can also require other files to run in this process
require('./renderer.js') //require('./renderer.js')
</script> </script>
<script src="js/app_common.js"></script> <script src="js/app_common.js"></script>
<script src="js/html.sortable.min.js"></script> <script src="js/html.sortable.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
</html> </html>

10
js/Chart.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,470 +1,482 @@
/****************** /******************
* APP FUNCTIONALITY * APP FUNCTIONALITY
******************/ ******************/
//access electron from here //access electron from here
const remote = require('electron').remote; const remote = require("electron").remote;
//user settings //user settings
const settings = require('electron-settings'); const settings = require("electron-settings");
settings.set('developer', {
first: 'Nathan',
last: 'Parikh'
});
//default coins
if(settings.has('user.coins')) {
//do nothing because coins already set
}
else {
settings.set('user', {
coins: 'BTC,ETH,LTC'
});
}
//default base currency
if(settings.has('user.currency')) {
//do nothing because currency already set
}
else {
settings.set('user.currency', 'USD');
}
(function() { //default coins
if (settings.has("user.coins")) {
//do nothing because coins already set
} else {
settings.set("user", {
coins: ["BTC", "ETH", "LTC"],
});
}
//default base currency
if (settings.has("user.currency")) {
//do nothing because currency already set
} else {
settings.set("user.currency", "USD");
}
function loadJSON(callback) { /* Base Currency */
var file = 'https://www.cryptocompare.com/api/data/coinlist/'; base = settings.get("user.currency"); // get the user's base currency
var xobj = new XMLHttpRequest(); var currSel = document.getElementById("base"); //select the currency select box
xobj.overrideMimeType("application/json"); currSel.value = settings.get("user.currency"); //select the option that corresponds to the user's currency
xobj.open('GET', file, true); setBase = function () {
xobj.onreadystatechange = function () { //selected base currency
if (xobj.readyState == 4 && xobj.status == "200") { var sel = document.getElementById("base");
// Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode var x = sel.selectedIndex;
callback(xobj.responseText); var y = sel.options;
} base = y[x].text;
}; settings.set("user.currency", base); //save the user's selection
xobj.send(null); updateData(); //immediately reflect the changed currency
} //loadJSON };
// Generate the list of all coins
loadJSON(function(response) {
// Parse JSON string into object
var myDiv = document.getElementById("coinlist");
var actual_JSON = JSON.parse(response);
//alert(settings.get('user.coins'));
//console.log(actual_JSON.Data);
//loop through data, get coin info, generate checkbox for each coin
Object.keys(actual_JSON.Data).forEach(function(key) {
//console.log(actual_JSON.Data[key].Name);
//console.log(actual_JSON.Data[key].CoinName);
var li = document.createElement("li");
var checkBox = document.createElement("input");
checkBox.className = "coinCode";
var label = document.createElement("label");
label.className = "coinName";
var div = document.createElement("div");
checkBox.type = "checkbox";
checkBox.value = actual_JSON.Data[key].Name;
checkBox.name = "cl[]";
//check the coins the user has already set
var str = String(settings.get('user.coins'));
var split_str = str.split(",");
if (split_str.indexOf(actual_JSON.Data[key].Name) !== -1) {
checkBox.checked = true;
}
myDiv.appendChild(li);
li.appendChild(checkBox);
li.appendChild(label);
label.appendChild(document.createTextNode(actual_JSON.Data[key].CoinName));
label.appendChild(document.createTextNode(' ('+actual_JSON.Data[key].Name+')'));
label.appendChild(div);
}); //forEach
}); //loadJSON
base = settings.get('user.currency'); // get the user's base currency
var currSel = document.getElementById('base'); //select the currency select box
currSel.value = settings.get('user.currency'); //select the option that corresponds to the user's currency
setBase = function() {
//selected base currency
var sel = document.getElementById('base');
var x = sel.selectedIndex;
var y = sel.options;
base = y[x].text;
settings.set('user.currency', base); //save the user's selection
updateData(); //immediately reflect the changed currency
};
})();
//Functions for creating/appending elements //Functions for creating/appending elements
function createNode(element) { function createNode(element) {
return document.createElement(element); return document.createElement(element);
} }
function append(parent, el) { function append(parent, el) {
return parent.appendChild(el); return parent.appendChild(el);
} }
const ul = document.getElementById("prices"); // Get the list where we will place coins
// Returns an array with values of the selected (checked) checkboxes in "frm" const portfolio_ul = document.getElementById("portfolio-list");
function getSelectedChbox(frm) { var url =
var selchbox = []; // array that will store the value of selected checkboxes "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=" +
// gets all the input tags in frm, and their number settings.get("user.coins") +
var inpfields = frm.getElementsByTagName('input'); "&tsyms=" +
var nr_inpfields = inpfields.length; base +
// traverse the inpfields elements, and adds the value of selected (checked) checkbox in selchbox "&extraParams=crypto-price-widget";
for(var i=0; i<nr_inpfields; i++) {
if(inpfields[i].type == 'checkbox' && inpfields[i].checked == true) selchbox.push(inpfields[i].value);
}
return selchbox;
}
const ul = document.getElementById('prices'); // Get the list where we will place coins
const portfolio_ul = document.getElementById('portfolio-list');;
const url = 'https://min-api.cryptocompare.com/data/pricemultifull?fsyms='+settings.get('user.coins') +'&tsyms='+base +'&extraParams=crypto-price-widget';
var pinCheck = document.getElementById("pin-to-top"); var pinCheck = document.getElementById("pin-to-top");
function initData() { function clearData() {
fetch(url) ul.innerHTML = "";
.then( clearTimeout(appRefresh);
function(response) { }
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' + function initData() {
response.status); //need to redeclare the url variable here to grab the latest user coins, etc.
return; var url =
} "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=" +
settings.get("user.coins") +
"&tsyms=" +
base +
"&extraParams=crypto-price-widget";
fetch(url)
.then(
function (response) {
// Examine the response
response.json().then(function (data) {
//console.log(url);
let pricesDISPLAY = data.DISPLAY; // display for everything except coin symbol
let pricesRAW = data.RAW; // raw to get "BTC" instead of bitcoin symbol
// Examine the response
response.json().then(function(data) {
//console.log(data);
let prices = data.DISPLAY;
var i = 0; var i = 0;
for (let key of Object.keys(prices)) { for (let key of Object.keys(pricesDISPLAY)) {
let coin = prices[key]; let coin = pricesDISPLAY[key];
//console.log(coin); //console.log(coin);
let li = createNode('li'), let li = createNode("li"),
span = createNode('span'); span = createNode("span");
sym = createNode('span'); sym = createNode("span");
li.setAttribute("class", "price"); li.setAttribute("class", "price");
li.setAttribute("id", "coin-"+[key]); li.setAttribute("id", "coin-" + [key]);
//alert("coin-"+[key])
//console.log(settings.get('coin.'+[key]+'.order')); span.setAttribute("class", "draggable");
li.setAttribute("sortorder", settings.get(li.id+'.order'));
//alert(settings.get(li.id+'.order')); //when adding a new coin, default sortorder to 999
if (settings.get(li.id + ".order") == null) {
settings.set(li.id + ".order", 999);
li.setAttribute("sortorder", 999);
} else {
li.setAttribute("sortorder", settings.get(li.id + ".order"));
}
append(li, span); append(li, span);
append(ul, li); append(ul, li);
i++; i++;
} //for } //for
//console.log(data.RAW.BTC.USD.PRICE)
sortChildren(
document.getElementById('prices'),
function(li) { return +li.getAttribute('sortorder') }
);
sortChildren(
document.getElementById('portfolio-list'),
function(li) { return +li.getAttribute('sortorder') }
);
//sort your coins //sort your coins
sortable('#prices', { sortable("#prices", {
handle: 'span' handle: "span",
})[0].addEventListener('sortstop', function(e) { })[0].addEventListener("sortstop", function (e) {
// Declare variables // Declare variables
var ul, ulPortfolio, li, liPortfolio, i; var ul, ulPortfolio, li, liPortfolio, i;
ul = document.getElementById("prices"); ul = document.getElementById("prices");
ulPortfolio = document.getElementById("portfolio-list"); ulPortfolio = document.getElementById("portfolio-list");
li = ul.getElementsByTagName('li'); li = ul.getElementsByTagName("li");
liPortfolio = ulPortfolio.getElementsByTagName('li'); liPortfolio = ulPortfolio.getElementsByTagName("li");
// Loop through all list items // Loop through all list items
for (i = 0; i < li.length; i++) { for (i = 0; i < li.length; i++) {
li[i].setAttribute("sortorder", i); li[i].setAttribute("sortorder", i);
var elementID = li[i].id; var elementID = li[i].id;
//alert(elementID); //alert(elementID);
settings.set(elementID, { // coin-BTC settings.set(elementID, {
order: li[i].getAttribute('sortorder') // coin-BTC
order: li[i].getAttribute("sortorder"),
}); });
//alert(settings.get(elementID + '.order')); //alert(settings.get(elementID + '.order'));
} //for } //for
//alert(settings.get('coin.'+e+'.order')); //alert(settings.get('coin.'+e+'.order'));
}); //sortable }); //sortable
//Pin to Top - settings check - immediately set checkbox and window to saved state
if (settings.get("user.pinToTop") == "yes") {
pinCheck.checked = true;
remote.getCurrentWindow().setAlwaysOnTop(true);
} else {
pinCheck.checked = false;
remote.getCurrentWindow().setAlwaysOnTop(false);
}
sortChildren(document.getElementById("prices"), function (li) {
return +li.getAttribute("sortorder");
});
sortChildren(document.getElementById("portfolio-list"), function (
li
) {
return +li.getAttribute("sortorder");
});
}); //response.json }); //response.json
updateData();
} //function(response) } //function(response)
) //.then ) //.then
.catch(function(err) { .catch(function (err) {
console.log('Fetch Error :-S', err); console.log("Unable to connect!");
}); var mainDiv = document.getElementById("main");
updateData(); var errorDiv = document.createElement("div");
} errorDiv.className = "error";
errorDiv.innerHTML =
'<h2>Uh-oh! Looks like you&#39;re offline.</h2>\
<img src="images/offline_doge.jpg" />\
<h4>Reconnect, then reload the app.</h4>\
<button type="button" class="refresh" onClick="location.reload(false);" >Reload</button>';
document.getElementById("main").appendChild(errorDiv);
}); //catch
} //initData
function updateData() { function updateData() {
//console.log(settings.get('user.coins')); //need to redeclare the url variable here to grab the latest user coins, etc.
const url = 'https://min-api.cryptocompare.com/data/pricemultifull?fsyms='+settings.get('user.coins') +'&tsyms='+base +'&extraParams=crypto-price-widget'; var url =
fetch(url) "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=" +
.then( settings.get("user.coins") +
function(response) { "&tsyms=" +
if (response.status !== 200) { base +
console.log('Looks like there was a problem. Status Code: ' + "&extraParams=crypto-price-widget";
response.status); /*
return; ** What data needs to be grabbed/changed?
** Base currency
** Coin price
** % change
** Portfolio - Coin price affects current value / total
*/
//console.log(settings.get('user.coins'));
fetch(url).then(
function (response) {
// Examine the text in the response
response.json().then(function (data) {
let pricesDISPLAY = data.DISPLAY; // display for everything except coin symbol
let pricesRAW = data.RAW; // raw to get "BTC" instead of bitcoin symbol
let portfolioSum = 0;
for (let key of Object.keys(pricesRAW)) {
let coinDISPLAY = pricesDISPLAY[key];
let coinDISPLAYchange = coinDISPLAY[base].CHANGEPCT24HOUR;
let coinRAW = pricesRAW[key];
//console.log(coinDISPLAY);
let li = document.getElementById("coin-" + [key]),
span = document.querySelector("#coin-" + [key] + " span");
let coinSymbol = coinRAW[base].FROMSYMBOL;
let coinRate = coinDISPLAY[base].PRICE.replace(/ /g, ""); //.replace(/ /g,'') removes space after $
//replace currencies that have no symbols with easier to read formats
if (coinRate.includes("AUD")) {
coinRate = coinRate.replace("AUD", "A$");
}
if (coinRate.includes("CAD")) {
coinRate = coinRate.replace("CAD", "C$");
}
if (coinRate.includes("HKD")) {
coinRate = coinRate.replace("HKD", "HK$");
}
if (coinRate.includes("MXN")) {
coinRate = coinRate.replace("MXN", "$");
}
if (coinRate.includes("NOK")) {
coinRate = coinRate.replace("NOK", "kr");
}
if (coinRate.includes("NZD")) {
coinRate = coinRate.replace("NZD", "NZ$");
}
if (coinRate.includes("SEK")) {
coinRate = coinRate.replace("SEK", "kr");
}
if (coinRate.includes("SGD")) {
coinRate = coinRate.replace("SGD", "S$");
}
if (coinRate.includes("TRY")) {
coinRate = coinRate.replace("TRY", "₺");
}
if (coinRate.includes("ZAR")) {
coinRate = coinRate.replace("ZAR", "R");
} }
// Examine the text in the response
response.json().then(function(data) {
let pricesDISPLAY = data.DISPLAY; // display for everything except coin symbol
let pricesRAW = data.RAW; // raw to get BTC instead of bitcoin symbol
let portfolioSum = 0;
// Chart labels //console.log(span);
var chartLabels = []; span.innerHTML =
// Chart data '<span class="sym">' +
var chartData = []; coinSymbol +
// Chart colors - need to match these colors to the coin in a future release "</span> " +
var chartColors = [ coinRate +
'#FF9F1C', '<span class="change">' +
'#2EC4B6', coinDISPLAYchange +
'#E71D36', "%</span>";
'#011627',
'#FDFFFC',
'#D31EE8',
'#0288D1',
'#5FC42D',
'#E64A19',
'#0097A7',
'#FBC02D',
'#00796B',
'#388E3C',
'#689F38',
'#303F9F',
'#C2185B',
'#FFA000',
'#D32F2F',
'#C2185B',
'#fff'
];
//randomize
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle... //Price Alert Test - PRO Feature
while (0 !== currentIndex) { /*
* Choose crypto
* Choose price
* Choose equals, greater than, or less than price
* Alert set to "on"
* Alert when matches conditions
* When click on notification, alert set to "off"
* Use electron settings, localStorage, or sessionStorage?
* Should this be included in the updateData or separate?
*/
// Pick a remaining element... /*
randomIndex = Math.floor(Math.random() * currentIndex); var alerted = localStorage.getItem('alerted') || '';
currentIndex -= 1; if(coinSymbol.includes("BTC") && coinRAW[base].PRICE >= "5723" && alerted != 'yes') {
let notif = new window.Notification('Price Alert', {
// And swap it with the current element. body: "BTC has gone above 5790!"
temporaryValue = array[currentIndex]; });
array[currentIndex] = array[randomIndex]; notif.onclick = () => {
array[randomIndex] = temporaryValue; //so it doesn't keep notifying us every 3 seconds.
localStorage.setItem('alerted','yes');
}
} }
*/
return array; // % Change
} let change = document.querySelector("#coin-" + [key] + " .change");
if (coinDISPLAYchange > 0) {
change.className += " positive";
change.classList.remove("negative");
} else if (coinDISPLAYchange < 0) {
change.className += " negative";
change.classList.remove("postive");
} else {
change.classList.remove("postive");
change.classList.remove("negative");
}
for (let key of Object.keys(pricesRAW)) { // Portfolio
let coinDISPLAY = pricesDISPLAY[key]; let quantityValue = document.querySelector(
let coinDISPLAYchange = coinDISPLAY[base].CHANGEPCT24HOUR; "#coin-" + [key] + " .quantity-value"
let coinRAW = pricesRAW[key]; );
//console.log(coinDISPLAY); let quantityNumber = settings.get("quantity." + [key]);
let li = document.getElementById("coin-"+[key]), let regp = /[^0-9.-]+/g;
span = document.querySelector("#coin-"+[key]+" span"); if (quantityNumber != null) {
span.setAttribute("class", "draggable"); quantityTotal =
parseFloat(coinRate.replace(regp, "")) *
let coinSymbol = coinRAW[base].FROMSYMBOL; parseFloat(quantityNumber.replace(regp, ""));
let coinRate = coinDISPLAY[base].PRICE.replace(/ /g,''); //.replace(/ /g,'') removes space after $ }
// sum of all total coin values
//replace currencies that have no symbols with easier to read formats portfolioSum += quantityTotal;
if(coinRate.includes("AUD")) { coinRate = coinRate.replace("AUD", "A$"); } // put sum into the markup
if(coinRate.includes("CAD")) { coinRate = coinRate.replace("CAD", "C$"); } let portfolioTotalValue = document.querySelector(
if(coinRate.includes("HKD")) { coinRate = coinRate.replace("HKD", "HK$"); } "#portfolio-total-value .value"
if(coinRate.includes("MXN")) { coinRate = coinRate.replace("MXN", "$"); }
if(coinRate.includes("NOK")) { coinRate = coinRate.replace("NOK", "kr"); }
if(coinRate.includes("NZD")) { coinRate = coinRate.replace("NZD", "NZ$"); }
if(coinRate.includes("SEK")) { coinRate = coinRate.replace("SEK", "kr"); }
if(coinRate.includes("SGD")) { coinRate = coinRate.replace("SGD", "S$"); }
if(coinRate.includes("TRY")) { coinRate = coinRate.replace("TRY", "₺"); }
if(coinRate.includes("ZAR")) { coinRate = coinRate.replace("ZAR", "R"); }
//console.log(span);
span.innerHTML = '<span class="sym">' + coinSymbol + '</span> ' + coinRate + '<span class="change">' + coinDISPLAYchange + '%</span>';
// % Change
let change = document.querySelector("#coin-"+[key]+" .change");
if(coinDISPLAYchange > 0) {
change.className += " positive";
change.classList.remove("negative");
}
else if(coinDISPLAYchange < 0) {
change.className += " negative";
change.classList.remove("postive");
}
else {
change.classList.remove("postive");
change.classList.remove("negative");
}
// Portfolio
let quantityValue = document.querySelector("#coin-"+[key]+" .quantity-value");
let quantityNumber = settings.get('quantity.'+[key]);
let regp = /[^0-9.-]+/g;
let quantityTotal = parseFloat(coinRate.replace(regp, '')) * parseFloat(quantityNumber.replace(regp, ''));
// sum of all total coin values
portfolioSum += quantityTotal;
// put sum into the markup
let portfolioTotalValue = document.querySelector("#portfolio-total-value .value");
// total value for each coin
if(coinRate.includes("Ƀ")) {
//because BTC has 8 decimal places
quantityValue.innerHTML = quantityTotal.toFixed(8);
portfolioTotalValue.innerHTML = portfolioSum.toFixed(8);
}
else {
//standard currency format
quantityValue.innerHTML = quantityTotal.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
portfolioTotalValue.innerHTML = portfolioSum.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
}
// Chart labels
chartLabels.push(key);
// Chart data
chartData.push(quantityTotal);
} //for
sortChildren(
document.getElementById('portfolio-list'),
function(li) { return +li.getAttribute('sortorder') }
); );
var newChartLabels = chartLabels; // total value for each coin
if (coinRate.includes("Ƀ")) {
// Chart //because BTC has 8 decimal places
var ctx = document.getElementById("portfolioChart"); quantityValue.innerHTML = quantityTotal.toFixed(8);
var myChart = new Chart(ctx, { portfolioTotalValue.innerHTML = portfolioSum.toFixed(8);
type: 'doughnut', } else if (quantityValue != null) {
data: { //standard currency format
datasets: [{ quantityValue.innerHTML = quantityTotal
data: chartData, .toFixed(2)
backgroundColor: chartColors, .replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
borderColor: '#000', portfolioTotalValue.innerHTML = portfolioSum
borderWidth: 0 .toFixed(2)
}], .replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
}
labels: newChartLabels } //for
}, }); //response.json().then
options: { } //function(response)
animation : false, ); //then
responsive: false, appRefresh = setTimeout(function () {
maintainAspectRatio: true, updateData();
legend : { }, 5000); // run this once every 5 seconds
position: 'bottom' } //updateData()
}
}
}); //myChart
//Pin to Top - settings check - immediately set checkbox and window to saved state
if(settings.get('user.pinToTop') == 'yes') {
pinCheck.checked = true;
remote.getCurrentWindow().setAlwaysOnTop(true);
} else {
pinCheck.checked = false;
remote.getCurrentWindow().setAlwaysOnTop(false);
}
}); //then
}
)
setTimeout(function(){updateData()}, 5000); // run this once every 5 seconds
}
// Let's do this thing! // Let's do this thing!
initData(); initData();
/* Test this function */
//document.getElementById('firstname').innerHTML = settings.get('user.coins');
// Click on #saveCoins, save the coin selection to the user // Click on #saveCoins, save the coin selection to the user
document.getElementById('saveCoins').onclick = function(){ document.getElementById("saveCoins").onclick = function () {
var coinForm = document.getElementById('coinlist'); var coinForm = document.getElementById("coinlist");
var selchb = getSelectedChbox(coinForm); // gets the array returned by getSelectedChbox() var selchb = getSelectedChbox(coinForm); // gets the array returned by getSelectedChbox()
//alert(selchb); settings.set("user.coins", selchb);
settings.set('user.coins', selchb); //clear and reload
clearData();
// just reloading the entire app because I have yet to figure out how to add/remove a coin from the primary list without a page reload initData();
location.reload(false); };
//alert(settings.get('user.currency'));
}
/*********** /***********
* PORTFOLIO * PORTFOLIO
***********/ ***********/
var portfolio_list_container = document.querySelector('#portfolio-list'); var portfolio_list_container = document.querySelector("#portfolio-list");
var portfolio_list = settings.get('user.coins'); var portfolio_list = settings.get("user.coins");
//generate html from list of coins //generate html from list of coins
for (let key of Object.keys(portfolio_list)) { for (let key of Object.keys(portfolio_list)) {
let coin = portfolio_list[key]; let coin = portfolio_list[key];
//console.log(coin); //console.log(coin);
let li = createNode('li'), let li = createNode("li"),
span = createNode('span'); span = createNode("span");
sym = createNode('span'); sym = createNode("span");
li.setAttribute("id", "coin-"+[coin]); li.setAttribute("id", "coin-" + [coin]);
li.setAttribute("sortorder", settings.get(li.id+'.order')); li.setAttribute("sortorder", settings.get(li.id + ".order"));
append(li, span); append(li, span);
append(portfolio_ul, li); append(portfolio_ul, li);
if (settings.has('quantity.'+[coin])) { if (settings.has("quantity." + [coin])) {
inputValue = settings.get('quantity.'+[coin]); inputValue = settings.get("quantity." + [coin]);
} } else {
else { inputValue = "0";
inputValue = '0'; settings.set("quantity." + [coin], "0");
inputValue = settings.set('quantity.'+[coin], '0');
} }
span.innerHTML = '<span class="sym">' + coin + '</span> <span class="block quantity"><label for="quantity.' + coin +'">Quantity</label> <input type="number" name="quantity.' + coin +'" min="0" value="'+inputValue+'" step=".01"></span> <span class="block value"><label>Current Value</label><span class="quantity-value"></span></span>'; span.innerHTML =
'<span class="sym">' +
coin +
'</span> <span class="block quantity"><label for="quantity.' +
coin +
'">Quantity</label> <input type="number" name="quantity.' +
coin +
'" min="0" value="' +
inputValue +
'" step=".01"></span> <span class="block value"><label>Current Value</label><span class="quantity-value"></span></span>';
i++; i++;
} //for } //for
// save quantities // save quantities
document.getElementById('saveQuantities').onclick = function(){ document.getElementById("saveQuantities").onclick = function () {
var items = portfolio_ul.getElementsByTagName("input"); var items = portfolio_ul.getElementsByTagName("input");
for (var i = 0; i < items.length; ++i) { for (var i = 0; i < items.length; ++i) {
// do something with items[i], which is a <li> element // do something with items[i], which is a <li> element
inputName = items[i].getAttribute("name"); inputName = items[i].getAttribute("name");
inputValue = items[i].value; inputValue = items[i].value;
//console.log(inputValue); //console.log(inputValue);
settings.set(inputName, inputValue); settings.set(inputName, inputValue);
} }
// just reloading the entire app because I have yet to figure out how to add/remove a coin from the primary list without a page reload // just reloading the entire app because I have yet to figure out how to add/remove a coin from the primary list without a page reload
//location.reload(false); //location.reload(false);
};
/***********
* SETTINGS
***********/
// Settings - list of coins
function loadJSON(callback) {
//Stored local version of https://www.cryptocompare.com/api/data/coinlist/ for performance
var file = "./coinlist.json";
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open("GET", file, true);
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
// Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
callback(xobj.responseText);
}
};
xobj.send(null);
} //loadJSON
// Generate the list of all coins
loadJSON(function (response) {
// Parse JSON string into object
var myDiv = document.getElementById("coinlist");
var actual_JSON = JSON.parse(response);
//alert(settings.get('user.coins'));
//console.log(actual_JSON.Data);
//loop through data, get coin info, generate checkbox for each coin
Object.keys(actual_JSON.Data).forEach(function (key) {
//console.log(actual_JSON.Data[key].Name);
//console.log(actual_JSON.Data[key].CoinName);
var li = document.createElement("li");
var checkBox = document.createElement("input");
checkBox.className = "coinCode";
var label = document.createElement("label");
label.className = "coinName";
var div = document.createElement("div");
checkBox.type = "checkbox";
checkBox.value = actual_JSON.Data[key].Name;
checkBox.id = actual_JSON.Data[key].Name;
label.htmlFor = actual_JSON.Data[key].Name;
checkBox.name = "cl[]";
//check the coins the user has already set
var str = String(settings.get("user.coins"));
var split_str = str.split(",");
if (split_str.indexOf(actual_JSON.Data[key].Name) !== -1) {
checkBox.checked = true;
}
myDiv.appendChild(li);
li.appendChild(checkBox);
li.appendChild(label);
label.appendChild(document.createTextNode(actual_JSON.Data[key].CoinName));
label.appendChild(
document.createTextNode(" (" + actual_JSON.Data[key].Name + ")")
);
label.appendChild(div);
}); //forEach
}); //loadJSON
// Returns an array with values of the selected (checked) checkboxes in "frm"
function getSelectedChbox(frm) {
var selchbox = []; // array that will store the value of selected checkboxes
// gets all the input tags in frm, and their number
var inpfields = frm.getElementsByTagName("input");
var nr_inpfields = inpfields.length;
// traverse the inpfields elements, and adds the value of selected (checked) checkbox in selchbox
for (var i = 0; i < nr_inpfields; i++) {
if (inpfields[i].type == "checkbox" && inpfields[i].checked == true)
selchbox.push(inpfields[i].value);
}
return selchbox;
} }
/*********** /***********
* PIN TO TOP * PIN TO TOP
*************/ *************/
pinCheck.onclick = function(event) { pinCheck.onclick = function (event) {
var window = remote.getCurrentWindow(); var window = remote.getCurrentWindow();
var checkbox = event.target; var checkbox = event.target;
if(checkbox.checked) { if (checkbox.checked) {
//Checkbox has been checked //Checkbox has been checked
window.setAlwaysOnTop(true); //immediately make the change to the window window.setAlwaysOnTop(true); //immediately make the change to the window
settings.set('user.pinToTop', 'yes'); settings.set("user.pinToTop", "yes");
} else { } else {
//Checkbox has been unchecked //Checkbox has been unchecked
window.setAlwaysOnTop(false); window.setAlwaysOnTop(false);
settings.set('user.pinToTop', 'no'); settings.set("user.pinToTop", "no");
} }
}; };
/******* /*******
* APP UI * APP UI
********/ ********/
//Window controls //Window controls
document.getElementById("close-btn").addEventListener("click", function (e) { document.getElementById("close-btn").addEventListener("click", function (e) {
@ -473,44 +485,44 @@ document.getElementById("close-btn").addEventListener("click", function (e) {
}); });
document.getElementById("min-btn").addEventListener("click", function (e) { document.getElementById("min-btn").addEventListener("click", function (e) {
var window = remote.getCurrentWindow(); var window = remote.getCurrentWindow();
window.minimize(); window.minimize();
}); });
//Panel tabs //Panel tabs
var tabLinks = document.querySelectorAll('.tabs button'); var tabLinks = document.querySelectorAll(".tabs button");
for (var i = 0; i < tabLinks.length; i++) { for (var i = 0; i < tabLinks.length; i++) {
tabLinks[i].onclick = function() { tabLinks[i].onclick = function () {
var target = this.getAttribute('href').replace('#', ''); var target = this.getAttribute("href").replace("#", "");
var sections = document.querySelectorAll('.panel'); var sections = document.querySelectorAll(".panel");
for(var j=0; j < sections.length; j++) { for (var j = 0; j < sections.length; j++) {
sections[j].style.display = 'none'; sections[j].style.display = "none";
}
document.getElementById(target).style.display = 'block';
for(var k=0; k < tabLinks.length; k++) {
tabLinks[k].removeAttribute('class');
} }
this.setAttribute('class', 'active'); document.getElementById(target).style.display = "block";
for (var k = 0; k < tabLinks.length; k++) {
tabLinks[k].removeAttribute("class");
}
this.setAttribute("class", "active");
return false; return false;
} };
}; }
//Coin search filter //Coin search filter
function myFunction() { function myFunction() {
// Declare variables // Declare variables
var input, filter, ul, li, a, i; var input, filter, ul, li, a, i;
input = document.getElementById('myInput'); input = document.getElementById("myInput");
filter = input.value.toUpperCase(); filter = input.value.toUpperCase();
ul = document.getElementById("coinlist"); ul = document.getElementById("coinlist");
li = ul.getElementsByTagName('li'); li = ul.getElementsByTagName("li");
// Loop through all list items, and hide those who don't match the search query // Loop through all list items, and hide those who don't match the search query
for (i = 0; i < li.length; i++) { for (i = 0; i < li.length; i++) {
label = li[i].getElementsByTagName("label")[0]; label = li[i].getElementsByTagName("label")[0];
checkbox = li[i].getElementsByTagName("input")[0].value; checkbox = li[i].getElementsByTagName("input")[0].value;
if (label.innerHTML.toUpperCase().indexOf(filter) > -1) { if (label.innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = ""; li[i].style.display = "";
} else { } else {
li[i].style.display = "none"; li[i].style.display = "none";
} }
} //for } //for
} //myFunction } //myFunction
@ -518,16 +530,20 @@ function myFunction() {
//sort by attribute //sort by attribute
function sortChildren(wrap, f, isNum) { function sortChildren(wrap, f, isNum) {
var l = wrap.children.length, var l = wrap.children.length,
arr = new Array(l); arr = new Array(l);
for(var i=0; i<l; ++i) for (var i = 0; i < l; ++i) arr[i] = [f(wrap.children[i]), wrap.children[i]];
arr[i] = [f(wrap.children[i]), wrap.children[i]]; arr.sort(
arr.sort(isNum isNum
? function(a,b){ return a[0]-b[0]; } ? function (a, b) {
: function(a,b){ return a[0]<b[0] ? -1 : a[0]>b[0] ? 1 : 0; } return a[0] - b[0];
}
: function (a, b) {
return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0;
}
); );
var par = wrap.parentNode, var par = wrap.parentNode,
ref = wrap.nextSibling; ref = wrap.nextSibling;
par.removeChild(wrap); par.removeChild(wrap);
for(var i=0; i<l; ++i) wrap.appendChild(arr[i][1]); for (var i = 0; i < l; ++i) wrap.appendChild(arr[i][1]);
par.insertBefore(wrap, ref); par.insertBefore(wrap, ref);
} //sortChildren } //sortChildren

73
main.js
View File

@ -1,29 +1,27 @@
const electron = require('electron') const electron = require("electron");
// Module to control application life. // app control, application life.BrowserWindow creates native browser window.
const app = electron.app const { app, BrowserWindow } = require("electron");
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow
//Store Window size and position //Store Window size and position
const windowStateKeeper = require('electron-window-state'); const windowStateKeeper = require("electron-window-state");
const path = require("path");
const url = require("url");
const path = require('path') const settings = require("electron-settings");
const url = require('url')
const settings = require('electron-settings');
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow = null;
function createWindow () { function createWindow() {
// Load the previous state with fallback to defaults // Load the previous state with fallback to defaults
let mainWindowState = windowStateKeeper({ let mainWindowState = windowStateKeeper({
defaultWidth: 320, defaultWidth: 320,
defaultHeight: 240 defaultHeight: 240,
}); });
// Create the browser window. // Create the browser window.
mainWindow = new electron.BrowserWindow({ mainWindow = new BrowserWindow({
title: app.getName(), title: app.getName(),
alwaysOnTop: false, alwaysOnTop: false,
//show: false, //show: false,
@ -31,16 +29,19 @@ function createWindow () {
y: mainWindowState.y, y: mainWindowState.y,
width: mainWindowState.width, width: mainWindowState.width,
height: mainWindowState.height, height: mainWindowState.height,
maxWidth: 360, maxWidth: 960,
minWidth: 280, minWidth: 290,
minHeight: 100, minHeight: 100,
maximizable: false, maximizable: false,
fullscreenable: false, fullscreenable: false,
frame: false, frame: false,
titleBarStyle: 'customButtonsOnHover', titleBarStyle: "customButtonsOnHover",
autoHideMenuBar: true, autoHideMenuBar: true,
transparent: true, transparent: true,
icon: 'images/icon.png' icon: path.join(__dirname, "images/icon.png"),
webPreferences: {
nodeIntegration: true,
},
}); });
// Let us register listeners on the window, so we can update the state // Let us register listeners on the window, so we can update the state
@ -49,45 +50,47 @@ function createWindow () {
mainWindowState.manage(mainWindow); mainWindowState.manage(mainWindow);
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadURL(url.format({ mainWindow.loadURL(
pathname: path.join(__dirname, 'index.html'), url.format({
protocol: 'file:', pathname: path.join(__dirname, "index.html"),
slashes: true protocol: "file:",
})) slashes: true,
})
);
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on("closed", function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null;
}) });
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.on('ready', createWindow) app.on("ready", createWindow);
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on("window-all-closed", function () {
// On OS X it is common for applications and their menu bar // On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== "darwin") {
app.quit() app.quit();
} }
}) });
app.on('activate', function () { app.on("activate", function () {
// On OS X it's common to re-create a window in the app when the // On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow();
} }
}) });
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

10800
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
{ {
"name": "crypto-price-widget", "name": "crypto-price-widget",
"productName": "Crypto Price Widget", "productName": "Crypto Price Widget",
"version": "1.1.0", "version": "1.4.0",
"description": "A cross-platform app for tracking Crypto prices", "description": "A cross-platform app for tracking Crypto prices",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
"start": "electron .", "start": "electron .",
"build": "node build.js", "build": "node build.js",
"package-mac": "electron-packager . --overwrite --platform=darwin --arch=x64 --icon=images/icon.icns --prune=true --out=release-builds", "package-mac": "electron-packager . --overwrite --platform=darwin --arch=x64 --icon=images/icon.icns --prune=true --out=release-builds",
"package-win": "electron-packager . --overwrite --asar=true --platform=win32 --arch=ia32 --icon=images/icon_win.ico --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"Crypto Price Widget\"", "package-win": "electron-packager . --overwrite --platform=win32 --arch=x64 --icon=images/icon_win.ico --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"Crypto Price Widget\"",
"package-linux": "electron-packager . --overwrite --platform=linux --arch=x64 --icon=images/icon.png --prune=true --out=release-builds" "package-linux": "electron-packager . --overwrite --platform=linux --arch=x64 --icon=images/icon.png --prune=true --out=release-builds"
}, },
"repository": "https://github.com/nathanp/crypto-price-widget", "repository": "https://github.com/nathanp/crypto-price-widget",
@ -22,18 +22,19 @@
"author": "Nathan Parikh", "author": "Nathan Parikh",
"license": "CC0-1.0", "license": "CC0-1.0",
"devDependencies": { "devDependencies": {
"electron": "~1.6.2", "electron": "^9.0.4",
"electron-packager": "^8.7.2" "electron-packager": "^14.2.1",
"electron-winstaller": "^4.0.0"
}, },
"dependencies": { "dependencies": {
"ava": "^0.15.2", "ava": "^3.8.2",
"cryptocurrencies": "^1.0.0", "cryptocurrencies": "^7.0.0",
"electron-settings": "^3.1.1", "electron-settings": "^3.2.0",
"electron-window-state": "^4.1.1", "electron-window-state": "^5.0.3",
"html5sortable": "^0.6.1", "html5sortable": "^0.9.17",
"isomorphic-fetch": "^2.2.1", "isomorphic-fetch": "^2.2.1",
"lodash.sortby": "^4.7.0", "lodash.sortby": "^4.7.0",
"sortablejs": "^1.6.0", "sortablejs": "^1.10.2",
"xo": "^0.16.0" "xo": "^0.32.0"
} }
} }

View File

@ -1,3 +1,9 @@
// This file is required by the index.html file and will // This file is required by the index.html file and will
// be executed in the renderer process for that window. // be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process. // All of the Node.js APIs are available in this process.
// Do this from the renderer process
/*
var notif = new window.Notification('Download Complete', {
body: "yolo"
})
*/