🏠 Home 

记录位置

允许用户自定义快捷键记录滚动位置,记录快捷键默认 Ctrl+O,恢复位置快捷键默认 Ctrl+Shift+H。提供保存位置、恢复位置、一键清理记录的菜单选项。恢复时在记录中找到匹配的完整网址记录,跳转到最近的匹配网址并平滑滚动恢复位置。进入网页时检查是否有记录,如果有则自动跳转到保存位置,主页面不自动恢复位置。

// ==UserScript==
// @name         记录位置
// @version      3.1
// @description  允许用户自定义快捷键记录滚动位置,记录快捷键默认 Ctrl+O,恢复位置快捷键默认 Ctrl+Shift+H。提供保存位置、恢复位置、一键清理记录的菜单选项。恢复时在记录中找到匹配的完整网址记录,跳转到最近的匹配网址并平滑滚动恢复位置。进入网页时检查是否有记录,如果有则自动跳转到保存位置,主页面不自动恢复位置。
// @author       hiisme
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        GM_notification
// @namespace https://greasyfork.org/users/217852
// ==/UserScript==
(async () => {
const MAX_STORED_PAGES = 20;
const DEFAULT_SAVE_SHORTCUT = 'Ctrl+O';
const DEFAULT_RESTORE_SHORTCUT = 'Ctrl+Shift+H';
let saveShortcut = await GM_getValue('saveShortcut', DEFAULT_SAVE_SHORTCUT);
let restoreShortcut = await GM_getValue('restoreShortcut', DEFAULT_RESTORE_SHORTCUT);
const getStorageKey = () => `scrollPosition_${window.location.href}`;
const saveScrollPosition = async () => {
const storedData = await GM_getValue('scrollPositions', {});
storedData[getStorageKey()] = Math.round(window.scrollY);
await GM_setValue('scrollPositions', storedData);
manageStoredKeys(storedData);
showNotification('塞进了回忆');
};
const smoothScrollTo = (position) => {
window.scrollTo({
top: position,
behavior: 'smooth'
});
};
const restoreScrollPosition = async () => {
const storedData = await GM_getValue('scrollPositions', {});
const domain = new URL(window.location.href).origin;
const keys = Object.keys(storedData);
const closestMatch = keys
.filter(key => key.includes(domain))
.sort()
.pop();
if (closestMatch) {
const targetUrl = closestMatch.split('_')[1];
if (targetUrl !== window.location.href) {
await GM_setValue('scrollPositionsToRestore', {
url: targetUrl,
position: storedData[closestMatch]
});
window.location.href = targetUrl;
} else {
smoothScrollTo(storedData[closestMatch]);
showNotification('已回到从前');
}
} else {
showNotification('没有找到回忆');
}
};
const clearAllPositions = async () => {
await GM_setValue('scrollPositions', {});
showNotification('所有的回忆都消失了');
};
const manageStoredKeys = (storedData) => {
const keys = Object.keys(storedData);
if (keys.length > MAX_STORED_PAGES) {
keys
.sort((a, b) => storedData[a] - storedData[b])
.slice(0, keys.length - MAX_STORED_PAGES)
.forEach(key => delete storedData[key]);
GM_setValue('scrollPositions', storedData);
}
};
const showNotification = (message) => {
GM_notification({
text: message,
title: '脚本通知',
timeout: 3000
});
};
const isValidShortcut = (shortcut) => /^((Ctrl|Shift|Alt)\+)*[A-Z]$/.test(shortcut);
const handleKeyboardEvent = (event) => {
const modifierKeys = `${event.ctrlKey ? 'Ctrl+' : ''}${event.shiftKey ? 'Shift+' : ''}${event.altKey ? 'Alt+' : ''}${event.key.toUpperCase()}`;
if (modifierKeys === saveShortcut) {
saveScrollPosition();
event.preventDefault();
} else if (modifierKeys === restoreShortcut) {
restoreScrollPosition();
event.preventDefault();
}
};
const setupEventListeners = () => {
window.addEventListener('keydown', handleKeyboardEvent);
};
GM_registerMenuCommand('塞进回忆', saveScrollPosition);
GM_registerMenuCommand('回忆从前', restoreScrollPosition);
GM_registerMenuCommand('清空回忆', clearAllPositions);
GM_registerMenuCommand('如何记忆时光', async () => {
const newSaveShortcut = prompt('键入记忆时光的按钮 (例如 Ctrl+O)', saveShortcut);
if (newSaveShortcut && isValidShortcut(newSaveShortcut)) {
await GM_setValue('saveShortcut', newSaveShortcut);
saveShortcut = newSaveShortcut;
alert(`记录位置快捷键已设置为: ${newSaveShortcut}`);
} else {
alert('快捷键格式无效,请使用 Ctrl、Shift、Alt 组合键加单个字母。');
}
});
GM_registerMenuCommand('如何回到从前', async () => {
const newRestoreShortcut = prompt('输入回到从前的按钮 (例如 Ctrl+Shift+H)', restoreShortcut);
if (newRestoreShortcut && isValidShortcut(newRestoreShortcut)) {
await GM_setValue('restoreShortcut', newRestoreShortcut);
restoreShortcut = newRestoreShortcut;
alert(`恢复位置快捷键已设置为: ${newRestoreShortcut}`);
} else {
alert('快捷键格式无效,请使用 Ctrl、Shift、Alt 组合键加单个字母。');
}
});
const checkForPendingRestore = async () => {
const pendingData = await GM_getValue('scrollPositionsToRestore', null);
if (pendingData) {
await GM_setValue('scrollPositionsToRestore', null);
window.addEventListener('load', () => {
smoothScrollTo(pendingData.position);
showNotification('回忆从前');
}, { once: true });
window.location.href = pendingData.url;
}
};
const initialize = async () => {
setupEventListeners();
await checkForPendingRestore();
window.addEventListener('load', async () => {
const storedData = await GM_getValue('scrollPositions', {});
const currentKey = getStorageKey();
if (storedData[currentKey]) {
smoothScrollTo(storedData[currentKey]);
showNotification('回忆从前');
}
});
};
initialize();
})();