diff --git a/chatgpt-suno-tampermonkey.user.js b/chatgpt-suno-tampermonkey.user.js
index bde8848..f5a40d9 100644
--- a/chatgpt-suno-tampermonkey.user.js
+++ b/chatgpt-suno-tampermonkey.user.js
@@ -1,7 +1,7 @@
// ==UserScript==
// @name ChatGPT to Suno Prompt Copier
// @namespace local.suno-helper
-// @version 0.10.1
+// @version 0.10.3
// @description Copy structured ChatGPT song prompt versions into Suno fields.
// @author local
// @match https://chatgpt.com/*
@@ -30,7 +30,7 @@
(function () {
"use strict";
- const SCRIPT_VERSION = "0.10.1";
+ const SCRIPT_VERSION = "0.10.3";
const STORAGE_KEY = "chatgptSunoPromptSlots";
const SLOT_COUNT = 2;
const isChatGPT = location.hostname.includes("chatgpt.com") || location.hostname.includes("chat.openai.com");
@@ -1878,11 +1878,11 @@
@@ -1910,12 +1910,14 @@
const slotSelect = body.querySelector("[data-cgs-slot]");
const trackList = body.querySelector("[data-cgs-track-list]");
let libraryTracks = [];
+ let visibleTrackIds = new Set();
const libraryTrackMap = new Map();
const selectedTrackIds = new Set();
let lastSelectedIndex = -1;
let autoScanTimer = 0;
- const getSelectedTracks = () => libraryTracks.filter((track) => selectedTrackIds.has(track.id));
+ const getVisibleTracks = () => libraryTracks.filter((track) => visibleTrackIds.has(track.id));
+ const getSelectedTracks = () => getVisibleTracks().filter((track) => selectedTrackIds.has(track.id));
const mergeLibraryTracks = (tracks) => {
for (const track of tracks) {
if (!track.id) continue;
@@ -1929,24 +1931,25 @@
};
const renderLibraryTrackList = () => {
try {
+ const visibleTracks = getVisibleTracks();
for (const id of [...selectedTrackIds]) {
- if (!libraryTrackMap.has(id)) selectedTrackIds.delete(id);
+ if (!visibleTrackIds.has(id)) selectedTrackIds.delete(id);
}
const selectedCount = selectedTrackIds.size;
- selectionSummary.textContent = libraryTracks.length
- ? `누적 ${libraryTracks.length}곡 / 선택 ${selectedCount}곡`
- : "누적된 곡 없음. 스크롤하면서 곡 감지를 눌러줘.";
+ selectionSummary.textContent = visibleTracks.length
+ ? `현재 화면 ${visibleTracks.length}곡 / 선택 ${selectedCount}곡 / 누적 ${libraryTracks.length}곡`
+ : `현재 화면 감지 없음 / 누적 ${libraryTracks.length}곡`;
const nodes = [];
- if (!libraryTracks.length) {
+ if (!visibleTracks.length) {
const empty = document.createElement("div");
empty.className = "cgs-track-item";
- empty.innerHTML = `
감지된 곡 없음
`;
+ empty.innerHTML = `
현재 화면에 감지된 곡 없음
`;
trackList.replaceChildren(empty);
return;
}
- libraryTracks.forEach((track, index) => {
+ visibleTracks.forEach((track, index) => {
const row = document.createElement("div");
row.className = `cgs-track-item ${selectedTrackIds.has(track.id) ? "cgs-selected" : ""}`;
row.dataset.cgsTrackIndex = String(index);
@@ -1984,15 +1987,17 @@
};
const setSelectedRange = (from, to) => {
const start = Math.max(0, Math.min(from, to));
- const end = Math.min(libraryTracks.length - 1, Math.max(from, to));
+ const visibleTracks = getVisibleTracks();
+ const end = Math.min(visibleTracks.length - 1, Math.max(from, to));
for (let index = start; index <= end; index += 1) {
- if (libraryTracks[index]?.id) selectedTrackIds.add(libraryTracks[index].id);
+ if (visibleTracks[index]?.id) selectedTrackIds.add(visibleTracks[index].id);
}
};
const scanAndMergeVisibleTracks = () => {
const scannedTracks = scanSunoLibraryTracks();
const before = libraryTracks.length;
mergeLibraryTracks(scannedTracks);
+ visibleTrackIds = new Set(scannedTracks.map((track) => track.id).filter(Boolean));
renderLibraryTrackList();
updateSummary();
return { scannedTracks, added: libraryTracks.length - before };
@@ -2062,7 +2067,8 @@
const item = event.target.closest("[data-cgs-track-index]");
if (!item) return;
const index = Number(item.getAttribute("data-cgs-track-index"));
- const track = libraryTracks[index];
+ const visibleTracks = getVisibleTracks();
+ const track = visibleTracks[index];
if (!track?.id) return;
if (event.shiftKey && lastSelectedIndex >= 0) {
setSelectedRange(lastSelectedIndex, index);
@@ -2085,7 +2091,7 @@
renderLibraryTrackList();
}
updateSummary();
- const track = getSelectedTracks()[0] || libraryTracks[0];
+ const track = getSelectedTracks()[0] || getVisibleTracks()[0];
if (!track) {
setStatus(body, "선택할 감지 곡이 없어. 곡 감지를 먼저 눌러줘.");
return;
@@ -2099,7 +2105,7 @@
};
body.querySelector("[data-cgs-process-one-mp3]").addEventListener("click", async () => {
- await registerSelectedManualDownloads("mp3", { one: true });
+ await processSelectedTrack("mp3");
});
body.querySelector("[data-cgs-process-one-wav]").addEventListener("click", async () => {
@@ -2107,7 +2113,7 @@
});
body.querySelector("[data-cgs-process-selected-mp3]").addEventListener("click", async () => {
- await registerSelectedManualDownloads("mp3");
+ await processSelectedTracks("mp3");
});
body.querySelector("[data-cgs-process-selected-wav]").addEventListener("click", async () => {
@@ -2115,7 +2121,7 @@
});
const registerSelectedManualDownloads = async (format, options = {}) => {
- if (!libraryTracks.length) {
+ if (!getVisibleTracks().length) {
mergeLibraryTracks(scanSunoLibraryTracks());
renderLibraryTrackList();
}
@@ -2132,7 +2138,7 @@
};
const clickSelectedSunoUiDownloads = async (format, options = {}) => {
- if (!libraryTracks.length) {
+ if (!getVisibleTracks().length) {
mergeLibraryTracks(scanSunoLibraryTracks());
renderLibraryTrackList();
}
@@ -2165,20 +2171,24 @@
});
const processLibraryTracks = async (format) => {
- if (!libraryTracks.length) {
+ if (!getVisibleTracks().length) {
mergeLibraryTracks(scanSunoLibraryTracks());
renderLibraryTrackList();
}
updateSummary();
try {
- await uploadTracksToCompanion(libraryTracks, body, format);
+ if (format === "wav") {
+ await expectManualDownloads(libraryTracks, body, "wav");
+ } else {
+ await uploadTracksToCompanion(libraryTracks, body, format);
+ }
} catch (error) {
setStatus(body, `${format.toUpperCase()} 일괄 처리 실패: ${error.message || error}`);
}
};
const processSelectedTracks = async (format) => {
- if (!libraryTracks.length) {
+ if (!getVisibleTracks().length) {
mergeLibraryTracks(scanSunoLibraryTracks());
renderLibraryTrackList();
}