83 lines
2.2 KiB
JavaScript
83 lines
2.2 KiB
JavaScript
// ==UserScript==
|
|
// @name Save Unsent AI Prompts
|
|
// @namespace Violent Monkey Scripts
|
|
// @version 1.0
|
|
// @description Auto-save unsent AI prompts as drafts
|
|
// @match https://chatgpt.com/*
|
|
// @grant none
|
|
// ==/UserScript==
|
|
|
|
/*
|
|
Doesn't it suck that chatgpt saves all your history unless you don't send it. There is no draft system in chatgpt.
|
|
|
|
This userscript will make it so you can dig for it in localStorage if you really need it.
|
|
|
|
Continued discussion about this userscript can be found here: https://goatmatrix.net/c/Userscripts/9sBaPCiRRE
|
|
*/
|
|
|
|
(async function(){
|
|
for await (let newTarget of targetDivs()) {
|
|
applyHandler(newTarget);
|
|
}
|
|
})();
|
|
|
|
function timeout(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
// Continuously looks for new #prompt-textarea divs
|
|
async function* targetDivs() {
|
|
let found = new Set();
|
|
while(true) {
|
|
let divs = document.querySelectorAll('#prompt-textarea');
|
|
for(let div of divs) {
|
|
if(!found.has(div)) {
|
|
found.add(div);
|
|
yield div;
|
|
}
|
|
}
|
|
await timeout(500);
|
|
}
|
|
}
|
|
|
|
function shouldSaveDraft(oldVal, newVal) {
|
|
// Save if text was added or replaced (not pure deletion).
|
|
if (newVal.length > oldVal.length) return true;
|
|
if (newVal.length === oldVal.length && newVal !== oldVal) return true;
|
|
return false;
|
|
}
|
|
|
|
function saveDraft(id, text) {
|
|
localStorage.setItem('draft-'+id, text);
|
|
}
|
|
|
|
function applyHandler(div) {
|
|
let currentId = null;
|
|
let oldValue = '';
|
|
|
|
// Called whenever mutations occur
|
|
function onDivMutate() {
|
|
let newValue = div.innerHTML.trim();
|
|
if (!newValue) {
|
|
// If there's nothing left, reset
|
|
currentId = null;
|
|
oldValue = '';
|
|
return;
|
|
}
|
|
// If we had no oldValue, this is the first time we're typing => new ID
|
|
if (!oldValue || !currentId) {
|
|
currentId = Date.now();
|
|
}
|
|
// Only save if something was added (newValue got longer than oldValue)
|
|
if(shouldSaveDraft(oldValue,newValue)) {
|
|
saveDraft(currentId,newValue);
|
|
}
|
|
// Update the known current content
|
|
oldValue = newValue;
|
|
}
|
|
|
|
// Observe changes in the div (childList & characterData changes)
|
|
let observer = new MutationObserver(onDivMutate);
|
|
observer.observe(div, {childList: true, characterData: true, subtree: true});
|
|
}
|