ginipick commited on
Commit
07e569b
Β·
1 Parent(s): 6982389

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -127
app.py CHANGED
@@ -415,14 +415,22 @@ HTML = """
415
  --transition: all 0.3s ease;
416
  }
417
 
418
- body {
419
- margin: 0;
420
- background: var(--bg-color);
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 λ²„νŠΌ λ ˆμ΄μ–΄ 처리 */
428
  .floating-home {
@@ -803,7 +811,7 @@ HTML = """
803
  /* 헀더 둜고 및 타이틀 */
804
  .library-header {
805
  position: fixed;
806
- top: 20px;
807
  left: 0;
808
  right: 0;
809
  text-align: center;
@@ -811,21 +819,21 @@ HTML = """
811
  pointer-events: none;
812
  }
813
 
814
- .library-header .title {
815
- display: inline-block;
816
- padding: 12px 30px;
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
  /* 점진적 λ‘œλ”© ν‘œμ‹œ */
831
  .loading-pages {
@@ -884,14 +892,10 @@ HTML = """
884
 
885
  <section id="home" class="fade-in">
886
  <div class="upload-container">
887
- <button class="upload" id="imageUploadBtn">
888
- <i class="fas fa-images"></i> 이미지 μΆ”κ°€
889
- <input id="imgInput" type="file" accept="image/*" multiple hidden>
890
- </button>
891
  <button class="upload" id="pdfUploadBtn">
892
  <i class="fas fa-file-pdf"></i> PDF μΆ”κ°€
893
- <input id="pdfInput" type="file" accept="application/pdf" hidden>
894
  </button>
 
895
  </div>
896
 
897
  <div class="section-title">λ‚΄ ν”„λ‘œμ νŠΈ</div>
@@ -899,7 +903,7 @@ HTML = """
899
  <!-- μΉ΄λ“œκ°€ 여기에 λ™μ μœΌλ‘œ μΆ”κ°€λ©λ‹ˆλ‹€ -->
900
  </div>
901
  <div id="noProjects" class="no-projects" style="display: none;">
902
- ν”„λ‘œμ νŠΈκ°€ μ—†μŠ΅λ‹ˆλ‹€. μ΄λ―Έμ§€λ‚˜ PDFλ₯Ό μΆ”κ°€ν•˜μ—¬ μ‹œμž‘ν•˜μ„Έμš”.
903
  </div>
904
  </section>
905
 
@@ -910,7 +914,7 @@ HTML = """
910
 
911
  <script>
912
  let projects=[], fb=null;
913
- const grid=$id('grid'), viewer=$id('viewer');
914
  pdfjsLib.GlobalWorkerOptions.workerSrc='/static/pdf.worker.js';
915
 
916
  // μ„œλ²„μ—μ„œ 미리 λ‘œλ“œλœ PDF ν”„λ‘œμ νŠΈ
@@ -927,51 +931,86 @@ HTML = """
927
  {once:true,capture:true});
928
  });
929
 
930
- // μ—…λ‘œλ“œ λ²„νŠΌ 이벀트 μ—°κ²° ν•¨μˆ˜
931
- function setupUploadButtons() {
932
- // λͺ¨λ“  μ—…λ‘œλ“œ λ²„νŠΌμ— 이벀트 λ¦¬μŠ€λ„ˆ μΆ”κ°€
933
- document.querySelectorAll('.upload').forEach(button => {
934
- button.addEventListener('click', function(e) {
935
- // λ²„νŠΌ λ‚΄λΆ€μ˜ input μš”μ†Œ μ°ΎκΈ°
936
- const inputElement = this.querySelector('input[type="file"]');
937
- if (inputElement) {
938
- // input μš”μ†Œ 클릭 (파일 선택 λ‹€μ΄μ–Όλ‘œκ·Έ μ—΄κΈ°)
939
- inputElement.click();
940
- e.preventDefault(); // λ²„νŠΌ κΈ°λ³Έ λ™μž‘ λ°©μ§€
941
- }
942
- });
943
- });
944
- }
945
-
946
  /* ── μœ ν‹Έ ── */
947
  function $id(id){return document.getElementById(id)}
948
 
949
- // 직접 이벀트 λ¦¬μŠ€λ„ˆ μ„€μ • (더 ν™•μ‹€ν•œ 방법)
950
- function setupDirectEvents() {
951
- // 이미지 μ—…λ‘œλ“œ λ²„νŠΌ
952
- const imageBtn = $id('imageUploadBtn');
953
- const imageInput = $id('imgInput');
954
- if (imageBtn && imageInput) {
955
- console.log('이미지 μ—…λ‘œλ“œ λ²„νŠΌ 이벀트 μ„€μ •');
956
- imageBtn.onclick = function(e) {
957
- e.preventDefault();
958
- e.stopPropagation();
959
- imageInput.click();
960
- };
961
- }
962
 
963
  // PDF μ—…λ‘œλ“œ λ²„νŠΌ
964
- const pdfBtn = $id('pdfUploadBtn');
965
- const pdfInput = $id('pdfInput');
 
966
  if (pdfBtn && pdfInput) {
967
- console.log('PDF μ—…λ‘œλ“œ λ²„νŠΌ 이벀트 μ„€μ •');
968
- pdfBtn.onclick = function(e) {
969
- e.preventDefault();
970
- e.stopPropagation();
 
971
  pdfInput.click();
972
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973
  }
974
- }
 
 
 
 
 
 
975
 
976
  function addCard(i, thumb, title, isCached = false) {
977
  const d = document.createElement('div');
@@ -1000,54 +1039,6 @@ HTML = """
1000
  $id('noProjects').style.display = 'none';
1001
  }
