Skip to content

Instantly share code, notes, and snippets.

@qgp9
Last active July 29, 2026 08:54
Show Gist options
  • Select an option

  • Save qgp9/8379850075c95f7a31bf9feba15f3e93 to your computer and use it in GitHub Desktop.

Select an option

Save qgp9/8379850075c95f7a31bf9feba15f3e93 to your computer and use it in GitHub Desktop.
tampermonkey-shortcut-manager
// shortcut-manager.js
window.createShortcutManager = function (options = {}) {
const registry = [];
let isEnabled = true;
function showNotification(message) {
let container = document.getElementById("tm-shortcut-noti-container");
if (!container) {
container = document.createElement("div");
container.id = "tm-shortcut-noti-container";
Object.assign(container.style, {
position: "fixed",
top: "20px",
right: "20px",
zIndex: "999999999",
display: "flex",
flexDirection: "column",
gap: "10px",
pointerEvents: "none",
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
});
document.body.appendChild(container);
}
const toast = document.createElement("div");
toast.innerText = message;
Object.assign(toast.style, {
backgroundColor: "rgba(28, 28, 30, 0.9)",
color: "#ffffff",
padding: "10px 16px",
borderRadius: "8px",
fontSize: "13px",
fontWeight: "500",
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
backdropFilter: "blur(8px)",
webkitBackdropFilter: "blur(8px)",
border: "1px solid rgba(255, 255, 255, 0.1)",
opacity: "0",
transform: "translateY(-10px)",
transition: "all 0.25s cubic-bezier(0.16, 1, 0.3, 1)",
});
container.appendChild(toast);
requestAnimationFrame(() => {
toast.style.opacity = "1";
toast.style.transform = "translateY(0)";
});
setTimeout(() => {
toast.style.opacity = "0";
toast.style.transform = "translateY(-10px)";
setTimeout(() => toast.remove(), 300);
}, 2500);
}
function isEditingText(target) {
return (
target.tagName === "INPUT" ||
target.tagName === "TEXTAREA" ||
target.isContentEditable
);
}
document.addEventListener("keydown", (e) => {
if (isEditingText(e.target)) return;
for (const {
shortcut: s,
action,
condition,
alwaysActive,
notification,
} of registry) {
const isMatched =
e.key.toLowerCase() === s.key.toLowerCase() &&
!!s.alt === e.altKey &&
!!s.ctrl === e.ctrlKey &&
!!s.shift === e.shiftKey &&
!!s.meta === e.metaKey;
if (isMatched) {
if (!isEnabled && !alwaysActive) continue;
if (typeof condition === "function" && !condition(e)) continue;
e.preventDefault();
if (notification) showNotification(notification);
action(e);
break;
}
}
});
return {
notify: showNotification,
register(shortcut, action, options = {}) {
registry.push({
shortcut,
action,
condition: options.condition || null,
alwaysActive: options.alwaysActive || false,
notification: options.notification || null,
});
},
translateGoogle(targetLang, shortcut, options = {}) {
this.register(
shortcut,
() => {
const u = encodeURIComponent(window.location.href);
window.location.href = `https://translate.google.com/translate?sl=auto&tl=${targetLang}&u=${u}`;
},
{
notification: `🌐 구글 번역 (${targetLang.toUpperCase()}) 이동 중...`,
...options,
},
);
},
promptGemini(promptText, shortcut, options = {}) {
this.register(
shortcut,
() => {
const url = `https://gemini.google.com/app?text=${encodeURIComponent(promptText)}`;
window.open(url, "_blank");
},
{ notification: "🤖 Gemini로 전달 중...", ...options },
);
},
toggle(shortcut, options = {}) {
this.register(
shortcut,
() => {
isEnabled = !isEnabled;
showNotification(
`⌨️ 단축키 ${isEnabled ? "활성화 (ON)" : "비활성화 (OFF)"}`,
);
},
{ ...options, alwaysActive: true },
);
},
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment