āļāđāļāļāļāļąāļ Enter āļŠāđāļāļāđāļāļāļ§āļēāļĄ, āļĢāļāļāļĢāļąāļ Enter āļāđāļēāļ, āđāļĨāļ°āđāļāļĨāļĩāđāļĒāļāļŦāđāļāļ/āđāļāđāļāđāļ Gemini āļāļąāļāđāļāļĄāļąāļāļī (Android āļĄāļ·āļāļāļ·āļ)
// ==UserScript==
// @name Gemini ðĄïļ Enter Fix Pro
// @namespace https://tampermonkey.local/gemini-enter-fix
// @version 1.4.0
// @description āļāđāļāļāļāļąāļ Enter āļŠāđāļāļāđāļāļāļ§āļēāļĄ, āļĢāļāļāļĢāļąāļ Enter āļāđāļēāļ, āđāļĨāļ°āđāļāļĨāļĩāđāļĒāļāļŦāđāļāļ/āđāļāđāļāđāļ Gemini āļāļąāļāđāļāļĄāļąāļāļī (Android āļĄāļ·āļāļāļ·āļ)
// @match https://gemini.google.com/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
/** ================= CONFIG ================= **/
const CONFIG = {
DEBUG: true,
NS: 'gemini-enterfix',
RECHECK_INTERVAL: 2000, // ms, āļāļĢāļ§āļāļŠāļāļāļāđāļāļāļāđāļāļāļ§āļēāļĄāđāļŦāļĄāđāļāļļāļ 2 āļ§āļīāļāļēāļāļĩ
};
/* ================== LOGGER ================== */
function log(msg, type = "info") {
try {
if (!CONFIG.DEBUG) return;
// āļāļĢāļ§āļāļŠāļāļāļāđāļāļāļ§āļēāļĄāđāļŦāđāđāļāđāđāļāļ§āđāļēāđāļāđāļ string āđāļŠāļĄāļ
const safeMsg = typeof msg === "string" ? msg : JSON.stringify(msg, null, 2);
// āđāļāļĢāļĩāļĒāļĄ payload āļāļĩāđāļāļĨāļāļāļ āļąāļĒ
const payload = {
namespace: "LogCenter", // â
āļāđāļāļāļāļĢāļāļāļąāļ CONFIG.NAMESPACE āđāļ Logs Center
from: (typeof GM_info !== "undefined" && GM_info.script && GM_info.script.name)
? GM_info.script.name
: "UnknownScript",
type,
time: new Date().toLocaleTimeString("th-TH", { hour12: false }),
stack: new Error().stack,
message: safeMsg
};
// â
āļŠāđāļ log āđāļāļĒāļąāļ Logs Center
window.postMessage(payload, "*");
} catch (err) {
console.error("Logger error:", err);
}
}
/** ================= UTILITIES ================= **/
function insertNewLine(el) {
try {
// āđāļāđ execCommand āđāļāļ·āđāļāđāļŦāđ Quill āļĢāļāļāļĢāļąāļ
el.focus();
const ok = document.execCommand('insertLineBreak', false);
if (!ok) {
const sel = el.ownerDocument.getSelection();
if (!sel || !sel.rangeCount) return;
const range = sel.getRangeAt(0);
const br = el.ownerDocument.createElement('br');
range.deleteContents();
range.insertNode(br);
range.setStartAfter(br);
range.setEndAfter(br);
sel.removeAllRanges();
sel.addRange(range);
}
el.dispatchEvent(new InputEvent('input', { bubbles: true }));
} catch (err) {
log(`insertNewLine error: ${err.message}`, 'error');
}
}
/** ================= KEY HANDLER ================= **/
function handleKey(e) {
try {
const el = document.activeElement;
if (!el || !el.isContentEditable) return;
// Enter āļāļĢāļĢāļĄāļāļē = āļāļķāđāļāļāļĢāļĢāļāļąāļāđāļŦāļĄāđ
if (e.key === 'Enter' && !e.ctrlKey && !e.shiftKey) {
e.preventDefault();
e.stopImmediatePropagation();
insertNewLine(el);
}
// Ctrl/Shift + Enter = āļŠāđāļāļāđāļāļāļ§āļēāļĄ
else if (e.key === 'Enter' && (e.ctrlKey || e.shiftKey)) {
log('ðĻ āļŠāđāļāļāđāļāļāļ§āļēāļĄ (Ctrl/Shift+Enter)');
}
} catch (err) {
log(`handleKey error: ${err.message}`, 'error');
}
}
/** ================= EVENT ATTACH ================= **/
function attachEditor(el) {
if (!el || el.dataset[`${CONFIG.NS}-active`] === '1') return;
el.dataset[`${CONFIG.NS}-active`] = '1';
// āđāļāđ keydown (āđāļĄāđāđāļāđ keypress āđāļāļĢāļēāļ° Quill intercept)
el.addEventListener('keydown', handleKey, { capture: true, passive: false });
log('â
āļāļđāļ Event Keydown āļŠāļģāđāļĢāđāļ');
}
function scanEditors(root = document) {
const boxes = root.querySelectorAll('.ql-editor,[contenteditable="true"],div[role="textbox"]');
boxes.forEach(attachEditor);
}
/** ================= AUTO RE-ATTACH ================= **/
// debounce āđāļāļ·āđāļāđāļŦāđāđāļāļĨāļĩāđāļĒāļāļŦāđāļāļāđāļĨāđāļ§ reattach āđāļāđāđāļĢāđāļ§āđāļāđāđāļĄāđāļāļĩāđāđāļāļīāļ
let reattachTimer = null;
function scheduleReattach() {
if (reattachTimer) return;
reattachTimer = setTimeout(() => {
reattachTimer = null;
scanEditors(document);
}, 300);
}
// āļŠāļąāļāđāļāļ DOM āđāļāļĨāļĩāđāļĒāļ (āđāļāļĨāļĩāđāļĒāļāđāļāđāļ/āļŦāđāļāļ)
const observer = new MutationObserver(scheduleReattach);
observer.observe(document, { childList: true, subtree: true });
// āļāļĢāļ§āļāļāđāļģāļāļļāļāđ N āļ§āļīāļāļēāļāļĩ (āļāđāļāļāļāļąāļāļāļĢāļāļĩ Shadow DOM āđāļŦāļĨāļāļāđāļē)
setInterval(() => {
scanEditors(document);
}, CONFIG.RECHECK_INTERVAL);
/** ================= INIT ================= **/
window.addEventListener('keydown', handleKey, { capture: true, passive: false });
scanEditors(document);
log('ð§Đ Gemini Enter Fix Pro āļāļĢāđāļāļĄāđāļāđāļāļēāļāđāļĨāđāļ§');
})();