Manually saved FetLife pages and scroll positions
// ==UserScript==
// @name FL Tools Return
// @namespace https://gitlab.com/fl-tools-lite/fl-tools-return
// @version 0.1.0
// @description Manually saved FetLife pages and scroll positions
// @author TypicalBits
// @icon data:image/png;base64,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
// @icon64 data:image/png;base64,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
// @license PolyForm-Noncommercial-1.0.0
// @match https://fetlife.com/*
// @run-at document-end
// @noframes
// @grant GM.getValue
// @grant GM.setValue
// @homepageURL https://gitlab.com/fl-tools-lite/fl-tools-return
// @supportURL https://gitlab.com/fl-tools-lite/fl-tools-return/-/issues
// ==/UserScript==
// Copyright 2026 TypicalBits.
(function(){
'use strict';
// dock.js
// Copyright 2026 TypicalBits. Shared FL Tools Lite coordination.
const LITE_ORDER = ['view','read','calendar','notes','return'];
const LITE_CORNERS = ['bottom-left','bottom-right','top-left','top-right'];
const LITE_COLORS = {view:'#62A8DE',read:'#B9A0F5',calendar:'#65D8EB',notes:'#F39BC8',return:'#CCD4E0'};
const LITE_REPAIR = 'flt-lite:repair-v1';
function claimProduct(document,id) {
if (!LITE_ORDER.includes(id) || document.querySelector(`[data-flt-lite-claim="${id}"]`)) return null;
const claim=document.createElement('span');claim.hidden=true;claim.dataset.fltLiteClaim=id;
document.documentElement.append(claim);
return {ensure(){if(!claim.isConnected)document.documentElement.append(claim);},release(){claim.remove();}};
}
function setLiteCorner(document,host,corner) {
host.dataset.corner=corner; document.documentElement.dataset.fltLiteCorner=corner;
for(const panel of document.querySelectorAll('[data-flt-lite-panel]'))panel.dataset.fltLiteCorner=corner;
}
function ownLiteDock(document,host,storage,restoreSaved=true) {
const w=document.defaultView; const shadow=host.attachShadow({mode:'open'});
const style=document.createElement('style');style.textContent=`
:host{position:fixed;bottom:16px;left:16px;z-index:2147483001;color-scheme:dark;font:12px/1.4 system-ui,sans-serif}
:host([data-corner="bottom-right"]){left:auto;right:16px}
:host([data-corner="top-left"]){bottom:auto;top:16px}
:host([data-corner="top-right"]){left:auto;right:16px;bottom:auto;top:16px}
:host([data-fallback="true"]){transform:translateY(-58px)}:host([data-fallback="true"][data-corner^="top"]){transform:translateY(58px)}
.dock{display:flex;flex-wrap:wrap;gap:5px;max-width:calc(100vw - 32px)}
button{display:flex;align-items:center;justify-content:center;padding:3px;width:46px;height:46px;border:1px solid var(--accent);border-radius:8px;background:#17171a;cursor:pointer;color:var(--accent);font:inherit}
button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}button[aria-expanded="true"]{box-shadow:0 0 0 1px var(--accent)}img{width:38px;height:38px;display:block}
`;const bar=document.createElement('nav');bar.className='dock';bar.setAttribute('aria-label','FL Tools Lite');shadow.append(style,bar);
let cornerRevision=0;
let current=null;const buttons=new Map(); let disposed=false;let writes=Promise.resolve();
function ports(){return [...host.children].filter(x=>x.hasAttribute('data-flt-lite-port'));}
function close(port,focus=false){port?.dispatchEvent(new w.Event('flt-lite:close'));buttons.get(port)?.setAttribute('aria-expanded','false');if(current===port)current=null;if(focus)buttons.get(port)?.focus();}
function open(port){if(current===port){close(port,true);return;}if(current)close(current);current=port;buttons.get(port)?.setAttribute('aria-expanded','true');port.dispatchEvent(new w.Event('flt-lite:open'));}
function render(){
const active=ports().sort((a,b)=>LITE_ORDER.indexOf(a.dataset.product)-LITE_ORDER.indexOf(b.dataset.product));
for(const [port,button]of buttons)if(!active.includes(port)){if(current===port)close(port);button.remove();buttons.delete(port);}
for(const port of active){
let button=buttons.get(port);
if(!button){port.dispatchEvent(new w.Event('flt-lite:close'));button=document.createElement('button');button.type='button';button.dataset.product=port.dataset.product;button.setAttribute('aria-label','Open FL Tools '+port.dataset.label);button.setAttribute('aria-expanded','false');button.style.setProperty('--accent',LITE_COLORS[port.dataset.product]);
if(port.dataset.icon){const image=document.createElement('img');image.src=port.dataset.icon;image.alt='';button.append(image);}else button.textContent=port.dataset.label;
button.addEventListener('click',()=>open(port));buttons.set(port,button);
}
if(bar.children[active.indexOf(port)]!==button)bar.append(button);
}
setLiteCorner(document,host,host.dataset.corner||'bottom-left');
}
const route=event=>{const port=event.target;if(port.parentNode!==host||!port.hasAttribute('data-flt-lite-port'))return;
if(event.type==='flt-lite:register')render();
if(event.type==='flt-lite:toggle')open(port);
if(event.type==='flt-lite:hide')close(port,true);
if(event.type==='flt-lite:focus')buttons.get(port)?.focus();
if(event.type==='flt-lite:corner'&&LITE_CORNERS.includes(port.dataset.corner)){
cornerRevision++;const corner=port.dataset.corner;setLiteCorner(document,host,corner);
if(storage)writes=writes.then(()=>storage.setValue('flt-lite:dock:v1',corner)).catch(()=>{});
}
};
for(const name of ['register','toggle','hide','focus','corner'])host.addEventListener('flt-lite:'+name,route);
const escape=event=>{if(current&&event.key==='Escape'){close(current,true);event.stopPropagation();}};
document.addEventListener('keydown',escape);
const observer=new w.MutationObserver(()=>{if(!disposed)render();});observer.observe(host,{childList:true});render();
if(storage&&restoreSaved)Promise.resolve().then(()=>storage.getValue('flt-lite:dock:v1','bottom-left')).then(corner=>{if(!disposed&&cornerRevision===0&&host.isConnected&&LITE_CORNERS.includes(corner))setLiteCorner(document,host,corner);}).catch(()=>{});
return {destroy(){disposed=true;observer.disconnect();document.removeEventListener('keydown',escape);for(const name of ['register','toggle','hide','focus','corner'])host.removeEventListener('flt-lite:'+name,route);},render};
}
function registerDock(document,{id,label,icon,onOpen=()=>{},onClose=()=>{},storage}) {
const w=document.defaultView;const port=document.createElement('span');port.hidden=true;port.dataset.fltLitePort='';port.dataset.product=id;port.dataset.label=label;port.dataset.icon=icon;
port.addEventListener('flt-lite:open',onOpen);port.addEventListener('flt-lite:close',onClose);
let owner=null,ownedHost=null,destroyed=false,scheduled=false;
function ensure(){
if(destroyed||!document.body)return;
let host=document.querySelector('[data-flt-lite-dock="1"]');
if(!host){const restoreSaved=!document.documentElement.dataset.fltLiteCorner;owner?.destroy();host=document.createElement('div');host.dataset.fltLiteDock='1';host.dataset.corner=document.documentElement.dataset.fltLiteCorner||ownedHost?.dataset.corner||'bottom-left';host.dataset.fallback=String(!!document.querySelector('[data-flt-lite-dock]:not([data-flt-lite-dock="1"])'));document.body.append(host);ownedHost=host;owner=ownLiteDock(document,host,storage,restoreSaved);}
if(port.parentNode!==host){host.append(port);port.dispatchEvent(new w.Event('flt-lite:register',{bubbles:true}));}
owner?.render();
}
const schedule=()=>{if(scheduled||destroyed)return;scheduled=true;w.queueMicrotask(()=>{scheduled=false;ensure();});};
const observer=new w.MutationObserver(records=>{if(!port.isConnected||!document.querySelector('[data-flt-lite-dock="1"]'))schedule();});observer.observe(document.documentElement,{childList:true,subtree:true});
document.addEventListener(LITE_REPAIR,schedule);ensure();
const send=name=>{ensure();port.dispatchEvent(new w.Event('flt-lite:'+name,{bubbles:true}));};
return {
ensure,open(){send('toggle');},close(){send('hide');},focus(){send('focus');},
setCorner(corner){if(!LITE_CORNERS.includes(corner))return;port.dataset.corner=corner;send('corner');},
get corner(){return port.parentNode?.dataset.corner||'bottom-left';},
destroy(){if(destroyed)return;destroyed=true;observer.disconnect();document.removeEventListener(LITE_REPAIR,schedule);onClose();const host=port.parentNode;port.remove();
if(owner&&host===ownedHost){const survivors=[...host.children];owner.destroy();for(const survivor of survivors)document.body.append(survivor);host.remove();document.dispatchEvent(new w.Event(LITE_REPAIR));}
else if(host&&!host.querySelector('[data-flt-lite-port]'))host.remove();
port.removeEventListener('flt-lite:open',onOpen);port.removeEventListener('flt-lite:close',onClose);
}
};
}
// storage.js
// Copyright 2026 TypicalBits.
function createRecordStore(storage,key,normalize,locks=globalThis.navigator?.locks) {
let value={},loaded=false,error='',queue=Promise.resolve();
return {
get value(){return structuredClone(value);},get error(){return error;},
async load(){try{value=normalize(await storage.getValue(key,{}));loaded=true;error='';}catch{error='Saved data could not be read. Reload before saving.';}return structuredClone(value);},
transact(change){const job=queue.then(async()=>{
if(!loaded)throw Error(error||'Saved data has not loaded.');
if(!locks?.request){error='This browser cannot safely save across tabs. Use a browser with Web Locks support.';throw Error(error);}
const controller=new AbortController();const timeout=setTimeout(()=>controller.abort(),10000);
try{return await locks.request('flt-lite:storage:'+key,{mode:'exclusive',signal:controller.signal},async()=>{
let latest;try{latest=normalize(await storage.getValue(key,{}));}catch{error='Saved data could not be read. Nothing was overwritten.';throw Error(error);}
const next=normalize(change(structuredClone(latest)));
try{await storage.setValue(key,next);value=next;error='';return structuredClone(value);}catch{error='Could not save. Your previous saved data is unchanged.';throw Error(error);}
});}catch(problem){if(controller.signal.aborted){error='Another tab is busy saving. Please try again.';throw Error(error);}throw problem;}finally{clearTimeout(timeout);}
});queue=job.catch(()=>{});return job;}
};
}
function pageKey(input) {
const url=new URL(input);
if(url.protocol!=='https:'||url.hostname!=='fetlife.com'||url.username||url.password||url.port)throw Error('This is not a FetLife page.');
url.hash='';return url.href;
}
// panel.js
// Copyright 2026 TypicalBits.
function liteElement(document,tag,attributes={},text='') {
const element=document.createElement(tag);for(const [key,value]of Object.entries(attributes))element.setAttribute(key,String(value));if(text)element.textContent=text;return element;
}
function createLitePanel(document,{id,name,accent,icon,version,storage,onOpen=()=>{}}) {
const e=(tag,attrs,text)=>liteElement(document,tag,attrs,text);
const host=e('div',{'data-flt-lite-panel':id,'data-flt-lite-corner':'bottom-left'});const shadow=host.attachShadow({mode:'open'});
const style=e('style');style.textContent=`
:host{all:initial;position:fixed;left:16px;bottom:16px;z-index:2147483002;font:12px/1.5 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#eeeef4;color-scheme:dark;--accent:${accent}}
:host([data-flt-lite-corner$="right"]){left:auto;right:16px}:host([data-flt-lite-corner^="top"]){bottom:auto;top:16px}
*,*::before,*::after{box-sizing:border-box}[hidden]{display:none!important}button,input,textarea,select{font:inherit;color:inherit}button{cursor:pointer}button:disabled{opacity:.5;cursor:default}
button,input,textarea,select{background:#222228;border:1px solid #4b4b59;border-radius:6px;padding:6px 8px;min-width:0}button{min-height:32px}button:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.panel{position:absolute;bottom:54px;left:0;width:min(320px,calc(100vw - 32px));max-height:calc(100dvh - 90px);overflow:auto;padding:12px;background:#131318;border:1px solid var(--accent);border-radius:10px;box-shadow:0 8px 26px #0008}
:host([data-flt-lite-corner$="right"]) .panel{left:auto;right:0}:host([data-flt-lite-corner^="top"]) .panel{bottom:auto;top:54px}
.heading{display:flex;align-items:center;gap:8px;margin-bottom:12px}.heading strong{flex:1;font-size:14px}.heading img{width:30px;height:30px}.version{font-size:10px;color:#b5b5c4}.close{width:30px;min-height:30px;padding:0}
p{margin:0 0 10px}fieldset{border:0;padding:0;margin:0 0 12px;min-width:0}legend,label{font-weight:600;padding:0;margin-bottom:6px;display:block}input,textarea,select{display:block;width:100%;margin-bottom:10px}textarea{min-height:160px;resize:vertical}
.choices,.actions{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}.choices button{flex:1}.choices button[aria-pressed=true],.primary{background:var(--accent);border-color:var(--accent);color:#101015;font-weight:600}
.row{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}.row label{margin:0;min-width:0}.switch{position:relative;flex:none;width:34px;min-height:20px;height:20px;padding:0;border-radius:5px}.switch::after{content:"";position:absolute;top:3px;left:3px;width:12px;height:12px;background:#b5b5c4;border-radius:3px}.switch[aria-checked=true]{background:var(--accent)}.switch[aria-checked=true]::after{left:17px;background:#131318}
.note,.status,.page{font-size:11px;color:#b5b5c4;overflow-wrap:anywhere}.status{border-top:1px solid #3d3d46;padding-top:8px;margin:10px 0 0}.status:empty{display:none}details{border-top:1px solid #3d3d46;margin-top:10px;padding-top:8px}summary{cursor:pointer;color:var(--accent);font-weight:600;margin-bottom:8px}.record{border-top:1px solid #3d3d46;padding:8px 0;overflow-wrap:anywhere}.record strong{display:block;margin-bottom:4px}.confirmation{border:1px solid var(--accent);padding:8px;border-radius:6px;margin-bottom:10px}
`;
const panel=e('section',{class:'panel','aria-label':'FL Tools '+name});panel.hidden=true;
const heading=e('div',{class:'heading'});if(icon)heading.append(e('img',{src:icon,alt:''}));heading.append(e('strong',{},'FL Tools '+name),e('span',{class:'version'},version));const close=e('button',{class:'close',type:'button','aria-label':'Close '+name},'×');heading.append(close);
const body=e('div',{'data-content':''}),settings=e('details');settings.append(e('summary',{},'Settings'));const corners=e('div',{class:'choices','aria-label':'Dock position'});
let dock;for(const corner of ['bottom-left','bottom-right','top-left','top-right']){const button=e('button',{type:'button','aria-label':corner.replace('-',' '),'aria-pressed':'false'},corner.startsWith('top')?'↑ '+(corner.endsWith('left')?'Left':'Right'):'↓ '+(corner.endsWith('left')?'Left':'Right'));button.addEventListener('click',()=>{dock.setCorner(corner);for(const b of corners.children)b.setAttribute('aria-pressed',String(b===button));});corners.append(button);}settings.append(e('p',{class:'note'},'Dock position'),corners);
const status=e('p',{class:'status',role:'status','data-status':''});panel.append(heading,body,settings,status);shadow.append(style,panel);document.body.append(host);
dock=registerDock(document,{id,label:name,icon,storage,onOpen:()=>{panel.hidden=false;onOpen();close.focus();},onClose:()=>{panel.hidden=true;}});close.addEventListener('click',()=>dock.close());
return {host,shadow,panel,body,settings,dock,e,setStatus(text){if(status.textContent!==text)status.textContent=text;},ensure(){if(!host.isConnected)document.body.append(host);dock.ensure();},destroy(){dock.destroy();host.remove();}};
}
function watchLitePage(document,callback) {
const window=document.defaultView;let queued=false,destroyed=false;
const owned=node=>{const element=node.nodeType===1?node:node.parentElement;const host=element?.getRootNode()?.host;return !!element?.closest('[data-flt-lite-panel],[data-flt-lite-dock],[data-flt-lite-port],[data-flt-lite-claim],[data-flt-lite-style],[data-flt-view-root],[data-flt-view-style]')||(typeof host?.hasAttribute==='function'&&host.hasAttribute('data-flt-lite-panel'));};
const schedule=()=>{if(queued||destroyed)return;queued=true;window.queueMicrotask(()=>{queued=false;if(!destroyed)callback();});};
const observer=new window.MutationObserver(records=>{if(records.some(record=>!owned(record.target)&&[...record.addedNodes,...record.removedNodes].some(node=>!owned(node))))schedule();});observer.observe(document.documentElement,{childList:true,subtree:true});
const events=['popstate','pageshow','turbo:load','turbo:render','turbolinks:load'];for(const event of events)window.addEventListener(event,schedule);
return ()=>{destroyed=true;observer.disconnect();for(const event of events)window.removeEventListener(event,schedule);};
}
// bootstrap.js
// Copyright 2026 TypicalBits.
async function bootstrapLite({document,window,storage,product,setup}) {
const claim=claimProduct(document,product.id);if(!claim)return {duplicate:true,destroy(){}};
let feature,stop=()=>{},ui;
try {
const refresh=()=>{claim.ensure();ui.ensure();feature?.refresh?.();};
ui=createLitePanel(document,{...product,storage,onOpen:refresh});ui.setStatus('Loading saved settings…');
feature=await setup({ui,document,window,storage});stop=watchLitePage(document,refresh);refresh();
return {refresh,destroy(){stop();feature?.destroy?.();ui.destroy();claim.release();}};
}catch(error){stop();feature?.destroy?.();ui?.destroy();claim.release();throw error;}
}
function liteButton(ui,label,attributes={},handler=()=>{}) {
const button=ui.e('button',{type:'button',...attributes},label);button.addEventListener('click',handler);return button;
}
function liteField(ui,name,label,value='') {
const id='flt-'+ui.host.dataset.fltLitePanel+'-'+name;const node=ui.e('input',{id,type:'text','data-field':name});node.value=value;
ui.body.append(ui.e('label',{for:id},label),node);return node;
}
// icon.js
const PRODUCT_ICON = "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%20role%3D%22img%22%20aria-labelledby%3D%22title%20desc%22%3E%0A%20%20%3Ctitle%20id%3D%22title%22%3EFL%20Tools%20Return%20badge%3C%2Ftitle%3E%0A%20%20%3Cdesc%20id%3D%22desc%22%3EFL%20Tools%20Return%20badge.%20Artwork%20is%20border-free%3B%20CSS%20supplies%20the%20launcher%20and%20menu%20frames.%3C%2Fdesc%3E%0A%20%20%3Cdefs%3E%0A%20%20%20%20%3CradialGradient%20id%3D%22surface%22%20cx%3D%2238%25%22%20cy%3D%2228%25%22%20r%3D%2285%25%22%3E%0A%20%20%20%20%20%20%3Cstop%20offset%3D%220%22%20stop-color%3D%22%2325242a%22%2F%3E%0A%20%20%20%20%20%20%3Cstop%20offset%3D%22.58%22%20stop-color%3D%22%2317171a%22%2F%3E%0A%20%20%20%20%20%20%3Cstop%20offset%3D%221%22%20stop-color%3D%22%230e0e10%22%2F%3E%0A%20%20%20%20%3C%2FradialGradient%3E%0A%20%20%20%20%3Cfilter%20id%3D%22labelGlow%22%20x%3D%22-40%25%22%20y%3D%22-60%25%22%20width%3D%22180%25%22%20height%3D%22220%25%22%3E%0A%20%20%20%20%20%20%3CfeGaussianBlur%20in%3D%22SourceGraphic%22%20stdDeviation%3D%22.85%22%20result%3D%22blur%22%2F%3E%0A%20%20%20%20%20%20%3CfeFlood%20flood-color%3D%22%23CCD4E0%22%20flood-opacity%3D%22.42%22%20result%3D%22glowColor%22%2F%3E%0A%20%20%20%20%20%20%3CfeComposite%20in%3D%22glowColor%22%20in2%3D%22blur%22%20operator%3D%22in%22%20result%3D%22softGlow%22%2F%3E%0A%20%20%20%20%20%20%3CfeMerge%3E%0A%20%20%20%20%20%20%20%20%3CfeMergeNode%20in%3D%22softGlow%22%2F%3E%0A%20%20%20%20%20%20%20%20%3CfeMergeNode%20in%3D%22SourceGraphic%22%2F%3E%0A%20%20%20%20%20%20%3C%2FfeMerge%3E%0A%20%20%20%20%3C%2Ffilter%3E%0A%20%20%3C%2Fdefs%3E%0A%20%20%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22url%28%23surface%29%22%2F%3E%0A%20%20%3Cimage%20href%3D%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAE90lEQVR4AcyZW4hWVRTH%2FzM5NamVGXQhrKjHLCqsJgeMLhBGQaCkZEqXyWns60JBRUJkD0UQZMVoWSFJt4dIKOqpHoIQqgepXkpKRcuKKCu0LK%2B%2F5ezvzNnn7HPxm%2FMdz8daZ%2B%2B199prrf86%2B%2By9z%2Fl6VfB7SZpfoNKV7tXSqa9IVxcZzwWAkYsx8BBcOxHYrgPS2lFpap5z9MLdB6WeHmmVpD64djpewr3OmiQ9rpxfb1Yft%2B9GLAzAJ2fpdLP9P6nt915mwplZvoIALPvwCjfoNFfWWuyXTncO%2B4%2BRHnH1VBEE8Kp0FZoXwUZTmEftbJhcF0dZJ5l3viCdGHIcBMDDsySuTAYujct11Jm6cZ%2BT%2BzNWwxSAl6XJBDgPjtPlcaGm%2BkDCz%2BKEfFhMAQD5bHqmwhHRdkMk1FAhiSfhxuKgGCOm0SDtltyxBndNAUAxlW3aLmPwBW5M1wsStggnrKRcx6mP6iWwRykA9KYA0GbUsku3%2BQlpEgkbCfkBWHJaqTegeE6gzZqGOFbMsko3%2BQzpbuzPhFMEsLOTjSEAJySVnNxLBlaztc8wZlk7zrVPuFgn2VJ9LpvnhRh7Es4ieza8vhCA4HrrRs1ia99mTPR7eC5%2BhNetkebZrXc6hcVaaRpjlsEfMv6vf6VdLNU%2FsHx%2FxeDMPYcEpmILATgWI2XJNpvF3Np3ufWbCaaVB4QNcjrTcOX%2F0nbGjMLX4ygVFG1Z1JfsCAH4I6lUUp6B3osA2eimAuI4EfgCjgebyOL9tHrLNHIpAnAqthCAbaWsZSvNZCp8zvSwQMV06efOPE%2Fg7zDkFLhjwsbW5OAUAJQ2J5U6kPvJ1koCX7VX%2Bpjx98ETJhKTis0DYIc2HFe5645gb3DCkTsDJPc2V40KDwArgW0g06Pe5lXmcFe9jdYDQLwL4abTLfEAIwA8bNPoOB%2FOoMY0e4e8CAAPmx0hIrkx4aYDOS%2FeFAXMGj0l3tHgureHRAB4gP9scNDx0HbGhQgAe%2FRPdLDUcm0wsSxvj4cXAbhdsjvwrRr%2BI%2BAN8RCR46Le96QGCkyRD%2BJheQDY6VhNhU5cpVH1Lb9In8Qj8gAslTbR%2BSbcVFrBcd1LsAfAot4nLaf8G24UMTu%2B4E3njWRQKQD38LKBUiWnR%2BxURbtJ7JKbJbYr32QKgHUPS69T8k2V69Gng2R%2FaJn0XSiUIACnaC8kR31VIviHeTbtZciF5ReZALgLHI80n41jvT%2BkVmk5wT%2Bb5zETgA0yEGRgAfX34FoJv4%2Fh%2F6kip7kAbDBG7E4sxOBrJtfAe%2FG1lMw%2FXcZXIQAzYiAwOIThB5C9dRi5StrJlJ2LLz5slDNbCkDbFIbt64L9a7m73VZh%2BT1r5BV8V%2FR22iL7RwTAjAFiPYPsrWiLyRXxp5yGZ2ctlXk%2BiCWvO9x3l%2FQ1D4b9g2KfTMJK5VvX%2FCxde4f0W%2Fkh45odAbDhLel3HM%2Bl%2FhzcCfFJVIt4voY537DRdmJC6hiAuTPHw9KD1O0PiT2UY1R83dEjXcnYt4pV8zUmBKBt2gIhoGuQf4WLaCPpHuBZ%2BrJIsUx%2FJQDMEQFtYH21f1C%2BMTnEgHyb5WvQHRhDKkfcVhkA8zwibeXb%2FBzqn8FJGt0h3cp8s7mf7OtYrhSAReHera8j2x%2BZbEz9GaZZi2eGm2Qt1XHlACw0gv2HHfUm6vYC0mJ6PUq9K3QIAAD%2F%2F1wKF9MAAAAGSURBVAMAjeXXP35naSYAAAAASUVORK5CYII%3D%22%20x%3D%2216%22%20y%3D%226%22%20width%3D%2232%22%20height%3D%2232%22%20preserveAspectRatio%3D%22xMidYMid%20meet%22%2F%3E%0A%20%20%3Ctext%20x%3D%2232%22%20y%3D%2254%22%20fill%3D%22%23CCD4E0%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2212%22%20font-weight%3D%22800%22%20letter-spacing%3D%22.1%22%20text-anchor%3D%22middle%22%20filter%3D%22url%28%23labelGlow%29%22%3ERETURN%3C%2Ftext%3E%0A%3C%2Fsvg%3E%0A";
// return.js
// Copyright 2026 TypicalBits.
function normalizeReturns(input) {
if(!input||typeof input!=='object'||Array.isArray(input)||Object.keys(input).length>100)throw Error('Invalid saved return points.');
const output={};for(const [url,record]of Object.entries(input)){
if(pageKey(url)!==url||!record||typeof record.title!=='string'||!Number.isFinite(record.y)||record.y<0)throw Error('Invalid return point.');
output[url]={url,title:record.title.slice(0,200),y:Math.floor(record.y),updated:Number.isFinite(record.updated)?record.updated:0};
}return output;
}
function createReturns(store) {
return {
list(){return Object.values(store.value).sort((a,b)=>b.updated-a.updated);},
async save(input,title,y){const url=pageKey(input);if(!Number.isFinite(y)||y<0)throw Error('Invalid page position.');await store.transact(value=>{
if(!Object.hasOwn(value,url)&&Object.keys(value).length>=100)throw Error('The 100-page limit has been reached. Remove a saved page first.');
return {...value,[url]:{url,title:String(title).slice(0,200),y:Math.floor(y),updated:Date.now()}};
});},
async remove(input){const url=pageKey(input);await store.transact(value=>{delete value[url];return value;});}
};
}
function restorePosition(window,record) {
if(pageKey(window.location.href)!==record.url||!Number.isFinite(record.y)||record.y<0)throw Error('Open this saved page before restoring its position.');
const height=Math.max(window.document.documentElement.scrollHeight,window.document.body?.scrollHeight||0);
const y=Math.min(Math.floor(record.y),Math.max(0,height-window.innerHeight));window.scrollTo({top:y,behavior:'instant'});return y;
}
// main.js
// Copyright 2026 TypicalBits.
function startReturn({document,window,storage,navigate=url=>window.location.assign(url)}) {
return bootstrapLite({document,window,storage,product:{id:'return',name:'Return',version:'0.1.0',icon:PRODUCT_ICON,accent:'#CCD4E0'},setup:async({ui})=>{
const store=createRecordStore(storage,'flt-return:records:v1',normalizeReturns,window.navigator.locks);await store.load();const points=createReturns(store);let busy=false,message='',signature='';
const actions=ui.e('div',{class:'actions'});const save=liteButton(ui,'Save position',{class:'primary','data-save':''},()=>perform(async()=>{await points.save(window.location.href,document.title,window.scrollY);message='Page and position saved.';}));
const restore=liteButton(ui,'Restore position',{'data-restore':''},()=>{try{const record=store.value[pageKey(window.location.href)];if(!record)throw Error('Save this page first.');const y=restorePosition(window,record);message=y<record.y?'Restored as far as the current page allows.':'Position restored.';}catch(error){message=error.message;}refresh();});actions.append(save,restore);
const list=ui.e('div',{'data-records':''});ui.body.append(actions,ui.e('p',{class:'note'},'Saves only when you choose Save position. Opening a saved page does not automatically scroll it.'),list);
async function perform(action){if(busy)return;busy=true;refresh();try{await action();}catch(error){message=error.message;}finally{busy=false;refresh();}}
function refresh(){const records=points.list(),next=JSON.stringify(records);restore.disabled=!store.value[pageKey(window.location.href)]||busy;save.disabled=busy;
if(next!==signature){signature=next;list.replaceChildren();if(!records.length)list.append(ui.e('p',{class:'note'},'No saved pages yet.'));
for(const record of records){const row=ui.e('div',{class:'record'});row.append(ui.e('strong',{},record.title||new URL(record.url).pathname),ui.e('p',{class:'page'},new URL(record.url).pathname));const buttons=ui.e('div',{class:'actions'});buttons.append(liteButton(ui,'Open',{'data-open':''},()=>{if(!busy)navigate(record.url);}),liteButton(ui,'Remove',{},()=>perform(async()=>{await points.remove(record.url);message='Saved page removed.';})));row.append(buttons);list.append(row);}
}
for(const button of list.querySelectorAll('button'))button.disabled=busy;ui.setStatus(message||store.error||`${records.length} / 100 pages saved.`);
}
return {refresh};
}});
}
void startReturn({document,window,storage:GM}).catch(()=>{});
})();