diff --git a/public/index.html b/public/index.html
index 044e5ed..15e019a 100644
--- a/public/index.html
+++ b/public/index.html
@@ -6,9 +6,11 @@
IXVD - Home
+
+
diff --git a/public/obj/js/issues.js b/public/obj/js/issues.js
index 14b9a2b..b26504b 100644
--- a/public/obj/js/issues.js
+++ b/public/obj/js/issues.js
@@ -44,7 +44,7 @@ async function updateIssues() {
issueDiv.append(detailsDiv);
let titleSpan = document.createElement("a");
- titleSpan.href = issue.url;
+ titleSpan.href = issue.html_url;
titleSpan.classList.add("issue-title");
detailsDiv.append(titleSpan);
titleSpan.innerText = issue.title;
diff --git a/public/obj/js/keybinds.js b/public/obj/js/keybinds.js
new file mode 100644
index 0000000..6c4273f
--- /dev/null
+++ b/public/obj/js/keybinds.js
@@ -0,0 +1,94 @@
+const footerDiv = document.querySelector("#footer");
+const textSpan = footerDiv.querySelector("span");
+const originalText = footerDiv.cloneNode(true).innerHTML;
+
+let keyCombo = [];
+let keyComboTimeout;
+
+let quickFeatures = [
+ {
+ fn: () => {
+ textSpan.innerHTML = "such glitter, much glamour";
+ const duration = 15 * 1000,
+ animationEnd = Date.now() + duration,
+ defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };
+
+ function randomInRange(min, max) {
+ return Math.random() * (max - min) + min;
+ }
+
+ const interval = setInterval(function() {
+ const timeLeft = animationEnd - Date.now();
+
+ if (timeLeft <= 0) {
+ return clearInterval(interval);
+ }
+
+ const particleCount = 50 * (timeLeft / duration);
+
+ // since particles fall down, start a bit higher than random
+ confetti(
+ Object.assign({}, defaults, {
+ particleCount,
+ origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 },
+ })
+ );
+ confetti(
+ Object.assign({}, defaults, {
+ particleCount,
+ origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 },
+ })
+ );
+ }, 250);
+ },
+ combo: [
+ 'ArrowUp',
+ 'ArrowUp',
+ 'ArrowDown',
+ 'ArrowDown',
+ 'ArrowLeft',
+ 'ArrowRight',
+ 'ArrowLeft',
+ 'ArrowRight',
+ 'b',
+ 'a',
+ 'Enter'
+ ]
+ },
+ {
+ fn: () => { window.location.href = "//git.ixvd.net" },
+ combo: ["Control", "g"]
+ }
+]
+
+const clearKeyCombo = async () => {
+ keyCombo = [];
+ textSpan.innerHTML = originalText;
+ await (() => new Promise(res => setTimeout(res, 0)))();
+}
+
+const checkKeyCombo = () => {
+ let hits = 0;
+ // check if 1 key matches and if combo is complete;
+ quickFeatures.forEach(async (quickFeature) => {
+ if (quickFeature.combo.join('').startsWith(keyCombo.join(''))) hits = keyCombo.length;
+ if (quickFeature.combo.join('') === keyCombo.join('')) {
+ await clearKeyCombo();
+ quickFeature.fn();
+ }
+ });
+ if (hits === 0) clearKeyCombo().catch(e => console.error(e));
+}
+
+const keyComboHandler = (e) => {
+ if (e) {
+ if (e.key === 'Escape') return clearKeyCombo();
+ keyCombo.push(e.key);
+ textSpan.innerHTML = keyCombo.join(' ');
+ }
+ clearTimeout(keyComboTimeout);
+ keyComboTimeout = setTimeout(clearKeyCombo, 3000);
+ checkKeyCombo();
+}
+
+document.addEventListener('keydown', keyComboHandler);
\ No newline at end of file