222 lines
10 KiB
JavaScript
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 = '생성';
|
|
});
|
|
});
|