1002
 
1003
- /* ── 이미지 μ—…λ‘œλ“œ ── */
1004
- $id('imgInput').onchange=e=>{
1005
- const files=[...e.target.files]; if(!files.length) return;
1006
-
1007
- // λ‘œλ”© ν‘œμ‹œ μΆ”κ°€
1008
- showLoading("이미지 λ‘œλ”© 쀑...");
1009
-
1010
- const pages=[],tot=files.length;let done=0;
1011
- files.forEach((f,i)=>{const r=new FileReader();r.onload=x=>{pages[i]={src:x.target.result,thumb:x.target.result};
1012
- if(++done===tot) {
1013
- save(pages, '이미지 μ»¬λ ‰μ…˜');
1014
- hideLoading();
1015
- }
1016
- };r.readAsDataURL(f);});
1017
- };
1018
-
1019
- /* ── PDF μ—…λ‘œλ“œ ── */
1020
- $id('pdfInput').onchange=e=>{
1021
- const file=e.target.files[0]; if(!file) return;
1022
-
1023
- // λ‘œλ”© ν‘œμ‹œ μΆ”κ°€
1024
- showLoading("PDF λ‘œλ”© 쀑...");
1025
-
1026
- const fr=new FileReader();
1027
- fr.onload=v=>{
1028
- pdfjsLib.getDocument({data:v.target.result}).promise.then(async pdf=>{
1029
- const pages=[];
1030
-
1031
- for(let p=1;p<=pdf.numPages;p++){
1032
- // λ‘œλ”© μƒνƒœ μ—…λ°μ΄νŠΈ
1033
- updateLoading(`PDF νŽ˜μ΄μ§€ λ‘œλ”© 쀑... (${p}/${pdf.numPages})`);
1034
-
1035
- const pg=await pdf.getPage(p), vp=pg.getViewport({scale:1});
1036
- const c=document.createElement('canvas');c.width=vp.width;c.height=vp.height;
1037
- await pg.render({canvasContext:c.getContext('2d'),viewport:vp}).promise;
1038
- pages.push({src:c.toDataURL(),thumb:c.toDataURL()});
1039
- }
1040
-
1041
- hideLoading();
1042
- save(pages, file.name.replace('.pdf', ''));
1043
- }).catch(error => {
1044
- console.error("PDF λ‘œλ”© 였λ₯˜:", error);
1045
- hideLoading();
1046
- showError("PDF λ‘œλ”© 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.");
1047
- });
1048
- };fr.readAsArrayBuffer(file);
1049
- };
1050
-
1051
  /* ── ν”„λ‘œμ νŠΈ μ €μž₯ ── */
