Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -206,7 +206,7 @@ async def cache_pdf(pdf_path: str):
|
|
| 206 |
except Exception as e:
|
| 207 |
import traceback
|
| 208 |
logger.error(f"PDF ์บ์ฑ ์ค๋ฅ: {str(e)}\n{traceback.format_exc()}")
|
| 209 |
-
if pdf_name in pdf_cache:
|
| 210 |
pdf_cache[pdf_name]["status"] = "error"
|
| 211 |
pdf_cache[pdf_name]["error"] = str(e)
|
| 212 |
|
|
@@ -310,7 +310,6 @@ async def get_cached_pdf(path: str, background_tasks: BackgroundTasks):
|
|
| 310 |
pages = pdf_cache[pdf_name].get("pages", [])
|
| 311 |
total_pages = pdf_cache[pdf_name].get("total_pages", 0)
|
| 312 |
|
| 313 |
-
# ์ผ๋ถ๋ง ์ฒ๋ฆฌ๋ ๊ฒฝ์ฐ์๋ ์ฌ์ฉ ๊ฐ๋ฅํ ํ์ด์ง ์ ๊ณต
|
| 314 |
return {
|
| 315 |
"status": "processing",
|
| 316 |
"progress": progress,
|
|
@@ -417,11 +416,11 @@ HTML = """
|
|
| 417 |
|
| 418 |
body {
|
| 419 |
margin: 0;
|
| 420 |
-
|
|
|
|
|
|
|
| 421 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 422 |
color: var(--text-color);
|
| 423 |
-
background-image: linear-gradient(120deg, var(--tertiary-color) 0%, var(--bg-color) 100%);
|
| 424 |
-
background-attachment: fixed;
|
| 425 |
}
|
| 426 |
|
| 427 |
/* ํค๋ ์ ๋ชฉ ์ ๊ฑฐ ๋ฐ Home ๋ฒํผ ๋ ์ด์ด ์ฒ๋ฆฌ */
|
|
@@ -484,7 +483,7 @@ HTML = """
|
|
| 484 |
opacity: 1;
|
| 485 |
transform: translateX(0);
|
| 486 |
}
|
| 487 |
-
|
| 488 |
#home, #viewerPage {
|
| 489 |
padding-top: 100px;
|
| 490 |
max-width: 1200px;
|
|
@@ -510,7 +509,7 @@ HTML = """
|
|
| 510 |
background: white;
|
| 511 |
margin: 0 10px;
|
| 512 |
font-weight: 500;
|
| 513 |
-
display: flex;
|
| 514 |
align-items: center;
|
| 515 |
box-shadow: var(--shadow-sm);
|
| 516 |
transition: var(--transition);
|
|
@@ -525,7 +524,7 @@ HTML = """
|
|
| 525 |
left: 0;
|
| 526 |
width: 100%;
|
| 527 |
height: 100%;
|
| 528 |
-
background: linear-gradient(120deg, var(--primary-color)
|
| 529 |
opacity: 0.08;
|
| 530 |
z-index: -1;
|
| 531 |
}
|
|
@@ -801,30 +800,30 @@ HTML = """
|
|
| 801 |
}
|
| 802 |
|
| 803 |
/* ํค๋ ๋ก๊ณ ๋ฐ ํ์ดํ */
|
|
|
|
| 804 |
.library-header {
|
| 805 |
position: fixed;
|
| 806 |
-
top: 20px
|
| 807 |
left: 0;
|
| 808 |
right: 0;
|
| 809 |
text-align: center;
|
| 810 |
z-index: 100;
|
| 811 |
-
pointer-events: none;
|
| 812 |
}
|
| 813 |
|
| 814 |
.library-header .title {
|
| 815 |
display: inline-block;
|
| 816 |
-
|
|
|
|
| 817 |
background: rgba(255, 255, 255, 0.85);
|
| 818 |
backdrop-filter: blur(10px);
|
| 819 |
border-radius: 30px;
|
| 820 |
box-shadow: var(--shadow-md);
|
| 821 |
-
font-size: 1.5rem
|
| 822 |
font-weight: 600;
|
| 823 |
background-image: linear-gradient(120deg, #667eea 0%, #764ba2 100%);
|
| 824 |
-webkit-background-clip: text;
|
| 825 |
background-clip: text;
|
| 826 |
color: transparent;
|
| 827 |
-
pointer-events: all;
|
| 828 |
}
|
| 829 |
|
| 830 |
/* ์ ์ง์ ๋ก๋ฉ ํ์ */
|
|
@@ -855,8 +854,8 @@ HTML = """
|
|
| 855 |
}
|
| 856 |
|
| 857 |
.library-header .title {
|
| 858 |
-
font-size:
|
| 859 |
-
padding:
|
| 860 |
}
|
| 861 |
|
| 862 |
.floating-home {
|
|
@@ -884,18 +883,16 @@ HTML = """
|
|
| 884 |
|
| 885 |
<section id="home" class="fade-in">
|
| 886 |
<div class="upload-container">
|
| 887 |
-
<button
|
| 888 |
<i class="fas fa-images"></i> ์ด๋ฏธ์ง ์ถ๊ฐ
|
|
|
|
| 889 |
</button>
|
| 890 |
-
<button
|
| 891 |
<i class="fas fa-file-pdf"></i> PDF ์ถ๊ฐ
|
|
|
|
| 892 |
</button>
|
| 893 |
</div>
|
| 894 |
|
| 895 |
-
<!-- ํ์ผ ์
๋ ฅ ์์๋ฅผ ๋ฒํผ ๋ฐ์ผ๋ก ์ด๋ํ์ฌ ๋ณ๋ ๋ฐฐ์น -->
|
| 896 |
-
<input id="imgInput" type="file" accept="image/*" multiple style="display:none">
|
| 897 |
-
<input id="pdfInput" type="file" accept="application/pdf" style="display:none">
|
| 898 |
-
|
| 899 |
<div class="section-title">๋ด ํ๋ก์ ํธ</div>
|
| 900 |
<div class="grid" id="grid">
|
| 901 |
<!-- ์นด๋๊ฐ ์ฌ๊ธฐ์ ๋์ ์ผ๋ก ์ถ๊ฐ๋ฉ๋๋ค -->
|
|
@@ -928,133 +925,104 @@ HTML = """
|
|
| 928 |
.play().then(a=>a.pause()).catch(()=>{});document.removeEventListener(evt,u,{capture:true});},
|
| 929 |
{once:true,capture:true});
|
| 930 |
});
|
| 931 |
-
|
| 932 |
-
|
| 933 |
-
document.
|
| 934 |
-
|
| 935 |
-
|
| 936 |
-
|
| 937 |
-
|
| 938 |
-
|
| 939 |
-
|
| 940 |
-
if (
|
| 941 |
-
console.log('์ด๋ฏธ์ง
|
| 942 |
-
|
| 943 |
-
|
| 944 |
-
|
| 945 |
-
|
| 946 |
-
|
| 947 |
-
console.error('์ด๋ฏธ์ง ์
๋ก๋ ๋ฒํผ ๋๋ ์
๋ ฅ ์์๋ฅผ ์ฐพ์ ์ ์์');
|
| 948 |
}
|
| 949 |
|
| 950 |
-
// PDF ์
๋ก๋ ๋ฒํผ
|
| 951 |
-
|
| 952 |
-
|
| 953 |
-
|
| 954 |
-
|
| 955 |
-
|
| 956 |
-
|
| 957 |
-
|
| 958 |
pdfInput.click();
|
| 959 |
-
}
|
| 960 |
-
} else {
|
| 961 |
-
console.error('PDF ์
๋ก๋ ๋ฒํผ ๋๋ ์
๋ ฅ ์์๋ฅผ ์ฐพ์ ์ ์์');
|
| 962 |
-
}
|
| 963 |
-
|
| 964 |
-
console.log('PDF/์ด๋ฏธ์ง ์
๋ ฅ ํ๋ ์ด๋ฒคํธ ์ค์ ');
|
| 965 |
-
if (imgInput) {
|
| 966 |
-
imgInput.addEventListener('change', function(e) {
|
| 967 |
-
console.log('์ด๋ฏธ์ง ์
๋ ฅ ๋ณ๊ฒฝ ๊ฐ์ง๋จ');
|
| 968 |
-
handleImageUpload(e);
|
| 969 |
-
});
|
| 970 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 971 |
|
| 972 |
-
|
| 973 |
-
|
| 974 |
-
|
| 975 |
-
handlePdfUpload(e);
|
| 976 |
-
});
|
| 977 |
-
}
|
| 978 |
|
| 979 |
-
|
| 980 |
-
|
| 981 |
-
if (homeButton) {
|
| 982 |
-
homeButton.addEventListener('click', function() {
|
| 983 |
-
console.log('ํ ๋ฒํผ ํด๋ฆญ๋จ');
|
| 984 |
-
homeButtonClicked();
|
| 985 |
-
});
|
| 986 |
-
}
|
| 987 |
|
| 988 |
-
|
| 989 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 990 |
|
| 991 |
-
//
|
| 992 |
-
|
| 993 |
-
}
|
| 994 |
-
|
| 995 |
-
|
| 996 |
-
|
| 997 |
-
const files =
|
| 998 |
-
if
|
| 999 |
|
| 1000 |
-
// ๋ก๋ฉ ํ์ ์ถ๊ฐ
|
| 1001 |
showLoading("์ด๋ฏธ์ง ๋ก๋ฉ ์ค...");
|
| 1002 |
|
| 1003 |
-
const pages =
|
| 1004 |
let done = 0;
|
| 1005 |
-
|
| 1006 |
-
|
| 1007 |
-
|
| 1008 |
-
|
| 1009 |
-
|
| 1010 |
-
pages[index] = {
|
| 1011 |
-
src: event.target.result,
|
| 1012 |
-
thumb: event.target.result
|
| 1013 |
-
};
|
| 1014 |
-
done++;
|
| 1015 |
-
if (done === total) {
|
| 1016 |
save(pages, '์ด๋ฏธ์ง ์ปฌ๋ ์
');
|
| 1017 |
hideLoading();
|
| 1018 |
}
|
| 1019 |
};
|
| 1020 |
-
|
| 1021 |
});
|
| 1022 |
-
}
|
| 1023 |
-
|
| 1024 |
-
|
| 1025 |
-
|
| 1026 |
const file = e.target.files[0];
|
| 1027 |
-
if
|
| 1028 |
|
| 1029 |
-
// ๋ก๋ฉ ํ์ ์ถ๊ฐ
|
| 1030 |
showLoading("PDF ๋ก๋ฉ ์ค...");
|
| 1031 |
|
| 1032 |
-
const
|
| 1033 |
-
|
| 1034 |
-
pdfjsLib.getDocument({data:
|
| 1035 |
const pages = [];
|
| 1036 |
|
| 1037 |
-
for
|
| 1038 |
-
|
| 1039 |
-
|
| 1040 |
-
|
| 1041 |
-
|
| 1042 |
-
|
| 1043 |
-
|
| 1044 |
-
canvas.width = viewport.width;
|
| 1045 |
-
canvas.height = viewport.height;
|
| 1046 |
-
|
| 1047 |
-
await page.render({
|
| 1048 |
-
canvasContext: canvas.getContext('2d'),
|
| 1049 |
-
viewport: viewport
|
| 1050 |
-
}).promise;
|
| 1051 |
-
|
| 1052 |
-
pages.push({
|
| 1053 |
-
src: canvas.toDataURL(),
|
| 1054 |
-
thumb: canvas.toDataURL()
|
| 1055 |
-
});
|
| 1056 |
}
|
| 1057 |
-
|
| 1058 |
hideLoading();
|
| 1059 |
save(pages, file.name.replace('.pdf', ''));
|
| 1060 |
}).catch(error => {
|
|
@@ -1063,56 +1031,9 @@ HTML = """
|
|
| 1063 |
showError("PDF ๋ก๋ฉ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.");
|
| 1064 |
});
|
| 1065 |
};
|
| 1066 |
-
|
| 1067 |
-
}
|
| 1068 |
-
|
| 1069 |
-
// ํ ๋ฒํผ ํด๋ฆญ ์ฒ๋ฆฌ ํจ์
|
| 1070 |
-
function homeButtonClicked() {
|
| 1071 |
-
if (fb) {
|
| 1072 |
-
fb.destroy();
|
| 1073 |
-
viewer.innerHTML = '';
|
| 1074 |
-
fb = null;
|
| 1075 |
-
}
|
| 1076 |
-
toggle(true);
|
| 1077 |
-
|
| 1078 |
-
// ๋ก๋ฉ ์ธ๋์ผ์ดํฐ ์ ๋ฆฌ
|
| 1079 |
-
if (pageLoadingInterval) {
|
| 1080 |
-
clearInterval(pageLoadingInterval);
|
| 1081 |
-
pageLoadingInterval = null;
|
| 1082 |
-
}
|
| 1083 |
-
document.getElementById('loadingPages').style.display = 'none';
|
| 1084 |
-
currentLoadingPdfPath = null;
|
| 1085 |
-
}
|
| 1086 |
-
const d = document.createElement('div');
|
| 1087 |
-
d.className = 'card fade-in';
|
| 1088 |
-
d.onclick = () => open(i);
|
| 1089 |
-
|
| 1090 |
-
// ์ ๋ชฉ ์ฒ๋ฆฌ
|
| 1091 |
-
const displayTitle = title ?
|
| 1092 |
-
(title.length > 15 ? title.substring(0, 15) + '...' : title) :
|
| 1093 |
-
'ํ๋ก์ ํธ ' + (i+1);
|
| 1094 |
-
|
| 1095 |
-
// ์บ์ ์ํ ๋ฑ์ง ์ถ๊ฐ
|
| 1096 |
-
const cachedBadge = isCached ?
|
| 1097 |
-
'<div class="cached-status">์บ์๋จ</div>' : '';
|
| 1098 |
-
|
| 1099 |
-
d.innerHTML = `
|
| 1100 |
-
<div class="card-inner">
|
| 1101 |
-
${cachedBadge}
|
| 1102 |
-
<img src="${thumb}" alt="${displayTitle}" loading="lazy">
|
| 1103 |
-
<p title="${title || 'ํ๋ก์ ํธ ' + (i+1)}">${displayTitle}</p>
|
| 1104 |
-
</div>
|
| 1105 |
-
`;
|
| 1106 |
-
grid.appendChild(d);
|
| 1107 |
-
|
| 1108 |
-
// ํ๋ก์ ํธ๊ฐ ์์ผ๋ฉด 'ํ๋ก์ ํธ ์์' ๋ฉ์์ง ์จ๊ธฐ๊ธฐ
|
| 1109 |
-
$id('noProjects').style.display = 'none';
|
| 1110 |
-
}
|
| 1111 |
|
| 1112 |
-
/* โโ ์ ํธ โโ */
|
| 1113 |
-
function $id(id){return document.getElementById(id)}
|
| 1114 |
-
|
| 1115 |
-
/* โโ ํ๋ก์ ํธ ์ ์ฅ โโ */
|
| 1116 |
function save(pages, title, isCached = false){
|
| 1117 |
const id=projects.push(pages)-1;
|
| 1118 |
addCard(id, pages[0].thumb, title, isCached);
|
|
@@ -1121,7 +1042,6 @@ HTML = """
|
|
| 1121 |
/* โโ ์๋ฒ PDF ๋ก๋ ๋ฐ ์บ์ ์ํ ํ์ธ โโ */
|
| 1122 |
async function loadServerPDFs() {
|
| 1123 |
try {
|
| 1124 |
-
// ๋ก๋ฉ ํ์ ์ถ๊ฐ
|
| 1125 |
if (document.querySelectorAll('.card').length === 0) {
|
| 1126 |
showLoading("๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋ฉ ์ค...");
|
| 1127 |
}
|
|
@@ -1140,16 +1060,15 @@ HTML = """
|
|
| 1140 |
return;
|
| 1141 |
}
|
| 1142 |
|
| 1143 |
-
// ์๋ฒ PDF ๋ก๋ ๋ฐ ์ธ๋ค์ผ ์์ฑ (๋ณ๋ ฌ ์ฒ๋ฆฌ๋ก ์ต์ ํ)
|
| 1144 |
const thumbnailPromises = serverProjects.map(async (project, index) => {
|
| 1145 |
-
updateLoading(
|
| 1146 |
|
| 1147 |
const pdfName = project.name;
|
| 1148 |
const isCached = cacheStatus[pdfName] && cacheStatus[pdfName].status === "completed";
|
| 1149 |
|
| 1150 |
try {
|
| 1151 |
// ์ธ๋ค์ผ ๊ฐ์ ธ์ค๊ธฐ
|
| 1152 |
-
const response = await fetch(
|
| 1153 |
const data = await response.json();
|
| 1154 |
|
| 1155 |
if(data.thumbnail) {
|
|
@@ -1159,31 +1078,23 @@ HTML = """
|
|
| 1159 |
path: project.path,
|
| 1160 |
cached: isCached
|
| 1161 |
}];
|
| 1162 |
-
|
| 1163 |
-
return {
|
| 1164 |
-
pages,
|
| 1165 |
-
name: project.name,
|
| 1166 |
-
isCached
|
| 1167 |
-
};
|
| 1168 |
}
|
| 1169 |
} catch (err) {
|
| 1170 |
-
console.error(
|
| 1171 |
}
|
| 1172 |
|
| 1173 |
return null;
|
| 1174 |
});
|
| 1175 |
|
| 1176 |
-
// ๋ชจ๋ ์ธ๋ค์ผ ์์ฒญ ๊ธฐ๋ค๋ฆฌ๊ธฐ
|
| 1177 |
const results = await Promise.all(thumbnailPromises);
|
| 1178 |
|
| 1179 |
-
// ์ฑ๊ณต์ ์ผ๋ก ๊ฐ์ ธ์จ ๊ฒฐ๊ณผ๋ง ํ์
|
| 1180 |
results.filter(result => result !== null).forEach(result => {
|
| 1181 |
save(result.pages, result.name, result.isCached);
|
| 1182 |
});
|
| 1183 |
|
| 1184 |
hideLoading();
|
| 1185 |
|
| 1186 |
-
// ํ๋ก์ ํธ๊ฐ ์์ ๊ฒฝ์ฐ ๋ฉ์์ง ํ์
|
| 1187 |
if (document.querySelectorAll('.card').length === 0) {
|
| 1188 |
$id('noProjects').style.display = 'block';
|
| 1189 |
}
|
|
@@ -1208,7 +1119,6 @@ HTML = """
|
|
| 1208 |
const pdfPath = projects[i][0].path;
|
| 1209 |
const pdfName = pdfPath.split('/').pop().replace('.pdf', '');
|
| 1210 |
|
| 1211 |
-
// ์บ์ ์ํ ๋ฑ์ง ์
๋ฐ์ดํธ
|
| 1212 |
let badgeEl = cards[i].querySelector('.cached-status');
|
| 1213 |
|
| 1214 |
if(cacheStatus[pdfName] && cacheStatus[pdfName].status === "completed") {
|
|
@@ -1228,7 +1138,7 @@ HTML = """
|
|
| 1228 |
badgeEl.className = 'cached-status';
|
| 1229 |
cards[i].querySelector('.card-inner')?.appendChild(badgeEl);
|
| 1230 |
}
|
| 1231 |
-
badgeEl.textContent =
|
| 1232 |
badgeEl.style.background = 'var(--secondary-color)';
|
| 1233 |
}
|
| 1234 |
}
|
|
@@ -1237,27 +1147,21 @@ HTML = """
|
|
| 1237 |
// ํ์ฌ ๋ก๋ฉ ์ค์ธ PDF๊ฐ ์์ผ๋ฉด ์ํ ํ์ธ
|
| 1238 |
if (currentLoadingPdfPath && pageLoadingInterval) {
|
| 1239 |
const pdfName = currentLoadingPdfPath.split('/').pop().replace('.pdf', '');
|
| 1240 |
-
|
| 1241 |
if (cacheStatus[pdfName]) {
|
| 1242 |
const status = cacheStatus[pdfName].status;
|
| 1243 |
const progress = cacheStatus[pdfName].progress || 0;
|
| 1244 |
|
| 1245 |
if (status === "completed") {
|
| 1246 |
-
// ์บ์ฑ ์๋ฃ ์
|
| 1247 |
clearInterval(pageLoadingInterval);
|
| 1248 |
$id('loadingPages').style.display = 'none';
|
| 1249 |
currentLoadingPdfPath = null;
|
| 1250 |
-
|
| 1251 |
-
// ์๋ฃ๋ ์บ์๋ก ํ๋ฆฝ๋ถ ๋ค์ ๋ก๋
|
| 1252 |
refreshFlipBook();
|
| 1253 |
} else if (status === "processing") {
|
| 1254 |
-
// ์งํ ์ค์ผ ๋ ํ์ ์
๋ฐ์ดํธ
|
| 1255 |
$id('loadingPages').style.display = 'block';
|
| 1256 |
-
$id('loadingPagesCount').textContent =
|
| 1257 |
}
|
| 1258 |
}
|
| 1259 |
}
|
| 1260 |
-
|
| 1261 |
} catch(error) {
|
| 1262 |
console.error('์บ์ ์ํ ํ์ธ ์ค๋ฅ:', error);
|
| 1263 |
}
|
|
@@ -1268,27 +1172,20 @@ HTML = """
|
|
| 1268 |
toggle(false);
|
| 1269 |
const pages = projects[i];
|
| 1270 |
|
| 1271 |
-
// ๊ธฐ์กด FlipBook ์ ๋ฆฌ
|
| 1272 |
if(fb) {
|
| 1273 |
fb.destroy();
|
| 1274 |
viewer.innerHTML = '';
|
| 1275 |
}
|
| 1276 |
|
| 1277 |
-
// ์๋ฒ PDF ๋๋ ๋ก์ปฌ ํ๋ก์ ํธ ์ฒ๋ฆฌ
|
| 1278 |
if(pages[0].path) {
|
| 1279 |
const pdfPath = pages[0].path;
|
| 1280 |
-
|
| 1281 |
-
// ์ ์ง์ ๋ก๋ฉ ํ๋๊ทธ ์ด๊ธฐํ
|
| 1282 |
let progressiveLoading = false;
|
| 1283 |
currentLoadingPdfPath = pdfPath;
|
| 1284 |
|
| 1285 |
-
// ์บ์ ์ฌ๋ถ ํ์ธ
|
| 1286 |
if(pages[0].cached) {
|
| 1287 |
-
// ์บ์๋ PDF ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
|
| 1288 |
showLoading("์บ์๋ PDF ๋ก๋ฉ ์ค...");
|
| 1289 |
-
|
| 1290 |
try {
|
| 1291 |
-
const response = await fetch(
|
| 1292 |
const cachedData = await response.json();
|
| 1293 |
|
| 1294 |
if(cachedData.status === "completed" && cachedData.pages) {
|
|
@@ -1297,29 +1194,22 @@ HTML = """
|
|
| 1297 |
currentLoadingPdfPath = null;
|
| 1298 |
return;
|
| 1299 |
} else if(cachedData.status === "processing" && cachedData.pages && cachedData.pages.length > 0) {
|
| 1300 |
-
// ์ผ๋ถ ํ์ด์ง๊ฐ ์ด๋ฏธ ์ฒ๋ฆฌ๋ ๊ฒฝ์ฐ ์ ์ง์ ๋ก๋ฉ ์ฌ์ฉ
|
| 1301 |
hideLoading();
|
| 1302 |
createFlipBook(cachedData.pages);
|
| 1303 |
progressiveLoading = true;
|
| 1304 |
-
|
| 1305 |
-
// ์ ์ง์ ๋ก๋ฉ ์ค์์ ํ์
|
| 1306 |
startProgressiveLoadingIndicator(cachedData.progress, cachedData.total_pages);
|
| 1307 |
}
|
| 1308 |
} catch(error) {
|
| 1309 |
console.error("์บ์ ๋ฐ์ดํฐ ๋ก๋ ์ค๋ฅ:", error);
|
| 1310 |
-
// ์บ์ ๋ก๋ฉ ์คํจ ์ ์๋ณธ PDF๋ก ๋์ฒด
|
| 1311 |
}
|
| 1312 |
}
|
| 1313 |
|
| 1314 |
-
if
|
| 1315 |
-
// ์บ์๊ฐ ์๊ฑฐ๋ ๋ก๋ฉ ์คํจ ์ ์๋ฒ PDF ๋ก๋
|
| 1316 |
showLoading("PDF ์ค๋น ์ค...");
|
| 1317 |
-
|
| 1318 |
try {
|
| 1319 |
-
const response = await fetch(
|
| 1320 |
const data = await response.json();
|
| 1321 |
|
| 1322 |
-
// ์บ์๋ก ๋ฆฌ๋ค์ด๋ ํธ๋ ๊ฒฝ์ฐ
|
| 1323 |
if(data.redirect) {
|
| 1324 |
const redirectRes = await fetch(data.redirect);
|
| 1325 |
const cachedData = await redirectRes.json();
|
|
@@ -1330,20 +1220,15 @@ HTML = """
|
|
| 1330 |
currentLoadingPdfPath = null;
|
| 1331 |
return;
|
| 1332 |
} else if(cachedData.status === "processing" && cachedData.pages && cachedData.pages.length > 0) {
|
| 1333 |
-
// ์ผ๋ถ ํ์ด์ง๊ฐ ์ด๋ฏธ ์ฒ๋ฆฌ๋ ๊ฒฝ์ฐ ์ ์ง์ ๋ก๋ฉ ์ฌ์ฉ
|
| 1334 |
hideLoading();
|
| 1335 |
createFlipBook(cachedData.pages);
|
| 1336 |
-
|
| 1337 |
-
// ์ ์ง์ ๋ก๋ฉ ์ค์์ ํ์
|
| 1338 |
startProgressiveLoadingIndicator(cachedData.progress, cachedData.total_pages);
|
| 1339 |
return;
|
| 1340 |
}
|
| 1341 |
}
|
| 1342 |
|
| 1343 |
-
|
| 1344 |
-
const pdfResponse = await fetch(`/api/pdf-content?path=${encodeURIComponent(pdfPath)}`);
|
| 1345 |
|
| 1346 |
-
// JSON ์๋ต์ธ ๊ฒฝ์ฐ (๋ฆฌ๋ค์ด๋ ํธ ๋ฑ)
|
| 1347 |
try {
|
| 1348 |
const jsonData = await pdfResponse.clone().json();
|
| 1349 |
if (jsonData.redirect) {
|
|
@@ -1353,7 +1238,6 @@ HTML = """
|
|
| 1353 |
if(cachedData.pages && cachedData.pages.length > 0) {
|
| 1354 |
hideLoading();
|
| 1355 |
createFlipBook(cachedData.pages);
|
| 1356 |
-
|
| 1357 |
if(cachedData.status === "processing") {
|
| 1358 |
startProgressiveLoadingIndicator(cachedData.progress, cachedData.total_pages);
|
| 1359 |
} else {
|
|
@@ -1363,78 +1247,63 @@ HTML = """
|
|
| 1363 |
}
|
| 1364 |
}
|
| 1365 |
} catch (e) {
|
| 1366 |
-
// JSON ํ์ฑ ์คํจ
|
| 1367 |
}
|
| 1368 |
|
| 1369 |
-
// ArrayBuffer ํํ์ PDF ๋ฐ์ดํฐ
|
| 1370 |
const pdfData = await pdfResponse.arrayBuffer();
|
| 1371 |
-
|
| 1372 |
-
// PDF ๋ก๋ ๋ฐ ํ์ด์ง ๋ ๋๋ง
|
| 1373 |
const pdf = await pdfjsLib.getDocument({data: pdfData}).promise;
|
| 1374 |
const pdfPages = [];
|
| 1375 |
|
| 1376 |
-
for(let p
|
| 1377 |
-
updateLoading(
|
| 1378 |
-
|
| 1379 |
const pg = await pdf.getPage(p);
|
| 1380 |
const vp = pg.getViewport({scale: 1});
|
| 1381 |
const c = document.createElement('canvas');
|
| 1382 |
c.width = vp.width;
|
| 1383 |
c.height = vp.height;
|
| 1384 |
-
|
| 1385 |
await pg.render({canvasContext: c.getContext('2d'), viewport: vp}).promise;
|
| 1386 |
pdfPages.push({src: c.toDataURL(), thumb: c.toDataURL()});
|
| 1387 |
}
|
| 1388 |
-
|
| 1389 |
hideLoading();
|
| 1390 |
createFlipBook(pdfPages);
|
| 1391 |
currentLoadingPdfPath = null;
|
| 1392 |
-
|
| 1393 |
} catch(error) {
|
| 1394 |
-
console.error('PDF ์ฒ๋ฆฌ ์ค
|
| 1395 |
hideLoading();
|
| 1396 |
showError("PDF๋ฅผ ๋ก๋ํ๋ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.");
|
| 1397 |
currentLoadingPdfPath = null;
|
| 1398 |
}
|
| 1399 |
}
|
| 1400 |
} else {
|
| 1401 |
-
// ๋ก์ปฌ ์
๋ก๋๋ ํ๋ก์ ํธ ์คํ
|
| 1402 |
createFlipBook(pages);
|
| 1403 |
currentLoadingPdfPath = null;
|
| 1404 |
}
|
| 1405 |
}
|
| 1406 |
|
| 1407 |
-
/* โโ ์ ์ง์ ๋ก๋ฉ ์ธ๋์ผ์ดํฐ ์์ โโ */
|
| 1408 |
function startProgressiveLoadingIndicator(progress, totalPages) {
|
| 1409 |
-
// ์งํ ์ํ ํ์ ํ์ฑํ
|
| 1410 |
$id('loadingPages').style.display = 'block';
|
| 1411 |
-
$id('loadingPagesCount').textContent =
|
| 1412 |
|
| 1413 |
-
// ๊ธฐ์กด ์ธํฐ๋ฒ ์ ๊ฑฐ
|
| 1414 |
if (pageLoadingInterval) {
|
| 1415 |
clearInterval(pageLoadingInterval);
|
| 1416 |
}
|
| 1417 |
-
|
| 1418 |
-
// ์ฃผ๊ธฐ์ ์ผ๋ก ์บ์ ์ํ ํ์ธ (2์ด๋ง๋ค)
|
| 1419 |
pageLoadingInterval = setInterval(async () => {
|
| 1420 |
if (!currentLoadingPdfPath) {
|
| 1421 |
clearInterval(pageLoadingInterval);
|
| 1422 |
$id('loadingPages').style.display = 'none';
|
| 1423 |
return;
|
| 1424 |
}
|
| 1425 |
-
|
| 1426 |
try {
|
| 1427 |
-
const response = await fetch(
|
| 1428 |
const status = await response.json();
|
| 1429 |
|
| 1430 |
-
// ์ํ ์
๋ฐ์ดํธ
|
| 1431 |
if (status.status === "completed") {
|
| 1432 |
clearInterval(pageLoadingInterval);
|
| 1433 |
$id('loadingPages').style.display = 'none';
|
| 1434 |
-
refreshFlipBook();
|
| 1435 |
currentLoadingPdfPath = null;
|
| 1436 |
} else if (status.status === "processing") {
|
| 1437 |
-
$id('loadingPagesCount').textContent =
|
| 1438 |
}
|
| 1439 |
} catch (e) {
|
| 1440 |
console.error("์บ์ ์ํ ํ์ธ ์ค๋ฅ:", e);
|
|
@@ -1442,20 +1311,15 @@ HTML = """
|
|
| 1442 |
}, 1000);
|
| 1443 |
}
|
| 1444 |
|
| 1445 |
-
/* โโ ํ๋ฆฝ๋ถ ์๋ก๊ณ ์นจ โโ */
|
| 1446 |
async function refreshFlipBook() {
|
| 1447 |
if (!currentLoadingPdfPath || !fb) return;
|
| 1448 |
-
|
| 1449 |
try {
|
| 1450 |
-
const response = await fetch(
|
| 1451 |
const cachedData = await response.json();
|
| 1452 |
|
| 1453 |
if(cachedData.status === "completed" && cachedData.pages) {
|
| 1454 |
-
// ๊ธฐ์กด ํ๋ฆฝ๋ถ ์ ๋ฆฌ
|
| 1455 |
fb.destroy();
|
| 1456 |
viewer.innerHTML = '';
|
| 1457 |
-
|
| 1458 |
-
// ์ ๋ฐ์ดํฐ๋ก ์ฌ์์ฑ
|
| 1459 |
createFlipBook(cachedData.pages);
|
| 1460 |
currentLoadingPdfPath = null;
|
| 1461 |
}
|
|
@@ -1466,47 +1330,39 @@ HTML = """
|
|
| 1466 |
|
| 1467 |
function createFlipBook(pages) {
|
| 1468 |
console.log('FlipBook ์์ฑ ์์. ํ์ด์ง ์:', pages.length);
|
| 1469 |
-
|
| 1470 |
try {
|
| 1471 |
-
// ํ๋ฉด ๋น์จ ๊ณ์ฐ
|
| 1472 |
const calculateAspectRatio = () => {
|
| 1473 |
const windowWidth = window.innerWidth;
|
| 1474 |
const windowHeight = window.innerHeight;
|
| 1475 |
const aspectRatio = windowWidth / windowHeight;
|
| 1476 |
|
| 1477 |
-
// ๋๋น ๋๋ ๋์ด ๊ธฐ์ค์ผ๋ก ์ต๋ 90% ์ ํ
|
| 1478 |
let width, height;
|
| 1479 |
-
if (aspectRatio > 1) {
|
| 1480 |
height = Math.min(windowHeight * 0.9, windowHeight - 40);
|
| 1481 |
-
width = height * aspectRatio * 0.8;
|
| 1482 |
if (width > windowWidth * 0.9) {
|
| 1483 |
width = windowWidth * 0.9;
|
| 1484 |
height = width / (aspectRatio * 0.8);
|
| 1485 |
}
|
| 1486 |
-
} else {
|
| 1487 |
width = Math.min(windowWidth * 0.9, windowWidth - 40);
|
| 1488 |
-
height = width / aspectRatio * 0.9;
|
| 1489 |
if (height > windowHeight * 0.9) {
|
| 1490 |
height = windowHeight * 0.9;
|
| 1491 |
width = height * aspectRatio * 0.9;
|
| 1492 |
}
|
| 1493 |
}
|
| 1494 |
-
|
| 1495 |
-
// ์ต์ ์ฌ์ด์ฆ ๋ฐํ
|
| 1496 |
return {
|
| 1497 |
width: Math.round(width),
|
| 1498 |
height: Math.round(height)
|
| 1499 |
};
|
| 1500 |
};
|
| 1501 |
|
| 1502 |
-
// ์ด๊ธฐ ํ๋ฉด ๋น์จ ๊ณ์ฐ
|
| 1503 |
const size = calculateAspectRatio();
|
| 1504 |
viewer.style.width = size.width + 'px';
|
| 1505 |
viewer.style.height = size.height + 'px';
|
| 1506 |
|
| 1507 |
-
// ํ์ด์ง ๋ฐ์ดํฐ ์ ์ (๋น ํ์ด์ง ์ฒ๋ฆฌ)
|
| 1508 |
const validPages = pages.map(page => {
|
| 1509 |
-
// src๊ฐ ์๋ ํ์ด์ง๋ ๋ก๋ฉ ์ค ์ด๋ฏธ์ง๋ก ๋์ฒด
|
| 1510 |
if (!page || !page.src) {
|
| 1511 |
return {
|
| 1512 |
src: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjVmNWY1Ii8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iIGZpbGw9IiM1NTUiPkxvYWRpbmcuLi48L3RleHQ+PC9zdmc+',
|
|
@@ -1522,7 +1378,6 @@ HTML = """
|
|
| 1522 |
autoSize: true,
|
| 1523 |
flipDuration: 800,
|
| 1524 |
backgroundColor: '#fff',
|
| 1525 |
-
/* ๐ ๋ด์ฅ ์ฌ์ด๋ */
|
| 1526 |
sound: true,
|
| 1527 |
assets: {flipMp3: 'static/turnPage2.mp3', hardFlipMp3: 'static/turnPage2.mp3'},
|
| 1528 |
controlsProps: {
|
|
@@ -1537,22 +1392,21 @@ HTML = """
|
|
| 1537 |
enableAnnotation: false,
|
| 1538 |
enableSound: true,
|
| 1539 |
enableLightbox: false,
|
| 1540 |
-
layout: 10,
|
| 1541 |
-
skin: 'light',
|
| 1542 |
-
autoNavigationTime: 3600,
|
| 1543 |
-
hideControls: false,
|
| 1544 |
-
paddingTop: 10,
|
| 1545 |
-
paddingLeft: 10,
|
| 1546 |
-
paddingRight: 10,
|
| 1547 |
-
paddingBottom: 10,
|
| 1548 |
-
pageTextureSize: 1024,
|
| 1549 |
-
thumbnails: true,
|
| 1550 |
-
autoHideControls: false,
|
| 1551 |
-
controlsTimeout: 8000
|
| 1552 |
}
|
| 1553 |
});
|
| 1554 |
|
| 1555 |
-
// ํ๋ฉด ํฌ๊ธฐ ๋ณ๊ฒฝ ์ FlipBook ํฌ๊ธฐ ์กฐ์
|
| 1556 |
window.addEventListener('resize', () => {
|
| 1557 |
if (fb) {
|
| 1558 |
const newSize = calculateAspectRatio();
|
|
@@ -1562,10 +1416,8 @@ HTML = """
|
|
| 1562 |
}
|
| 1563 |
});
|
| 1564 |
|
| 1565 |
-
// FlipBook ์์ฑ ํ ์ปจํธ๋กค๋ฐ ๊ฐ์ ํ์
|
| 1566 |
setTimeout(() => {
|
| 1567 |
try {
|
| 1568 |
-
// ์ปจํธ๋กค๋ฐ ๊ด๋ จ ์์ ์ฐพ๊ธฐ ๋ฐ ์คํ์ผ ์ ์ฉ
|
| 1569 |
const menuBars = document.querySelectorAll('.flipbook-container .fb3d-menu-bar');
|
| 1570 |
if (menuBars && menuBars.length > 0) {
|
| 1571 |
menuBars.forEach(menuBar => {
|
|
@@ -1587,15 +1439,26 @@ HTML = """
|
|
| 1587 |
}
|
| 1588 |
}
|
| 1589 |
|
| 1590 |
-
|
| 1591 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1592 |
|
| 1593 |
function toggle(showHome){
|
| 1594 |
-
$id('home').style.display=showHome?'block':'none';
|
| 1595 |
-
$id('viewerPage').style.display=showHome?'none':'block';
|
| 1596 |
-
$id('homeButton').style.display=showHome?'none':'block';
|
| 1597 |
|
| 1598 |
-
// ๋ทฐ์ด ๋ชจ๋์ผ ๋ ์คํ์ผ ๋ณ๊ฒฝ
|
| 1599 |
if(!showHome) {
|
| 1600 |
document.body.classList.add('viewer-mode');
|
| 1601 |
} else {
|
|
@@ -1603,11 +1466,8 @@ HTML = """
|
|
| 1603 |
}
|
| 1604 |
}
|
| 1605 |
|
| 1606 |
-
/* -- ๋ก๋ฉ ๋ฐ ์ค๋ฅ ํ์ -- */
|
| 1607 |
function showLoading(message, progress = -1) {
|
| 1608 |
-
// ๊ธฐ์กด ๋ก๋ฉ ์ปจํ
์ด๋๊ฐ ์๋ค๋ฉด ์ ๊ฑฐ
|
| 1609 |
hideLoading();
|
| 1610 |
-
|
| 1611 |
const loadingContainer = document.createElement('div');
|
| 1612 |
loadingContainer.className = 'loading-container fade-in';
|
| 1613 |
loadingContainer.id = 'loadingContainer';
|
|
@@ -1638,7 +1498,6 @@ HTML = """
|
|
| 1638 |
|
| 1639 |
if (progress >= 0) {
|
| 1640 |
let progressBar = $id('progressBar');
|
| 1641 |
-
|
| 1642 |
if (!progressBar) {
|
| 1643 |
const loadingContainer = $id('loadingContainer');
|
| 1644 |
if (loadingContainer) {
|
|
@@ -1649,7 +1508,7 @@ HTML = """
|
|
| 1649 |
progressBar = $id('progressBar');
|
| 1650 |
}
|
| 1651 |
} else {
|
| 1652 |
-
progressBar.style.width =
|
| 1653 |
}
|
| 1654 |
}
|
| 1655 |
}
|
|
@@ -1662,7 +1521,6 @@ HTML = """
|
|
| 1662 |
}
|
| 1663 |
|
| 1664 |
function showError(message) {
|
| 1665 |
-
// ๊ธฐ์กด ์ค๋ฅ ๋ฉ์์ง๊ฐ ์๋ค๋ฉด ์ ๊ฑฐ
|
| 1666 |
const existingError = $id('errorContainer');
|
| 1667 |
if (existingError) {
|
| 1668 |
existingError.remove();
|
|
@@ -1678,12 +1536,10 @@ HTML = """
|
|
| 1678 |
|
| 1679 |
document.body.appendChild(errorContainer);
|
| 1680 |
|
| 1681 |
-
// ํ์ธ ๋ฒํผ ํด๋ฆญ ์ด๋ฒคํธ
|
| 1682 |
$id('errorCloseBtn').onclick = () => {
|
| 1683 |
errorContainer.remove();
|
| 1684 |
};
|
| 1685 |
|
| 1686 |
-
// 5์ด ํ ์๋์ผ๋ก ๋ซ๊ธฐ
|
| 1687 |
setTimeout(() => {
|
| 1688 |
if ($id('errorContainer')) {
|
| 1689 |
$id('errorContainer').remove();
|
|
@@ -1691,7 +1547,15 @@ HTML = """
|
|
| 1691 |
}, 5000);
|
| 1692 |
}
|
| 1693 |
|
| 1694 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1695 |
</script>
|
| 1696 |
</body>
|
| 1697 |
</html>
|
|
@@ -1702,4 +1566,4 @@ async def root():
|
|
| 1702 |
return get_html_content()
|
| 1703 |
|
| 1704 |
if __name__ == "__main__":
|
| 1705 |
-
uvicorn.run("app:app", host="0.0.0.0", port=int(os.getenv("PORT", 7860)))
|
|
|
|
| 206 |
except Exception as e:
|
| 207 |
import traceback
|
| 208 |
logger.error(f"PDF ์บ์ฑ ์ค๋ฅ: {str(e)}\n{traceback.format_exc()}")
|
| 209 |
+
if 'pdf_name' in locals() and pdf_name in pdf_cache:
|
| 210 |
pdf_cache[pdf_name]["status"] = "error"
|
| 211 |
pdf_cache[pdf_name]["error"] = str(e)
|
| 212 |
|
|
|
|
| 310 |
pages = pdf_cache[pdf_name].get("pages", [])
|
| 311 |
total_pages = pdf_cache[pdf_name].get("total_pages", 0)
|
| 312 |
|
|
|
|
| 313 |
return {
|
| 314 |
"status": "processing",
|
| 315 |
"progress": progress,
|
|
|
|
| 416 |
|
| 417 |
body {
|
| 418 |
margin: 0;
|
| 419 |
+
/* โผ ๊ณ ๊ธ์ง ๋ธ๋ฃจ ๊ณ์ด ๊ทธ๋ผ๋์์ด์
์ผ๋ก ๋ณ๊ฒฝ */
|
| 420 |
+
background-image: linear-gradient(135deg, #0f2027 0%, #203a43 50%, #2c5364 100%);
|
| 421 |
+
background-attachment: fixed;
|
| 422 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 423 |
color: var(--text-color);
|
|
|
|
|
|
|
| 424 |
}
|
| 425 |
|
| 426 |
/* ํค๋ ์ ๋ชฉ ์ ๊ฑฐ ๋ฐ Home ๋ฒํผ ๋ ์ด์ด ์ฒ๋ฆฌ */
|
|
|
|
| 483 |
opacity: 1;
|
| 484 |
transform: translateX(0);
|
| 485 |
}
|
| 486 |
+
|
| 487 |
#home, #viewerPage {
|
| 488 |
padding-top: 100px;
|
| 489 |
max-width: 1200px;
|
|
|
|
| 509 |
background: white;
|
| 510 |
margin: 0 10px;
|
| 511 |
font-weight: 500;
|
| 512 |
+
display: inline-flex;
|
| 513 |
align-items: center;
|
| 514 |
box-shadow: var(--shadow-sm);
|
| 515 |
transition: var(--transition);
|
|
|
|
| 524 |
left: 0;
|
| 525 |
width: 100%;
|
| 526 |
height: 100%;
|
| 527 |
+
background: linear-gradient(120deg, var(--primary-color), var(--secondary-color));
|
| 528 |
opacity: 0.08;
|
| 529 |
z-index: -1;
|
| 530 |
}
|
|
|
|
| 800 |
}
|
| 801 |
|
| 802 |
/* ํค๋ ๋ก๊ณ ๋ฐ ํ์ดํ */
|
| 803 |
+
/* โผ pointer-events: none ์ ๊ฑฐ, ๋์ด์ ํจ๋ฉ ์กฐ์ ํ์ฌ ์ ๋ชฉ์ ๋ ์๋ก */
|
| 804 |
.library-header {
|
| 805 |
position: fixed;
|
| 806 |
+
top: 10px; /* ๊ธฐ์กด 20px -> 10px์ผ๋ก */
|
| 807 |
left: 0;
|
| 808 |
right: 0;
|
| 809 |
text-align: center;
|
| 810 |
z-index: 100;
|
|
|
|
| 811 |
}
|
| 812 |
|
| 813 |
.library-header .title {
|
| 814 |
display: inline-block;
|
| 815 |
+
/* ๋์ด ์ค์ด๊ธฐ ์ํ ํจ๋ฉ/ํฐํธ ํฌ๊ธฐ ์กฐ์ */
|
| 816 |
+
padding: 8px 20px; /* ๊ธฐ์กด 12px 30px -> 8px 20px */
|
| 817 |
background: rgba(255, 255, 255, 0.85);
|
| 818 |
backdrop-filter: blur(10px);
|
| 819 |
border-radius: 30px;
|
| 820 |
box-shadow: var(--shadow-md);
|
| 821 |
+
font-size: 1.2rem; /* ๊ธฐ์กด 1.5rem -> 1.2rem */
|
| 822 |
font-weight: 600;
|
| 823 |
background-image: linear-gradient(120deg, #667eea 0%, #764ba2 100%);
|
| 824 |
-webkit-background-clip: text;
|
| 825 |
background-clip: text;
|
| 826 |
color: transparent;
|
|
|
|
| 827 |
}
|
| 828 |
|
| 829 |
/* ์ ์ง์ ๋ก๋ฉ ํ์ */
|
|
|
|
| 854 |
}
|
| 855 |
|
| 856 |
.library-header .title {
|
| 857 |
+
font-size: 1rem;
|
| 858 |
+
padding: 6px 16px;
|
| 859 |
}
|
| 860 |
|
| 861 |
.floating-home {
|
|
|
|
| 883 |
|
| 884 |
<section id="home" class="fade-in">
|
| 885 |
<div class="upload-container">
|
| 886 |
+
<button class="upload" id="imageUploadBtn">
|
| 887 |
<i class="fas fa-images"></i> ์ด๋ฏธ์ง ์ถ๊ฐ
|
| 888 |
+
<input id="imgInput" type="file" accept="image/*" multiple hidden>
|
| 889 |
</button>
|
| 890 |
+
<button class="upload" id="pdfUploadBtn">
|
| 891 |
<i class="fas fa-file-pdf"></i> PDF ์ถ๊ฐ
|
| 892 |
+
<input id="pdfInput" type="file" accept="application/pdf" hidden>
|
| 893 |
</button>
|
| 894 |
</div>
|
| 895 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 896 |
<div class="section-title">๋ด ํ๋ก์ ํธ</div>
|
| 897 |
<div class="grid" id="grid">
|
| 898 |
<!-- ์นด๋๊ฐ ์ฌ๊ธฐ์ ๋์ ์ผ๋ก ์ถ๊ฐ๋ฉ๋๋ค -->
|
|
|
|
| 925 |
.play().then(a=>a.pause()).catch(()=>{});document.removeEventListener(evt,u,{capture:true});},
|
| 926 |
{once:true,capture:true});
|
| 927 |
});
|
| 928 |
+
|
| 929 |
+
/* โโ ์ ํธ โโ */
|
| 930 |
+
function $id(id){return document.getElementById(id)}
|
| 931 |
+
|
| 932 |
+
// ์ง์ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ค์ (์
๋ก๋ ๋ฒํผ ํด๋ฆญ์ ํ์ผ ์ ํ์ฐฝ ์ด๊ธฐ)
|
| 933 |
+
function setupDirectEvents() {
|
| 934 |
+
// ์ด๋ฏธ์ง ์
๋ก๋ ๋ฒํผ
|
| 935 |
+
const imageBtn = $id('imageUploadBtn');
|
| 936 |
+
const imageInput = $id('imgInput');
|
| 937 |
+
if (imageBtn && imageInput) {
|
| 938 |
+
console.log('์ด๋ฏธ์ง ์
๋ก๋ ๋ฒํผ ์ด๋ฒคํธ ์ค์ ');
|
| 939 |
+
imageBtn.onclick = function(e) {
|
| 940 |
+
e.preventDefault();
|
| 941 |
+
e.stopPropagation();
|
| 942 |
+
imageInput.click();
|
| 943 |
+
};
|
|
|
|
| 944 |
}
|
| 945 |
|
| 946 |
+
// PDF ์
๋ก๋ ๋ฒํผ
|
| 947 |
+
const pdfBtn = $id('pdfUploadBtn');
|
| 948 |
+
const pdfInput = $id('pdfInput');
|
| 949 |
+
if (pdfBtn && pdfInput) {
|
| 950 |
+
console.log('PDF ์
๋ก๋ ๋ฒํผ ์ด๋ฒคํธ ์ค์ ');
|
| 951 |
+
pdfBtn.onclick = function(e) {
|
| 952 |
+
e.preventDefault();
|
| 953 |
+
e.stopPropagation();
|
| 954 |
pdfInput.click();
|
| 955 |
+
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 956 |
}
|
| 957 |
+
}
|
| 958 |
+
|
| 959 |
+
function addCard(i, thumb, title, isCached = false) {
|
| 960 |
+
const d = document.createElement('div');
|
| 961 |
+
d.className = 'card fade-in';
|
| 962 |
+
d.onclick = () => open(i);
|
| 963 |
|
| 964 |
+
const displayTitle = title ?
|
| 965 |
+
(title.length > 15 ? title.substring(0, 15) + '...' : title) :
|
| 966 |
+
'ํ๋ก์ ํธ ' + (i+1);
|
|
|
|
|
|
|
|
|
|
| 967 |
|
| 968 |
+
const cachedBadge = isCached ?
|
| 969 |
+
'<div class="cached-status">์บ์๋จ</div>' : '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 970 |
|
| 971 |
+
d.innerHTML = `
|
| 972 |
+
<div class="card-inner">
|
| 973 |
+
${cachedBadge}
|
| 974 |
+
<img src="${thumb}" alt="${displayTitle}" loading="lazy">
|
| 975 |
+
<p title="${title || 'ํ๋ก์ ํธ ' + (i+1)}">${displayTitle}</p>
|
| 976 |
+
</div>
|
| 977 |
+
`;
|
| 978 |
+
grid.appendChild(d);
|
| 979 |
|
| 980 |
+
// ํ๋ก์ ํธ๊ฐ ์์ผ๋ฉด 'ํ๋ก์ ํธ ์์' ๋ฉ์์ง ์จ๊ธฐ๊ธฐ
|
| 981 |
+
$id('noProjects').style.display = 'none';
|
| 982 |
+
}
|
| 983 |
+
|
| 984 |
+
/* โโ ์ด๋ฏธ์ง ์
๋ก๋ โโ */
|
| 985 |
+
$id('imgInput').onchange = e => {
|
| 986 |
+
const files = [...e.target.files];
|
| 987 |
+
if(!files.length) return;
|
| 988 |
|
|
|
|
| 989 |
showLoading("์ด๋ฏธ์ง ๋ก๋ฉ ์ค...");
|
| 990 |
|
| 991 |
+
const pages=[], tot = files.length;
|
| 992 |
let done = 0;
|
| 993 |
+
files.forEach((f,i)=> {
|
| 994 |
+
const r=new FileReader();
|
| 995 |
+
r.onload=x=>{
|
| 996 |
+
pages[i] = {src: x.target.result, thumb: x.target.result};
|
| 997 |
+
if(++done===tot) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 998 |
save(pages, '์ด๋ฏธ์ง ์ปฌ๋ ์
');
|
| 999 |
hideLoading();
|
| 1000 |
}
|
| 1001 |
};
|
| 1002 |
+
r.readAsDataURL(f);
|
| 1003 |
});
|
| 1004 |
+
};
|
| 1005 |
+
|
| 1006 |
+
/* โโ PDF ์
๋ก๋ โโ */
|
| 1007 |
+
$id('pdfInput').onchange = e => {
|
| 1008 |
const file = e.target.files[0];
|
| 1009 |
+
if(!file) return;
|
| 1010 |
|
|
|
|
| 1011 |
showLoading("PDF ๋ก๋ฉ ์ค...");
|
| 1012 |
|
| 1013 |
+
const fr = new FileReader();
|
| 1014 |
+
fr.onload = v => {
|
| 1015 |
+
pdfjsLib.getDocument({data: v.target.result}).promise.then(async pdf=>{
|
| 1016 |
const pages = [];
|
| 1017 |
|
| 1018 |
+
for(let p=1; p <= pdf.numPages; p++){
|
| 1019 |
+
updateLoading(\`PDF ํ์ด์ง ๋ก๋ฉ ์ค... (\${p}/\${pdf.numPages})\`);
|
| 1020 |
+
const pg=await pdf.getPage(p), vp=pg.getViewport({scale:1});
|
| 1021 |
+
const c=document.createElement('canvas');
|
| 1022 |
+
c.width=vp.width;c.height=vp.height;
|
| 1023 |
+
await pg.render({canvasContext:c.getContext('2d'),viewport:vp}).promise;
|
| 1024 |
+
pages.push({src:c.toDataURL(), thumb:c.toDataURL()});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1025 |
}
|
|
|
|
| 1026 |
hideLoading();
|
| 1027 |
save(pages, file.name.replace('.pdf', ''));
|
| 1028 |
}).catch(error => {
|
|
|
|
| 1031 |
showError("PDF ๋ก๋ฉ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.");
|
| 1032 |
});
|
| 1033 |
};
|
| 1034 |
+
fr.readAsArrayBuffer(file);
|
| 1035 |
+
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1036 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1037 |
function save(pages, title, isCached = false){
|
| 1038 |
const id=projects.push(pages)-1;
|
| 1039 |
addCard(id, pages[0].thumb, title, isCached);
|
|
|
|
| 1042 |
/* โโ ์๋ฒ PDF ๋ก๋ ๋ฐ ์บ์ ์ํ ํ์ธ โโ */
|
| 1043 |
async function loadServerPDFs() {
|
| 1044 |
try {
|
|
|
|
| 1045 |
if (document.querySelectorAll('.card').length === 0) {
|
| 1046 |
showLoading("๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋ฉ ์ค...");
|
| 1047 |
}
|
|
|
|
| 1060 |
return;
|
| 1061 |
}
|
| 1062 |
|
|
|
|
| 1063 |
const thumbnailPromises = serverProjects.map(async (project, index) => {
|
| 1064 |
+
updateLoading(\`PDF ํ๋ก์ ํธ ๋ก๋ฉ ์ค... (\${index+1}/\${serverProjects.length})\`);
|
| 1065 |
|
| 1066 |
const pdfName = project.name;
|
| 1067 |
const isCached = cacheStatus[pdfName] && cacheStatus[pdfName].status === "completed";
|
| 1068 |
|
| 1069 |
try {
|
| 1070 |
// ์ธ๋ค์ผ ๊ฐ์ ธ์ค๊ธฐ
|
| 1071 |
+
const response = await fetch(\`/api/pdf-thumbnail?path=\${encodeURIComponent(project.path)}\`);
|
| 1072 |
const data = await response.json();
|
| 1073 |
|
| 1074 |
if(data.thumbnail) {
|
|
|
|
| 1078 |
path: project.path,
|
| 1079 |
cached: isCached
|
| 1080 |
}];
|
| 1081 |
+
return { pages, name: project.name, isCached };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1082 |
}
|
| 1083 |
} catch (err) {
|
| 1084 |
+
console.error(\`์ธ๋ค์ผ ๋ก๋ ์ค๋ฅ (\${project.name}):\`, err);
|
| 1085 |
}
|
| 1086 |
|
| 1087 |
return null;
|
| 1088 |
});
|
| 1089 |
|
|
|
|
| 1090 |
const results = await Promise.all(thumbnailPromises);
|
| 1091 |
|
|
|
|
| 1092 |
results.filter(result => result !== null).forEach(result => {
|
| 1093 |
save(result.pages, result.name, result.isCached);
|
| 1094 |
});
|
| 1095 |
|
| 1096 |
hideLoading();
|
| 1097 |
|
|
|
|
| 1098 |
if (document.querySelectorAll('.card').length === 0) {
|
| 1099 |
$id('noProjects').style.display = 'block';
|
| 1100 |
}
|
|
|
|
| 1119 |
const pdfPath = projects[i][0].path;
|
| 1120 |
const pdfName = pdfPath.split('/').pop().replace('.pdf', '');
|
| 1121 |
|
|
|
|
| 1122 |
let badgeEl = cards[i].querySelector('.cached-status');
|
| 1123 |
|
| 1124 |
if(cacheStatus[pdfName] && cacheStatus[pdfName].status === "completed") {
|
|
|
|
| 1138 |
badgeEl.className = 'cached-status';
|
| 1139 |
cards[i].querySelector('.card-inner')?.appendChild(badgeEl);
|
| 1140 |
}
|
| 1141 |
+
badgeEl.textContent = \`\${cacheStatus[pdfName].progress}%\`;
|
| 1142 |
badgeEl.style.background = 'var(--secondary-color)';
|
| 1143 |
}
|
| 1144 |
}
|
|
|
|
| 1147 |
// ํ์ฌ ๋ก๋ฉ ์ค์ธ PDF๊ฐ ์์ผ๋ฉด ์ํ ํ์ธ
|
| 1148 |
if (currentLoadingPdfPath && pageLoadingInterval) {
|
| 1149 |
const pdfName = currentLoadingPdfPath.split('/').pop().replace('.pdf', '');
|
|
|
|
| 1150 |
if (cacheStatus[pdfName]) {
|
| 1151 |
const status = cacheStatus[pdfName].status;
|
| 1152 |
const progress = cacheStatus[pdfName].progress || 0;
|
| 1153 |
|
| 1154 |
if (status === "completed") {
|
|
|
|
| 1155 |
clearInterval(pageLoadingInterval);
|
| 1156 |
$id('loadingPages').style.display = 'none';
|
| 1157 |
currentLoadingPdfPath = null;
|
|
|
|
|
|
|
| 1158 |
refreshFlipBook();
|
| 1159 |
} else if (status === "processing") {
|
|
|
|
| 1160 |
$id('loadingPages').style.display = 'block';
|
| 1161 |
+
$id('loadingPagesCount').textContent = \`\${progress}%\`;
|
| 1162 |
}
|
| 1163 |
}
|
| 1164 |
}
|
|
|
|
| 1165 |
} catch(error) {
|
| 1166 |
console.error('์บ์ ์ํ ํ์ธ ์ค๋ฅ:', error);
|
| 1167 |
}
|
|
|
|
| 1172 |
toggle(false);
|
| 1173 |
const pages = projects[i];
|
| 1174 |
|
|
|
|
| 1175 |
if(fb) {
|
| 1176 |
fb.destroy();
|
| 1177 |
viewer.innerHTML = '';
|
| 1178 |
}
|
| 1179 |
|
|
|
|
| 1180 |
if(pages[0].path) {
|
| 1181 |
const pdfPath = pages[0].path;
|
|
|
|
|
|
|
| 1182 |
let progressiveLoading = false;
|
| 1183 |
currentLoadingPdfPath = pdfPath;
|
| 1184 |
|
|
|
|
| 1185 |
if(pages[0].cached) {
|
|
|
|
| 1186 |
showLoading("์บ์๋ PDF ๋ก๋ฉ ์ค...");
|
|
|
|
| 1187 |
try {
|
| 1188 |
+
const response = await fetch(\`/api/cached-pdf?path=\${encodeURIComponent(pdfPath)}\`);
|
| 1189 |
const cachedData = await response.json();
|
| 1190 |
|
| 1191 |
if(cachedData.status === "completed" && cachedData.pages) {
|
|
|
|
| 1194 |
currentLoadingPdfPath = null;
|
| 1195 |
return;
|
| 1196 |
} else if(cachedData.status === "processing" && cachedData.pages && cachedData.pages.length > 0) {
|
|
|
|
| 1197 |
hideLoading();
|
| 1198 |
createFlipBook(cachedData.pages);
|
| 1199 |
progressiveLoading = true;
|
|
|
|
|
|
|
| 1200 |
startProgressiveLoadingIndicator(cachedData.progress, cachedData.total_pages);
|
| 1201 |
}
|
| 1202 |
} catch(error) {
|
| 1203 |
console.error("์บ์ ๋ฐ์ดํฐ ๋ก๋ ์ค๋ฅ:", error);
|
|
|
|
| 1204 |
}
|
| 1205 |
}
|
| 1206 |
|
| 1207 |
+
if(!progressiveLoading) {
|
|
|
|
| 1208 |
showLoading("PDF ์ค๋น ์ค...");
|
|
|
|
| 1209 |
try {
|
| 1210 |
+
const response = await fetch(\`/api/pdf-content?path=\${encodeURIComponent(pdfPath)}\`);
|
| 1211 |
const data = await response.json();
|
| 1212 |
|
|
|
|
| 1213 |
if(data.redirect) {
|
| 1214 |
const redirectRes = await fetch(data.redirect);
|
| 1215 |
const cachedData = await redirectRes.json();
|
|
|
|
| 1220 |
currentLoadingPdfPath = null;
|
| 1221 |
return;
|
| 1222 |
} else if(cachedData.status === "processing" && cachedData.pages && cachedData.pages.length > 0) {
|
|
|
|
| 1223 |
hideLoading();
|
| 1224 |
createFlipBook(cachedData.pages);
|
|
|
|
|
|
|
| 1225 |
startProgressiveLoadingIndicator(cachedData.progress, cachedData.total_pages);
|
| 1226 |
return;
|
| 1227 |
}
|
| 1228 |
}
|
| 1229 |
|
| 1230 |
+
const pdfResponse = await fetch(\`/api/pdf-content?path=\${encodeURIComponent(pdfPath)}\`);
|
|
|
|
| 1231 |
|
|
|
|
| 1232 |
try {
|
| 1233 |
const jsonData = await pdfResponse.clone().json();
|
| 1234 |
if (jsonData.redirect) {
|
|
|
|
| 1238 |
if(cachedData.pages && cachedData.pages.length > 0) {
|
| 1239 |
hideLoading();
|
| 1240 |
createFlipBook(cachedData.pages);
|
|
|
|
| 1241 |
if(cachedData.status === "processing") {
|
| 1242 |
startProgressiveLoadingIndicator(cachedData.progress, cachedData.total_pages);
|
| 1243 |
} else {
|
|
|
|
| 1247 |
}
|
| 1248 |
}
|
| 1249 |
} catch (e) {
|
| 1250 |
+
// JSON ํ์ฑ ์คํจ -> PDF ์๋ณธ ๋ฐ์ดํฐ๋ก ์ฒ๋ฆฌ
|
| 1251 |
}
|
| 1252 |
|
|
|
|
| 1253 |
const pdfData = await pdfResponse.arrayBuffer();
|
|
|
|
|
|
|
| 1254 |
const pdf = await pdfjsLib.getDocument({data: pdfData}).promise;
|
| 1255 |
const pdfPages = [];
|
| 1256 |
|
| 1257 |
+
for(let p=1; p <= pdf.numPages; p++) {
|
| 1258 |
+
updateLoading(\`ํ์ด์ง ์ค๋น ์ค... (\${p}/\${pdf.numPages})\`);
|
|
|
|
| 1259 |
const pg = await pdf.getPage(p);
|
| 1260 |
const vp = pg.getViewport({scale: 1});
|
| 1261 |
const c = document.createElement('canvas');
|
| 1262 |
c.width = vp.width;
|
| 1263 |
c.height = vp.height;
|
|
|
|
| 1264 |
await pg.render({canvasContext: c.getContext('2d'), viewport: vp}).promise;
|
| 1265 |
pdfPages.push({src: c.toDataURL(), thumb: c.toDataURL()});
|
| 1266 |
}
|
|
|
|
| 1267 |
hideLoading();
|
| 1268 |
createFlipBook(pdfPages);
|
| 1269 |
currentLoadingPdfPath = null;
|
|
|
|
| 1270 |
} catch(error) {
|
| 1271 |
+
console.error('PDF ์ฒ๋ฆฌ ์ค ์ค๋ฅ:', error);
|
| 1272 |
hideLoading();
|
| 1273 |
showError("PDF๋ฅผ ๋ก๋ํ๋ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.");
|
| 1274 |
currentLoadingPdfPath = null;
|
| 1275 |
}
|
| 1276 |
}
|
| 1277 |
} else {
|
|
|
|
| 1278 |
createFlipBook(pages);
|
| 1279 |
currentLoadingPdfPath = null;
|
| 1280 |
}
|
| 1281 |
}
|
| 1282 |
|
|
|
|
| 1283 |
function startProgressiveLoadingIndicator(progress, totalPages) {
|
|
|
|
| 1284 |
$id('loadingPages').style.display = 'block';
|
| 1285 |
+
$id('loadingPagesCount').textContent = \`\${progress}%\`;
|
| 1286 |
|
|
|
|
| 1287 |
if (pageLoadingInterval) {
|
| 1288 |
clearInterval(pageLoadingInterval);
|
| 1289 |
}
|
|
|
|
|
|
|
| 1290 |
pageLoadingInterval = setInterval(async () => {
|
| 1291 |
if (!currentLoadingPdfPath) {
|
| 1292 |
clearInterval(pageLoadingInterval);
|
| 1293 |
$id('loadingPages').style.display = 'none';
|
| 1294 |
return;
|
| 1295 |
}
|
|
|
|
| 1296 |
try {
|
| 1297 |
+
const response = await fetch(\`/api/cache-status?path=\${encodeURIComponent(currentLoadingPdfPath)}\`);
|
| 1298 |
const status = await response.json();
|
| 1299 |
|
|
|
|
| 1300 |
if (status.status === "completed") {
|
| 1301 |
clearInterval(pageLoadingInterval);
|
| 1302 |
$id('loadingPages').style.display = 'none';
|
| 1303 |
+
refreshFlipBook();
|
| 1304 |
currentLoadingPdfPath = null;
|
| 1305 |
} else if (status.status === "processing") {
|
| 1306 |
+
$id('loadingPagesCount').textContent = \`\${status.progress}%\`;
|
| 1307 |
}
|
| 1308 |
} catch (e) {
|
| 1309 |
console.error("์บ์ ์ํ ํ์ธ ์ค๋ฅ:", e);
|
|
|
|
| 1311 |
}, 1000);
|
| 1312 |
}
|
| 1313 |
|
|
|
|
| 1314 |
async function refreshFlipBook() {
|
| 1315 |
if (!currentLoadingPdfPath || !fb) return;
|
|
|
|
| 1316 |
try {
|
| 1317 |
+
const response = await fetch(\`/api/cached-pdf?path=\${encodeURIComponent(currentLoadingPdfPath)}\`);
|
| 1318 |
const cachedData = await response.json();
|
| 1319 |
|
| 1320 |
if(cachedData.status === "completed" && cachedData.pages) {
|
|
|
|
| 1321 |
fb.destroy();
|
| 1322 |
viewer.innerHTML = '';
|
|
|
|
|
|
|
| 1323 |
createFlipBook(cachedData.pages);
|
| 1324 |
currentLoadingPdfPath = null;
|
| 1325 |
}
|
|
|
|
| 1330 |
|
| 1331 |
function createFlipBook(pages) {
|
| 1332 |
console.log('FlipBook ์์ฑ ์์. ํ์ด์ง ์:', pages.length);
|
|
|
|
| 1333 |
try {
|
|
|
|
| 1334 |
const calculateAspectRatio = () => {
|
| 1335 |
const windowWidth = window.innerWidth;
|
| 1336 |
const windowHeight = window.innerHeight;
|
| 1337 |
const aspectRatio = windowWidth / windowHeight;
|
| 1338 |
|
|
|
|
| 1339 |
let width, height;
|
| 1340 |
+
if (aspectRatio > 1) {
|
| 1341 |
height = Math.min(windowHeight * 0.9, windowHeight - 40);
|
| 1342 |
+
width = height * aspectRatio * 0.8;
|
| 1343 |
if (width > windowWidth * 0.9) {
|
| 1344 |
width = windowWidth * 0.9;
|
| 1345 |
height = width / (aspectRatio * 0.8);
|
| 1346 |
}
|
| 1347 |
+
} else {
|
| 1348 |
width = Math.min(windowWidth * 0.9, windowWidth - 40);
|
| 1349 |
+
height = width / aspectRatio * 0.9;
|
| 1350 |
if (height > windowHeight * 0.9) {
|
| 1351 |
height = windowHeight * 0.9;
|
| 1352 |
width = height * aspectRatio * 0.9;
|
| 1353 |
}
|
| 1354 |
}
|
|
|
|
|
|
|
| 1355 |
return {
|
| 1356 |
width: Math.round(width),
|
| 1357 |
height: Math.round(height)
|
| 1358 |
};
|
| 1359 |
};
|
| 1360 |
|
|
|
|
| 1361 |
const size = calculateAspectRatio();
|
| 1362 |
viewer.style.width = size.width + 'px';
|
| 1363 |
viewer.style.height = size.height + 'px';
|
| 1364 |
|
|
|
|
| 1365 |
const validPages = pages.map(page => {
|
|
|
|
| 1366 |
if (!page || !page.src) {
|
| 1367 |
return {
|
| 1368 |
src: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjVmNWY1Ii8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iIGZpbGw9IiM1NTUiPkxvYWRpbmcuLi48L3RleHQ+PC9zdmc+',
|
|
|
|
| 1378 |
autoSize: true,
|
| 1379 |
flipDuration: 800,
|
| 1380 |
backgroundColor: '#fff',
|
|
|
|
| 1381 |
sound: true,
|
| 1382 |
assets: {flipMp3: 'static/turnPage2.mp3', hardFlipMp3: 'static/turnPage2.mp3'},
|
| 1383 |
controlsProps: {
|
|
|
|
| 1392 |
enableAnnotation: false,
|
| 1393 |
enableSound: true,
|
| 1394 |
enableLightbox: false,
|
| 1395 |
+
layout: 10,
|
| 1396 |
+
skin: 'light',
|
| 1397 |
+
autoNavigationTime: 3600,
|
| 1398 |
+
hideControls: false,
|
| 1399 |
+
paddingTop: 10,
|
| 1400 |
+
paddingLeft: 10,
|
| 1401 |
+
paddingRight: 10,
|
| 1402 |
+
paddingBottom: 10,
|
| 1403 |
+
pageTextureSize: 1024,
|
| 1404 |
+
thumbnails: true,
|
| 1405 |
+
autoHideControls: false,
|
| 1406 |
+
controlsTimeout: 8000
|
| 1407 |
}
|
| 1408 |
});
|
| 1409 |
|
|
|
|
| 1410 |
window.addEventListener('resize', () => {
|
| 1411 |
if (fb) {
|
| 1412 |
const newSize = calculateAspectRatio();
|
|
|
|
| 1416 |
}
|
| 1417 |
});
|
| 1418 |
|
|
|
|
| 1419 |
setTimeout(() => {
|
| 1420 |
try {
|
|
|
|
| 1421 |
const menuBars = document.querySelectorAll('.flipbook-container .fb3d-menu-bar');
|
| 1422 |
if (menuBars && menuBars.length > 0) {
|
| 1423 |
menuBars.forEach(menuBar => {
|
|
|
|
| 1439 |
}
|
| 1440 |
}
|
| 1441 |
|
| 1442 |
+
$id('homeButton').onclick = () => {
|
| 1443 |
+
if(fb) {
|
| 1444 |
+
fb.destroy();
|
| 1445 |
+
viewer.innerHTML = '';
|
| 1446 |
+
fb = null;
|
| 1447 |
+
}
|
| 1448 |
+
toggle(true);
|
| 1449 |
+
if (pageLoadingInterval) {
|
| 1450 |
+
clearInterval(pageLoadingInterval);
|
| 1451 |
+
pageLoadingInterval = null;
|
| 1452 |
+
}
|
| 1453 |
+
$id('loadingPages').style.display = 'none';
|
| 1454 |
+
currentLoadingPdfPath = null;
|
| 1455 |
+
};
|
| 1456 |
|
| 1457 |
function toggle(showHome){
|
| 1458 |
+
$id('home').style.display = showHome?'block':'none';
|
| 1459 |
+
$id('viewerPage').style.display = showHome?'none':'block';
|
| 1460 |
+
$id('homeButton').style.display = showHome?'none':'block';
|
| 1461 |
|
|
|
|
| 1462 |
if(!showHome) {
|
| 1463 |
document.body.classList.add('viewer-mode');
|
| 1464 |
} else {
|
|
|
|
| 1466 |
}
|
| 1467 |
}
|
| 1468 |
|
|
|
|
| 1469 |
function showLoading(message, progress = -1) {
|
|
|
|
| 1470 |
hideLoading();
|
|
|
|
| 1471 |
const loadingContainer = document.createElement('div');
|
| 1472 |
loadingContainer.className = 'loading-container fade-in';
|
| 1473 |
loadingContainer.id = 'loadingContainer';
|
|
|
|
| 1498 |
|
| 1499 |
if (progress >= 0) {
|
| 1500 |
let progressBar = $id('progressBar');
|
|
|
|
| 1501 |
if (!progressBar) {
|
| 1502 |
const loadingContainer = $id('loadingContainer');
|
| 1503 |
if (loadingContainer) {
|
|
|
|
| 1508 |
progressBar = $id('progressBar');
|
| 1509 |
}
|
| 1510 |
} else {
|
| 1511 |
+
progressBar.style.width = \`\${progress}%\`;
|
| 1512 |
}
|
| 1513 |
}
|
| 1514 |
}
|
|
|
|
| 1521 |
}
|
| 1522 |
|
| 1523 |
function showError(message) {
|
|
|
|
| 1524 |
const existingError = $id('errorContainer');
|
| 1525 |
if (existingError) {
|
| 1526 |
existingError.remove();
|
|
|
|
| 1536 |
|
| 1537 |
document.body.appendChild(errorContainer);
|
| 1538 |
|
|
|
|
| 1539 |
$id('errorCloseBtn').onclick = () => {
|
| 1540 |
errorContainer.remove();
|
| 1541 |
};
|
| 1542 |
|
|
|
|
| 1543 |
setTimeout(() => {
|
| 1544 |
if ($id('errorContainer')) {
|
| 1545 |
$id('errorContainer').remove();
|
|
|
|
| 1547 |
}, 5000);
|
| 1548 |
}
|
| 1549 |
|
| 1550 |
+
window.addEventListener('DOMContentLoaded', () => {
|
| 1551 |
+
// ์
๋ก๋ ๋ฒํผ์ด ์ ์ ๋์ํ๋๋ก ์ง์ ์ด๋ฒคํธ ์ค์
|
| 1552 |
+
setupDirectEvents();
|
| 1553 |
+
|
| 1554 |
+
loadServerPDFs();
|
| 1555 |
+
|
| 1556 |
+
// ์บ์ ์ํ๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ํ์ธ
|
| 1557 |
+
setInterval(checkCacheStatus, 3000);
|
| 1558 |
+
});
|
| 1559 |
</script>
|
| 1560 |
</body>
|
| 1561 |
</html>
|
|
|
|
| 1566 |
return get_html_content()
|
| 1567 |
|
| 1568 |
if __name__ == "__main__":
|
| 1569 |
+
uvicorn.run("app:app", host="0.0.0.0", port=int(os.getenv("PORT", 7860)))
|