Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
271194cc9e |
@@ -294,7 +294,6 @@
|
|||||||
<script src="~/js/casino/holdem/seatMenu.js?v=@ViewData["cssVersion"]"></script>
|
<script src="~/js/casino/holdem/seatMenu.js?v=@ViewData["cssVersion"]"></script>
|
||||||
<script src="~/js/casino/holdem/betting.js?v=@ViewData["cssVersion"]"></script>
|
<script src="~/js/casino/holdem/betting.js?v=@ViewData["cssVersion"]"></script>
|
||||||
<script src="~/js/casino/holdem/actionBar.js?v=@ViewData["cssVersion"]"></script>
|
<script src="~/js/casino/holdem/actionBar.js?v=@ViewData["cssVersion"]"></script>
|
||||||
<script src="~/js/casino/holdem/shortcuts.js?v=@ViewData["cssVersion"]"></script>
|
|
||||||
<script src="~/js/casino/holdem/potWizard.js?v=@ViewData["cssVersion"]"></script>
|
<script src="~/js/casino/holdem/potWizard.js?v=@ViewData["cssVersion"]"></script>
|
||||||
<script src="~/js/casino/holdem/handHistoryExport.js?v=@ViewData["cssVersion"]"></script>
|
<script src="~/js/casino/holdem/handHistoryExport.js?v=@ViewData["cssVersion"]"></script>
|
||||||
<script src="~/js/casino/holdem/main.js?v=@ViewData["cssVersion"]"></script>
|
<script src="~/js/casino/holdem/main.js?v=@ViewData["cssVersion"]"></script>
|
||||||
|
|||||||
@@ -1219,7 +1219,6 @@ body.hasActionBar #holdemSidebar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.actionBtn {
|
.actionBtn {
|
||||||
position: relative;
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -1257,29 +1256,6 @@ body.hasActionBar #holdemSidebar {
|
|||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionKey {
|
|
||||||
position: absolute;
|
|
||||||
top: 5px;
|
|
||||||
right: 7px;
|
|
||||||
padding: 0 0.25rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid currentColor;
|
|
||||||
opacity: 0.4;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: 0.6rem;
|
|
||||||
line-height: 1.4;
|
|
||||||
text-transform: uppercase;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No keyboard, no key badges — on a phone they'd just be clutter on the buttons
|
|
||||||
the dealer is already tapping. */
|
|
||||||
@media (hover: none) {
|
|
||||||
.actionKey {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionFold {
|
.actionFold {
|
||||||
background: linear-gradient(180deg, #3d1f1f, #2c1515);
|
background: linear-gradient(180deg, #3d1f1f, #2c1515);
|
||||||
border-color: #5b2626;
|
border-color: #5b2626;
|
||||||
|
|||||||
@@ -194,19 +194,6 @@ const ActionBar = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Which key presses each button. Shown on the button itself and hidden on touch
|
|
||||||
// devices — a shortcut nobody can discover may as well not exist, and a key badge
|
|
||||||
// on a phone is just clutter.
|
|
||||||
KEY_HINTS: {
|
|
||||||
actionFold: "F",
|
|
||||||
actionCheck: "C",
|
|
||||||
actionCall: "C",
|
|
||||||
actionRaise: "R",
|
|
||||||
actionAdvance: "↵",
|
|
||||||
raiseConfirm: "↵",
|
|
||||||
raiseCancel: "esc",
|
|
||||||
},
|
|
||||||
|
|
||||||
button(label, className, onClick, sublabel) {
|
button(label, className, onClick, sublabel) {
|
||||||
const btn = document.createElement("button");
|
const btn = document.createElement("button");
|
||||||
btn.type = "button";
|
btn.type = "button";
|
||||||
@@ -217,14 +204,6 @@ const ActionBar = {
|
|||||||
main.textContent = label;
|
main.textContent = label;
|
||||||
btn.appendChild(main);
|
btn.appendChild(main);
|
||||||
|
|
||||||
const hint = this.KEY_HINTS[className];
|
|
||||||
if (hint) {
|
|
||||||
const kbd = document.createElement("kbd");
|
|
||||||
kbd.className = "actionKey";
|
|
||||||
kbd.textContent = hint;
|
|
||||||
btn.appendChild(kbd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sublabel) {
|
if (sublabel) {
|
||||||
const sub = document.createElement("span");
|
const sub = document.createElement("span");
|
||||||
sub.className = "actionBtnSub";
|
sub.className = "actionBtnSub";
|
||||||
|
|||||||
@@ -116,38 +116,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
// snapshots refer to a hand that no longer exists.
|
// snapshots refer to a hand that no longer exists.
|
||||||
const clearActionHistory = () => { actionHistory.length = 0; };
|
const clearActionHistory = () => { actionHistory.length = 0; };
|
||||||
|
|
||||||
// Keyboard shortcuts press the very same buttons a dealer would tap, rather than
|
|
||||||
// calling the betting engine themselves — there's no second code path to drift out
|
|
||||||
// of step with what the bar is actually offering right now.
|
|
||||||
const pressInBar = selector => {
|
|
||||||
const btn = document.querySelector(`#actionBar ${selector}`);
|
|
||||||
if (!btn || btn.disabled) return false;
|
|
||||||
btn.click();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const quickRaiseButton = label =>
|
|
||||||
[...document.querySelectorAll("#actionBar .raiseQuickBtn")]
|
|
||||||
.find(b => b.querySelector(".actionBtnLabel").textContent === label);
|
|
||||||
|
|
||||||
Shortcuts.mount({
|
|
||||||
fold: () => pressInBar(".actionFold"),
|
|
||||||
checkOrCall: () => pressInBar(".actionCheck") || pressInBar(".actionCall"),
|
|
||||||
raise: () => pressInBar(".actionRaise"),
|
|
||||||
allIn: () => {
|
|
||||||
// Open the raise pad first if it isn't already, then take its All-in amount.
|
|
||||||
if (!document.querySelector("#actionBar .raisePad") && !pressInBar(".actionRaise")) return false;
|
|
||||||
const quick = quickRaiseButton("All-in");
|
|
||||||
if (!quick) return false;
|
|
||||||
quick.click();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
// Enter confirms a raise if one is being entered, otherwise moves the hand on.
|
|
||||||
advance: () => pressInBar(".raiseConfirm") || pressInBar(".actionAdvance"),
|
|
||||||
undo: () => pressInBar(".actionUndo"),
|
|
||||||
cancel: () => pressInBar(".raiseCancel"),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Moving to the next hand used to ask "are you sure?" every single time —
|
// Moving to the next hand used to ask "are you sure?" every single time —
|
||||||
// the most-pressed button in a session, gated behind a system dialog. It now
|
// the most-pressed button in a session, gated behind a system dialog. It now
|
||||||
// just happens, and the toast offers the way back for the few seconds anyone
|
// just happens, and the toast offers the way back for the few seconds anyone
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
// Keyboard control for a dealer running this on a laptop.
|
|
||||||
//
|
|
||||||
// The phone has gestures; the desktop had a mouse and nothing else. These are the
|
|
||||||
// same actions the bar already offers, reachable without moving a hand to the
|
|
||||||
// trackpad between every decision — which is the whole point when the bar is being
|
|
||||||
// tapped thirty times a hand.
|
|
||||||
const Shortcuts = {
|
|
||||||
// Deliberately single letters with no modifier: a dealer's spare hand rests on
|
|
||||||
// the keyboard, and a chord is slower than reaching for the button would be.
|
|
||||||
KEYS: {
|
|
||||||
f: "fold",
|
|
||||||
c: "checkOrCall",
|
|
||||||
r: "raise",
|
|
||||||
a: "allIn",
|
|
||||||
" ": "advance",
|
|
||||||
enter: "advance",
|
|
||||||
u: "undo",
|
|
||||||
escape: "cancel",
|
|
||||||
},
|
|
||||||
|
|
||||||
mount(handlers) {
|
|
||||||
this.handlers = handlers;
|
|
||||||
document.addEventListener("keydown", e => this.onKey(e));
|
|
||||||
},
|
|
||||||
|
|
||||||
// Nothing fires while the dealer is typing a name, an amount, or a note — the
|
|
||||||
// "c" in "Cass" must not fold the table.
|
|
||||||
isTyping() {
|
|
||||||
const el = document.activeElement;
|
|
||||||
if (!el) return false;
|
|
||||||
const tag = el.tagName;
|
|
||||||
return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || el.isContentEditable;
|
|
||||||
},
|
|
||||||
|
|
||||||
// An overlay owns the keyboard while it's up: the confirm dialog already binds
|
|
||||||
// Enter and Escape, and the card picker and seat menu are modal.
|
|
||||||
overlayOpen() {
|
|
||||||
return ["confirmOverlay", "potWizardOverlay", "cardPickerOverlay", "seatMenuOverlay"]
|
|
||||||
.some(id => {
|
|
||||||
const el = document.getElementById(id);
|
|
||||||
return el && !el.hidden;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onKey(e) {
|
|
||||||
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
||||||
|
|
||||||
const key = e.key.length === 1 ? e.key.toLowerCase() : e.key.toLowerCase();
|
|
||||||
const action = this.KEYS[key];
|
|
||||||
if (!action) return;
|
|
||||||
|
|
||||||
// Escape is the exception: it should still close the raise pad even if focus
|
|
||||||
// happens to be sitting in its amount field.
|
|
||||||
if (this.isTyping() && !(action === "cancel")) return;
|
|
||||||
if (this.overlayOpen()) return;
|
|
||||||
|
|
||||||
const handled = this.handlers[action] && this.handlers[action]();
|
|
||||||
if (handled) e.preventDefault();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof module !== "undefined" && module.exports) {
|
|
||||||
module.exports = Shortcuts;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user