1052
  function save(pages, title, isCached = false){
1053
  const id=projects.push(pages)-1;
@@ -1641,17 +1632,6 @@ HTML = """
1641
  }
1642
  }, 5000);
1643
  }
1644
-
1645
- // νŽ˜μ΄μ§€ λ‘œλ“œ μ‹œ μ„œλ²„ PDF λ‘œλ“œ
1646
- window.addEventListener('DOMContentLoaded', () => {
1647
- // 직접 이벀트 λ¦¬μŠ€λ„ˆ μ„€μ • (더 ν™•μ‹€ν•œ 방법)
1648
- setupDirectEvents();
1649
-
1650
- loadServerPDFs();
1651
-
1652
- // μΊμ‹œ μƒνƒœλ₯Ό 주기적으둜 확인 (3μ΄ˆλ§ˆλ‹€)
1653
- setInterval(checkCacheStatus, 3000);
1654
- });
1655
  </script>
1656
  </body>
1657
  </html>
 
415
  --transition: all 0.3s ease;
416
  }
417
 
418
+
419
+ body {
420
+ margin: 0;
421
+ background: var(--bg-color);
422
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
423
+ color: var(--text-color);
424
+ /* μƒˆλ‘œμš΄ νΌν”Œ 계톡 κ³ κΈ‰μŠ€λŸ¬μš΄ κ·ΈλΌλ””μ—μ΄μ…˜ λ°°κ²½ */
425
+ background-image: linear-gradient(135deg, #2a0845 0%, #6441a5 50%, #c9a8ff 100%);
426
+ background-attachment: fixed;
427
+ }
428
+
429
+ /* λ·°μ–΄ λͺ¨λ“œμΌ λ•Œ λ°°κ²½ λ³€κ²½ */
430
+ .viewer-mode {
431
+ background-image: linear-gradient(135deg, #30154e 0%, #6b47ad 50%, #d5b8ff 100%) !important;
432
+ }
433
+
434
 
435
  /* 헀더 제λͺ© 제거 및 Home λ²„νŠΌ λ ˆμ΄μ–΄ 처리 */
436
  .floating-home {
 
811
  /* 헀더 둜고 및 타이틀 */
812
  .library-header {
813
  position: fixed;
814
+ top: 12px;
815
  left: 0;
816
  right: 0;
817
  text-align: center;
 
819
  pointer-events: none;
820
  }
821
 
822
+ .library-header .title {
823
+ display: inline-block;
824
+ padding: 8px 24px; /* νŒ¨λ”© μΆ•μ†Œ */
825
+ background: rgba(255, 255, 255, 0.85);
826
+ backdrop-filter: blur(10px);
827
+ border-radius: 25px; /* ν…Œλ‘λ¦¬ λͺ¨μ„œλ¦¬ μΆ•μ†Œ */
828
+ box-shadow: var(--shadow-md);
829
+ font-size: 1.25rem; /* κΈ€μž 크기 μΆ•μ†Œ (1.5remμ—μ„œ 1.25rem으둜) */
830
+ font-weight: 600;
831
+ background-image: linear-gradient(120deg, #8e74eb 0%, #9d66ff 100%); /* 제λͺ© 색상도 바탕화면과 μ–΄μšΈλ¦¬κ²Œ λ³€κ²½ */
832
+ -webkit-background-clip: text;
833
+ background-clip: text;
834
+ color: transparent;
835
+ pointer-events: all;
836
+ }
837
 
838
  /* 점진적 λ‘œλ”© ν‘œμ‹œ */
839
  .loading-pages {
 
892
 
893
  <section id="home" class="fade-in">
894
  <div class="upload-container">
 
 
 
 
895
  <button class="upload" id="pdfUploadBtn">
896
  <i class="fas fa-file-pdf"></i> PDF μΆ”κ°€
 
897
  </button>
898
+ <input id="pdfInput" type="file" accept="application/pdf" style="display:none">
899
  </div>
900
 
901
  <div class="section-title">λ‚΄ ν”„λ‘œμ νŠΈ</div>
 
903
  <!-- μΉ΄λ“œκ°€ 여기에 λ™μ μœΌλ‘œ μΆ”κ°€λ©λ‹ˆλ‹€ -->
904
  </div>
905
  <div id="noProjects" class="no-projects" style="display: none;">
906
+ ν”„λ‘œμ νŠΈκ°€ μ—†μŠ΅λ‹ˆλ‹€. PDFλ₯Ό μΆ”κ°€ν•˜μ—¬ μ‹œμž‘ν•˜μ„Έμš”.
907
  </div>
908
  </section>
909
 
 
914
 
915
  <script>
916
  let projects=[], fb=null;
917
+ const grid=document.getElementById('grid'), viewer=document.getElementById('viewer');
918
  pdfjsLib.GlobalWorkerOptions.workerSrc='/static/pdf.worker.js';
919
 
920
  // μ„œλ²„μ—μ„œ 미리 λ‘œλ“œλœ PDF ν”„λ‘œμ νŠΈ
 
931
  {once:true,capture:true});
932
  });
933
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
934
  /* ── μœ ν‹Έ ── */
935
  function $id(id){return document.getElementById(id)}
936
 
937
+ // 파일 μ—…λ‘œλ“œ 이��트 처리
938
+ document.addEventListener("DOMContentLoaded", function() {
939
+ console.log("DOM λ‘œλ“œ μ™„λ£Œ, 이벀트 μ„€μ • μ‹œμž‘");
 
 
 
 
 
 
 
 
 
 
940
 
941
  // PDF μ—…λ‘œλ“œ λ²„νŠΌ
942
+ const pdfBtn = document.getElementById('pdfUploadBtn');
943
+ const pdfInput = document.getElementById('pdfInput');
944
+
945
  if (pdfBtn && pdfInput) {
946
+ console.log("PDF μ—…λ‘œλ“œ λ²„νŠΌ 찾음");
947
+
948
+ // λ²„νŠΌ 클릭 μ‹œ 파일 μž…λ ₯ 트리거
949
+ pdfBtn.addEventListener('click', function() {
950
+ console.log("PDF λ²„νŠΌ 클릭됨");
951
  pdfInput.click();
952
+ });
953
+
954
+ // 파일 선택 μ‹œ 처리
955
+ pdfInput.addEventListener('change', function(e) {
956
+ console.log("PDF 파일 선택됨:", e.target.files.length);
957
+ const file = e.target.files[0];
958
+ if (!file) return;
959
+
960
+ showLoading("PDF λ‘œλ”© 쀑...");
961
+
962
+ const reader = new FileReader();
963
+ reader.onload = function(event) {
964
+ pdfjsLib.getDocument({data: event.target.result}).promise.then(async function(pdf) {
965
+ const pages = [];
966
+
967
+ for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
968
+ updateLoading(`PDF νŽ˜μ΄μ§€ λ‘œλ”© 쀑... (${pageNum}/${pdf.numPages})`);
969
+
970
+ const page = await pdf.getPage(pageNum);
971
+ const viewport = page.getViewport({scale: 1});
972
+ const canvas = document.createElement('canvas');
973
+ canvas.width = viewport.width;
974
+ canvas.height = viewport.height;
975
+
976
+ await page.render({
977
+ canvasContext: canvas.getContext('2d'),
978
+ viewport: viewport
979
+ }).promise;
980
+
981
+ pages.push({
982
+ src: canvas.toDataURL(),
983
+ thumb: canvas.toDataURL()
984
+ });
985
+ }
986
+
987
+ hideLoading();
988
+ save(pages, file.name.replace('.pdf', ''));
989
+ }).catch(function(error) {
990
+ console.error("PDF λ‘œλ”© 였λ₯˜:", error);
991
+ hideLoading();
992
+ showError("PDF λ‘œλ”© 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: " + error.message);
993
+ });
994
+ };
995
+
996
+ reader.onerror = function(error) {
997
+ console.error("파일 읽기 였λ₯˜:", error);
998
+ hideLoading();
999
+ showError("νŒŒμΌμ„ μ½λŠ” 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.");
1000
+ };
1001
+
1002
+ reader.readAsArrayBuffer(file);
1003
+ });
1004
+ } else {
1005
+ console.error("PDF μ—…λ‘œλ“œ μš”μ†Œλ₯Ό 찾을 수 μ—†μŒ");
1006
  }
1007
+
1008
+ // μ„œλ²„ PDF λ‘œλ“œ 및 μΊμ‹œ μƒνƒœ 확인
1009
+ loadServerPDFs();
1010
+
1011
+ // μΊμ‹œ μƒνƒœλ₯Ό 주기적으둜 확인
1012
+ setInterval(checkCacheStatus, 3000);
1013
+ });
1014
 
1015
  function addCard(i, thumb, title, isCached = false) {
1016
  const d = document.createElement('div');
 
1039
  $id('noProjects').style.display = 'none';
1040
  }
1041
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1042
  /* ── ν”„λ‘œμ νŠΈ μ €μž₯ ── */
1043
  function save(pages, title, isCached = false){
1044
  const id=projects.push(pages)-1;
 
1632
  }
1633
  }, 5000);
1634
  }
 
 
 
 
 
 
 
 
 
 
 
1635
  </script>
1636
  </body>
1637
  </html>