Auto-scroll to selected Suno rows for UI downloads

This commit is contained in:
DESKTOP-KSVGT20\shkim
2026-05-02 02:08:54 +09:00
parent 33aa56e571
commit abcb2e69b7
+41 -5
View File
@@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name ChatGPT to Suno Prompt Copier // @name ChatGPT to Suno Prompt Copier
// @namespace local.suno-helper // @namespace local.suno-helper
// @version 0.9.9 // @version 0.10.0
// @description Copy structured ChatGPT song prompt versions into Suno fields. // @description Copy structured ChatGPT song prompt versions into Suno fields.
// @author local // @author local
// @match https://chatgpt.com/* // @match https://chatgpt.com/*
@@ -30,7 +30,7 @@
(function () { (function () {
"use strict"; "use strict";
const SCRIPT_VERSION = "0.9.9"; const SCRIPT_VERSION = "0.10.0";
const STORAGE_KEY = "chatgptSunoPromptSlots"; const STORAGE_KEY = "chatgptSunoPromptSlots";
const SLOT_COUNT = 2; const SLOT_COUNT = 2;
const isChatGPT = location.hostname.includes("chatgpt.com") || location.hostname.includes("chat.openai.com"); const isChatGPT = location.hostname.includes("chatgpt.com") || location.hostname.includes("chat.openai.com");
@@ -972,7 +972,7 @@
}) || null; }) || null;
} }
function findTrackRowElement(track) { function findTrackRowElementNow(track) {
const rows = getVisibleLibraryRows(); const rows = getVisibleLibraryRows();
const index = getTrackVisibleIndex(track, rows); const index = getTrackVisibleIndex(track, rows);
if (index >= 0) return rows[index].element; if (index >= 0) return rows[index].element;
@@ -981,6 +981,42 @@
return rows.find((row) => row.normalized.includes(title))?.element || null; return rows.find((row) => row.normalized.includes(title))?.element || null;
} }
function getPageScroller() {
return document.scrollingElement || document.documentElement || document.body;
}
async function findTrackRowElement(track, statusTarget) {
const current = findTrackRowElementNow(track);
if (current) return current;
const scroller = getPageScroller();
const originalTop = scroller.scrollTop || window.scrollY || 0;
const maxSteps = 50;
const step = Math.max(260, Math.floor(window.innerHeight * 0.72));
setStatus(statusTarget, `SUNO 화면에서 곡 행 찾는 중: ${track.title || track.id}`);
scroller.scrollTop = 0;
window.scrollTo?.(0, 0);
await sleep(450);
for (let stepIndex = 0; stepIndex <= maxSteps; stepIndex += 1) {
const found = findTrackRowElementNow(track);
if (found) return found;
const before = scroller.scrollTop || window.scrollY || 0;
scroller.scrollTop = before + step;
window.scrollTo?.(0, before + step);
await sleep(260);
const after = scroller.scrollTop || window.scrollY || 0;
if (Math.abs(after - before) < 4) break;
}
scroller.scrollTop = originalTop;
window.scrollTo?.(0, originalTop);
await sleep(200);
return null;
}
function findMoreButtonInRow(row) { function findMoreButtonInRow(row) {
if (!row) return null; if (!row) return null;
const buttons = [...row.querySelectorAll("button, [role='button']")]; const buttons = [...row.querySelectorAll("button, [role='button']")];
@@ -1004,8 +1040,8 @@
} }
async function clickSunoUiDownload(track, format, statusTarget) { async function clickSunoUiDownload(track, format, statusTarget) {
const row = findTrackRowElement(track); const row = await findTrackRowElement(track, statusTarget);
if (!row) throw new Error("현재 화면에서 곡 행을 못 찾았어. SUNO 목록에서 그 곡이 보이게 스크롤한 뒤 다시 눌러줘."); if (!row) throw new Error("SUNO 화면을 훑어도 곡 행을 못 찾았어. 필터/검색 때문에 목록에 안 보이는지 확인해줘.");
const moreButton = findMoreButtonInRow(row); const moreButton = findMoreButtonInRow(row);
if (!moreButton) throw new Error("곡의 ... 메뉴 버튼을 못 찾았어."); if (!moreButton) throw new Error("곡의 ... 메뉴 버튼을 못 찾았어.");