1 | ||
1 | ||
1 | ||
1 |
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.
It wasn't that straightforward to make because chatgpt uses a single page application and it doesn't actually put the text in a textarea. But after some mutation observer stuff it's not so bad. It was a 0.2/10 in difficulty when saving content from a textarea to localStorage should be a 0.02/10.
To install it click here: https://lab.gvid.tv/x0x7/Userscripts/raw/branch/main/saveprompt.user.js
The code:
// ==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==
(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});
}
this is super cool!
In theory I could adapt it to other sites. Most of them would be more simple because they use text area inputs. So if I were to make a multi-site one I'd probably make a separate script that covers what more normal sites have in common. But it could in theory be possible to never lose something you type in a text box.
Also if you delete a large portion of text it starts a new save bucket so each version is saved.
Thats extra cool! We all hate having the boxes eat our words. Nothing better than designing a NLP input over 30 minutes just to say, oops, sorry!
It doesn't have a UI or anything. I'll make one if it gets really popular or I use it a bunch, or if someone suggests code. It's really only meant to be used once every two months as a butt catcher. It's good enough that if something is worth that kind of time for you, you can dig it out of localStorage in 3 minutes.
a UI would be cool. But prob not worth the time, i agree. losing a long winded prompt only happens to me about once every few months. I wish there was a node in stable that would port your prompts and the Ksampler data to a txt file or data base. So many times i cry because i delete. sage. :-(
Kewl. Did you know that TamperMonkey went proprietary? I guess they're trying to tamper with your system. Better to use ViolentMonkey.
I've almost always used ViolentMonkey. Better UI, cooler name.
Hm. When Greasemonkey got eclipsed (I forget what even happened) I remember switching to one of these two, and when I started using userscripts again last year I just wanted the same thing. But maybe I mistook TamperMonkey for ViolentMonkey. I dislike both of those name tbh but idk if the new Greasemonkey is good.