Files
2025-07-02 14:13:16 +09:00

222 lines
10 KiB
JavaScript

function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return new Blob(byteArrays, {type: contentType});
}
function uploadImageAI(blob) {
var formData = new FormData();
// 파일명은 임의로 지정 ("generated.png")
formData.append("file", blob, "generated.png");
// 기존에 숨겨진 input(#editor_nonce)이 있다면 사용하고,
// 없으면 전역 변수 ed_nonce를 사용합니다.
var nonceElem = document.getElementById('editor_nonce');
if (nonceElem && nonceElem.value) {
formData.append("editor_nonce", nonceElem.value);
} else if (ed_nonce) {
formData.append("editor_nonce", ed_nonce);
} else {
//console.warn("Nonce 값이 설정되어 있지 않습니다.");
}
return fetch(g5Config.g5_editor_url + '/php/rb.upload.php', {
method: 'POST',
body: formData
}).then(function(response) {
return response.json();
});
}
// 함수: 작업 유형에 따른 placeholder 변경
function updatePlaceholder() {
var taskType = document.querySelector('input[name="taskType"]:checked').value;
var promptInput = document.getElementById('prompt');
if (taskType === 'image') {
document.getElementById("prompt_ai_img").src = "./image/ai/Stability.svg";
promptInput.placeholder = "생성 하고자하는 주제를 영문(단어)로 입력하세요.";
} else {
document.getElementById("prompt_ai_img").src = "./image/ai/Gemini.svg";
promptInput.placeholder = "이전 대화를 기억하지 못합니다. 질의나 문장 생성용으로 사용하세요.";
}
}
// 엔터키 입력 시 바로 요청
document.getElementById('prompt').addEventListener('keydown', function (e) {
if (e.key === "Enter") {
e.preventDefault();
document.getElementById('generateBtn').click();
}
});
// 라디오 버튼 변경 시 플레이스홀더 업데이트
var radios = document.querySelectorAll('input[name="taskType"]');
radios.forEach(function (radio) {
radio.addEventListener('change', updatePlaceholder);
});
updatePlaceholder(); // 초기 로드시 설정
document.getElementById('generateBtn').addEventListener('click', function () {
var prompt = document.getElementById('prompt').value.trim();
var taskType = document.querySelector('input[name="taskType"]:checked').value; // 선택된 작업 유형
if (prompt === '') {
alert('생성하실 주제를 입력해 주세요.');
return;
}
var btn = document.getElementById('generateBtn');
btn.disabled = true;
btn.textContent = '생각 중..';
document.getElementById('result').innerHTML = '';
// 로딩 오버레이 표시
var overlay = document.querySelector(".loadingOverlay_ai");
overlay.style.display = "block";
// API 요청 데이터 설정
var formData = new URLSearchParams();
formData.append("prompt", prompt);
formData.append("taskType", taskType);
fetch(g5Config.g5_editor_url + '/plugin/ai/ajax.generate.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData.toString()
})
.then(response => response.json())
.then(data => {
var editor = document.getElementById("editor");
var accumulateCheckbox = document.getElementById('accumulateCheckbox');
if (taskType === 'text' && data.text) {
document.getElementById("prompt_ai_img").src = "./image/ai/Gemini.svg";
// 텍스트의 경우 누적 체크박스가 체크되지 않으면 에디터 초기화
if (!(accumulateCheckbox && accumulateCheckbox.checked)) {
editor.innerHTML = "";
}
var newText = document.createElement("div");
newText.innerHTML = data.text;
var emptyDiv = document.createElement("div");
emptyDiv.innerHTML = "<br>";
if (editor) {
editor.appendChild(newText);
editor.appendChild(emptyDiv); // 빈 줄 추가
} else {
//console.error("Error: #editor element not found.");
}
//document.getElementById('result').innerHTML = '<p style="font-size: 12px; color:#999; text-align:right">모델 : ' + data.model + '</p>';
// 텍스트 생성 후 입력창 비우기
document.getElementById('prompt').value = "";
} else if (taskType === 'image') {
document.getElementById("prompt_ai_img").src = "./image/ai/Stability.svg";
if (data.image && data.image.length > 0) {
// 이미지 생성 성공 시
if (!(accumulateCheckbox && accumulateCheckbox.checked)) {
editor.innerHTML = "";
}
// base64 데이터를 Blob으로 변환 (타입: image/png)
var blob = b64toBlob(data.image, "image/png");
// 생성된 이미지를 업로드합니다.
uploadImageAI(blob).then(function(uploadResponse) {
if (uploadResponse.files && uploadResponse.files[0] && uploadResponse.files[0].url) {
var fileUrl = uploadResponse.files[0].url;
// ✅ .resizable_wrap 부모 div 생성
var resizableWrap = document.createElement("div");
resizableWrap.classList.add("resizable_wrap");
resizableWrap.style.position = "relative";
//resizableWrap.style.display = "inline-block"; // 부모 크기 유지
// ✅ AI 이미지용 wrapper 생성 (크기 및 리사이즈 핸들 포함)
var newImage = document.createElement("div");
newImage.classList.add("resizable", "rb_ai_image");
newImage.style.width = "450px";
newImage.style.height = "300px";
newImage.style.position = "relative";
// 원본 크기와 비율을 data 속성에 추가 (원본 너비: 450, 원본 높이: 300)
newImage.setAttribute("data-original-width", "450");
newImage.setAttribute("data-original-height", "300");
newImage.setAttribute("data-ratio", (300 / 450).toString());
newImage.innerHTML = `
<img src="${fileUrl}" alt="Generated Image" crossorigin="anonymous" draggable="false"
style="width: 100%; height: 100%; object-fit: cover;">
<div class="resize-handle"></div>
`;
// ✅ .resizable_wrap 내부에 .resizable 추가
resizableWrap.appendChild(newImage);
editor.appendChild(resizableWrap);
// 현재 newImage의 width에 맞춰 높이를 재계산하여 비율 유지
function updateHeight() {
var ratio = parseFloat(newImage.getAttribute("data-ratio"));
if (!isNaN(ratio)) {
newImage.style.height = (newImage.offsetWidth * ratio) + "px";
}
}
// 초기 높이 업데이트
updateHeight();
// 창 크기 변경 시 업데이트
window.addEventListener("resize", updateHeight);
// 필요시, 리사이즈 기능 활성화 (예: makeImageResizableWithObserver)
makeImageResizableWithObserver($(newImage));
} else {
document.getElementById('result').innerHTML = '<p style="font-size: 12px; color:#f55036">이미지 업로드 실패</p>';
}
}).catch(function(err) {
document.getElementById('result').innerHTML = '<p style="font-size: 12px; color:#f55036">이미지 업로드 오류</p>';
});
} else {
// 이미지 생성 실패 또는 에러 처리...
if (data.error) {
document.getElementById('result').innerHTML = '<p style="font-size: 12px; color:#f55036">이미지 생성 실패</p>';
} else {
document.getElementById('result').innerHTML = '<p style="font-size: 12px; color:#f55036">잠시후 다시 생성해주세요.</p>';
}
}
} else if (data.error) {
document.getElementById('result').innerHTML = '<p style="font-size: 12px; color:#f55036">오류가 있습니다.</p>';
}
overlay.style.display = "none";
btn.disabled = false;
btn.textContent = '생성';
})
.catch(error => {
document.getElementById('result').innerHTML = '<p style="font-size: 12px; color:#f55036">오류가 있습니다.</p>';
document.querySelector(".loadingOverlay_ai").style.display = "none";
btn.disabled = false;
btn.textContent = '생성';
});
});