diff --git a/README.md b/README.md
index 8c93839..556fff8 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,9 @@
-I hope one day this will be a useful jinteki.net extension.
+This is an extension for the jinteki.net website.
-Currently it maintains a list of friends (or cyber-celebrities ;-) ) online and pins links to their running games to the top of the screen.
+Features:
-Once I've got a couple of dummy icons, and made it look less crap, I shall be releasing this in the Chrome App Store.
+* maintains a list of friends (or cyber-celebrities ;-) ) online
+* pins links to friends games in progress to the top of the lobby.
+* introduces a fixes panel in-game. This panel serves as a series of shortcuts for the jinteki.net [commands list](http://www.jinteki.net/help#commands).
[Trello Board for Janteki](https://trello.com/b/sJSYgy2m/jankteki)
diff --git a/inline/gameboard.js b/inline/gameboard.js
new file mode 100644
index 0000000..72dd89e
--- /dev/null
+++ b/inline/gameboard.js
@@ -0,0 +1,97 @@
+var socket = io.connect(iourl + '/lobby');
+
+var observer = new MutationObserver(function () {
+ if (document.querySelector('#gameboard').style.display !== "none") {
+ createFixesPanel();
+
+ var fixesPanel = document.querySelector('#fixes-pane .panel');
+
+ var buttons = [
+ {text: 'Draw n cards', command: 'draw', prompt: 'How many to draw?'},
+ {text: 'Adjust credits', command: 'credit', prompt: 'How many credits?'},
+ {text: 'Adjust clicks', command: 'click', prompt: 'How many clicks?'},
+ {text: 'Adjust memory', command: 'memory', prompt: 'How much memory?', side: 'runner'},
+ {text: 'Adjust tags', command: 'tag', prompt: 'How many tags?', side: 'runner'},
+ {text: 'Adjust bad publicity', command: 'bp', prompt: 'How much bad publicity?', side: 'corp'},
+ {text: 'Adjust link', command: 'link', prompt: 'How much link?', side: 'runner'},
+ {text: 'Adjust hand size', command: 'handsize', prompt: 'What is your handsize?'},
+ {text: 'Take meat damage', command: 'take-meat', prompt: 'How much meat damage?', side: 'runner'},
+ {text: 'Take net damage', command: 'take-net', prompt: 'How much net damage?', side: 'runner'},
+ {text: 'Take brain damage', command: 'take-brain', prompt: 'How much brain damage?', side: 'runner'},
+ {text: 'Discard card', command: 'discard', prompt: 'Which card?', which: true},
+ {text: 'Put card on deck', command: 'deck', prompt: 'Which card?', which: true},
+ {text: 'Initiate trace', command: 'trace', prompt: 'Base strength?', side: 'corp'},
+ {text: 'Close active prompt', command: 'close-prompt'},
+ {text: 'Start a Psi game', command: 'psi', 'side': 'corp'},
+ {text: 'End a run', command: 'end-run', 'side': 'corp'},
+ {text: 'Jack out', command: 'jack-out', 'side': 'runner'},
+ {text: 'Set card counters', command: 'counter', 'prompt': 'How many counters?'},
+ {text: 'Advance card', command: 'adv-counter', 'prompt': 'How many counters?', side: 'corp'},
+ {text: 'Debug card', command: 'card-info'}
+ ];
+
+ buttons.forEach((btn) => fixesPanel.appendChild(
+ createFixButton(btn)
+ ));
+ }
+});
+
+var gameBoard = document.querySelector('#gameboard');
+observer.observe(gameBoard, {childList: true});
+
+function createFixesPanel () {
+ if (!document.getElementById('fixes-pane')) {
+ var fixes = document.createElement('div');
+
+ fixes.className = getSide();
+ fixes.id = 'fixes-pane';
+ fixes.innerHTML = '
Fixes
';
+
+ var secondaryPane = document.querySelector('.secondary-pane'),
+ buttonPane = document.querySelector('.button-pane');
+
+ var buttonWrap = document.createElement('div');
+ buttonWrap.id = 'button-wrap';
+
+ buttonWrap.appendChild(fixes);
+
+ buttonWrap.insertBefore(buttonPane, fixes);
+
+ secondaryPane.appendChild(buttonWrap);
+
+ var expander = document.querySelector('#fixes-pane h4');
+ var panel = document.querySelector('#fixes-pane .panel');
+
+ expander.addEventListener('click',
+ () => panel.classList.toggle('expanded'));
+ }
+}
+
+function createFixButton (btn) {
+ var button = document.createElement('button');
+
+ button.innerHTML = btn.text;
+ button.className = 'side' in btn ? btn.side : '';
+
+ button.addEventListener('click', function () {
+ var n = btn.prompt ? prompt(btn.prompt) : '';
+ n = btn.which ? ' #' + n : ' ' + n;
+
+ socket.emit("netrunner", {
+ "action": "do",
+ "gameid": localStorage['gameid'],
+ "command": "say",
+ "side": getSide(),
+ "args": {
+ "user": user,
+ "text": "/" + btn.command + n
+ }
+ });
+ });
+
+ return button;
+}
+
+function getSide () {
+ return document.querySelector('.runner-board.opponent') ? 'corp' : 'runner';
+}
diff --git a/inline/injector.js b/inline/injector.js
new file mode 100644
index 0000000..939f7bd
--- /dev/null
+++ b/inline/injector.js
@@ -0,0 +1,6 @@
+var s = document.createElement('script');
+s.src = chrome.extension.getURL('inline/gameboard.js');
+s.onload = function() {
+ this.parentNode.removeChild(this);
+};
+(document.head || document.documentElement).appendChild(s);
diff --git a/inline/jankteki.css b/inline/jankteki.css
index 842351e..6cc7348 100644
--- a/inline/jankteki.css
+++ b/inline/jankteki.css
@@ -21,3 +21,50 @@
.friends-title {
margin-top: 10px;
}
+
+.gameboard #fixes-pane .panel {
+ overflow: scroll;
+}
+
+.gameboard #fixes-pane h4 {
+ margin-bottom: 10px;
+ text-align: center;
+}
+
+.gameboard #fixes-pane button {
+ font-size: 11px;
+ margin: 0 0 5px 0;
+ padding: 0 8px 1px;
+ width: 100%;
+}
+
+#fixes-pane .panel {
+ height: 28px;
+ margin-top: 5px;
+ transition: height 0.8s;
+}
+
+#fixes-pane .panel.expanded {
+ height: 150px;
+}
+
+#fixes-pane .panel h4 {
+ cursor: pointer;
+}
+
+#fixes-pane .panel h4 span::before {
+ color: #fff;
+ content: "▸ ";
+}
+
+#fixes-pane .panel.expanded h4 span::before {
+ content: "▾ ";
+}
+
+#fixes-pane.corp button.runner {
+ display: none;
+}
+
+#fixes-pane.runner button.corp {
+ display: none;
+}
diff --git a/inline/lobby.js b/inline/lobby.js
index 6b72215..2dc2b81 100644
--- a/inline/lobby.js
+++ b/inline/lobby.js
@@ -1,6 +1,6 @@
var friends = [];
-var observer = new MutationObserver(function() {
+var observer = new MutationObserver(function () {
if (document.querySelector('#gamelobby').style.display !== "none") {
chrome.storage.sync.get(['friends'], function (items) {
var pinned = getOrCreatePinned();
diff --git a/manifest.json b/manifest.json
index 523c275..90e0bde 100644
--- a/manifest.json
+++ b/manifest.json
@@ -3,7 +3,7 @@
"name": "Jankteki",
"description": "An enhancement suite for jinteki.net",
- "version": "0.3.0",
+ "version": "0.4.0",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
@@ -27,12 +27,12 @@
"matches": [
"http://www.jinteki.net/*"
],
- "js": ["inline/lobby.js"],
+ "js": ["inline/lobby.js", "inline/injector.js"],
"css": ["inline/jankteki.css"],
"run_at": "document_end"
}
],
-
+ "web_accessible_resources": ["inline/gameboard.js"],
"permissions": [
"contextMenus",
"declarativeContent",