Skip to content

Commit

Permalink
feat: 클라이언트측 이미지 업로드 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
HyeokjinKang committed Oct 30, 2023
1 parent 4b30775 commit 0efbb4d
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 89 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ resources/

*.swp

dist/
dist/

public/images/profiles/
3 changes: 2 additions & 1 deletion locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -234,5 +234,6 @@
"rank_title": "RANKING",
"rank_subtitle": "랭킹",
"profile": "Profile",
"banner": "Display"
"banner": "Display",
"image_error": "Image upload failed. Please make sure the image is less than 1MB."
}
3 changes: 2 additions & 1 deletion locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,5 +218,6 @@
"rank_title": "랭킹",
"rank_subtitle": "RANKING",
"profile": "프로필",
"banner": "장식장"
"banner": "장식장",
"image_error": "이미지 업로드에 실패하였습니다. 이미지 용량이 1MB 이하인지 확인해주세요."
}
135 changes: 49 additions & 86 deletions public/js/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -2015,99 +2015,62 @@ const changeProfile = (e) => {
],
onClosing: (instance, toast, closedBy) => {
if (closedBy != "button") {
let url = "";
iziToast.show({
overlay: true,
timeout: 20000,
zindex: 999,
theme: "dark",
title: "Enter url of picture.",
position: "center",
progressBarColor: "#999",
inputs: [
[
'<input type="text" id="urlInput" />',
"change",
(instance, toast, input, e) => {
url = input.value;
},
true,
],
],
buttons: [
[
"<button><b>OK</b></button>",
async (instance, toast) => {
loadingOverlayShow();
instance.hide({ transitionOut: "fadeOut" }, toast, "confirm");
url = document.getElementById("urlInput").value;
if (url != "" && validURL(url)) {
if (await validImage(url)) {
await fetch(`${api}/profile/${closedBy}`, {
method: "PUT",
credentials: "include",
body: JSON.stringify({
value: url,
}),
headers: {
"Content-Type": "application/json",
},
})
.then((res) => res.json())
.then((data) => {
if (data.result != "success") {
alert(`Error occured.\n${data.error}`);
} else {
if (closedBy == "background") document.getElementById("profileImageContainer").style.backgroundImage = `url("${url}")`;
else document.getElementById("profileImage").src = url;
}
})
.catch((error) => {
alert(`Error occured.\n${error}`);
console.error(`Error occured.\n${error}`);
});
} else {
iziToast.error({
title: "Invalid image",
message: "Please enter valid image URL.",
});
}
} else {
if (url == "") {
iziToast.error({
title: "Empty URL",
message: "Please enter valid URL.",
});
} else {
iziToast.error({
title: "Invalid URL",
message: "Please enter valid URL.",
});
}
}
loadingOverlayHide();
},
],
],
});
let input = document.createElement("input");
input.type = "file";
input.accept = "image/*";
input.setAttribute("onchange", `picLoaded(event, "${closedBy}")`);
input.click();
loadingOverlayShow();
}
},
});
break;
}
};
const validURL = (str) => {
const pattern = /((?:(?:http?|https?|ftp)[s]*:\/\/)?[a-z0-9-%\/\&=?\.]+\.[a-z]{2,4}\/?([^\s<>\#%"\,\{\}\\|\\\^\[\]`]+)?)/gi;
return !!pattern.test(str);
};

const validImage = (url) => {
const img = new Image();
img.src = url;
return new Promise((resolve) => {
img.onerror = () => resolve(false);
img.onload = () => resolve(true);
});
const picLoaded = async (e, type) => {
const file = e.target.files[0];
if (file.type.indexOf("image") == -1) {
loadingOverlayHide();
return iziToast.error({
title: "Error!",
message: imageError,
});
}
let payload = new FormData();
payload.append("img", file);
payload.append("userid", userid);
fetch(`${url}/profile/${userid}/${type}`, {
credentials: "include",
method: "POST",
body: payload,
})
.then((res) => res.json())
.then((data) => {
loadingOverlayHide();
if (data.result == "failed") {
iziToast.error({
title: "Error!",
message: imageError,
});
} else {
iziToast.success({
title: "Success!",
});
if (type == "background") document.getElementById("profileImageContainer").style.backgroundImage = `url("${data.url}")`;
else {
document.getElementById("profileImage").src = data.url;
document.getElementById("profilePic").src = data.url;
}
}
})
.catch((e) => {
loadingOverlayHide();
iziToast.error({
title: "Error!",
message: imageError,
});
});
};

const scrollEvent = (e) => {
Expand Down
1 change: 1 addition & 0 deletions views/game.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@
const alias = "<%= __('alias') %>".split(",");
const rating = "<%= __('rating') %>";
const nothingHere = "<%= __('nothing_here') %>";
const imageError = "<%= __('image_error') %>";
if (lang == "en") document.body.style.letterSpacing = "-0.3px";
</script>
<script src="/js/iziToast.min.js"></script>
Expand Down

0 comments on commit 0efbb4d

Please sign in to comment.