Created
April 7, 2024 20:16
-
-
Save aleclarson/259c6b778deb04079f1ab4319c306e26 to your computer and use it in GitHub Desktop.
Google AI Studio: Finished notification – Tampermonkey Userscript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Gemini Finished Notification | |
// @namespace http://tampermonkey.net/ | |
// @version 0.3 | |
// @description Notify when Gemini is done loading a model response | |
// @author Claude 3 | |
// @match https://aistudio.google.com/app/prompts/* | |
// @grant GM_notification | |
// @grant GM_getTab | |
// @grant GM_openInTab | |
// ==/UserScript== | |
(function () { | |
"use strict"; | |
function waitForElement(selector, timeout = 10000) { | |
return new Promise((resolve, reject) => { | |
const interval = setInterval(() => { | |
const element = document.querySelector(selector); | |
if (element) { | |
clearInterval(interval); | |
resolve(element); | |
} | |
}, 100); | |
setTimeout(() => { | |
clearInterval(interval); | |
reject(new Error(`Timed out waiting for element: ${selector}`)); | |
}, timeout); | |
}); | |
} | |
async function observeLoadingIndicator() { | |
const targetNode = await waitForElement(".prompt-content"); | |
let hasLoadingIndicator = false; | |
let notifyTimeout; | |
const notifySoon = (content) => { | |
notifyTimeout = setTimeout(() => { | |
GM_notification({ | |
title: "Gemini is done", | |
text: content ? content.textContent.slice(0, 100) + '…' : 'Come see what Gemini wrote!', | |
silent: false, | |
onclick: function () { | |
window.focus(); | |
} | |
}); | |
// Allow another notification to be sent. | |
hasLoadingIndicator = false; | |
notifyTimeout = null; | |
}, 1000); | |
} | |
const observer = new MutationObserver(function (mutations) { | |
mutations.forEach(function (mutation) { | |
if (mutation.type === "childList") { | |
const content = | |
mutation.target.querySelector(".model-response-contents") || | |
(mutation.target.matches(".model-response-contents") ? mutation.target : null); | |
if (!content) { | |
return; | |
} | |
if (notifyTimeout) { | |
clearTimeout(notifyTimeout); | |
notifySoon(content); | |
} else { | |
const loadingIndicator = content.querySelector( | |
"loading-indicator" | |
); | |
if (hasLoadingIndicator && !loadingIndicator) { | |
notifySoon(content); | |
} | |
hasLoadingIndicator = !!loadingIndicator; | |
} | |
} | |
}); | |
}); | |
observer.observe(targetNode, { childList: true, subtree: true }); | |
} | |
observeLoadingIndicator(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment