diff --git a/README.md b/README.md index 4beb058..d308791 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,16 @@ ## π λ³κ²½ μ΄λ ₯ (Changelog) +### v0.7.3 (2026-01-12) +- **Anilife λͺ¨λ°μΌ UI μ΅μ ν (ν리미μ κ°νΈ)**: + - **λΆμ νμ΄μ§**: κ°λ‘ μ¬λ°±μ μ΅μν(15px -> 2px)νμ¬ λͺ¨λ°μΌ κ°λ μ± μ¦λ. + - **ν νμ΄μ§**: κΈ°μ‘΄ ν μ΄λΈ λ μ΄μμμ λͺ¨λ°μΌ μ μ© **μΉ΄λν λ μ΄μμ**μΌλ‘ μ λ©΄ κ΅μ²΄. νμΌλͺ κ³Ό μ§νλ₯ λ°λ₯Ό κ°μ‘°νκ³ 2λ¨ μ 보 그리λλ₯Ό λμ νμ¬ κ°μμ± ν보. + - **μ€λ²νλ‘μ° μμ **: μλ¨ λ©λ΄(λΈλ λν¬λΌ) κ°λ‘ μ€ν¬λ‘€ μ μ© λ° μ‘μ λ²νΌ μλ μ€λ°κΏ λ°°μΉλ₯Ό ν΅ν΄ νλ©΄ λμΉ¨ ν΄κ²°. +- **Linkkf μμ ν λ° μλ§ μ°λ**: + - **μλ§ μλν**: GDM(v0.2.30+) μ°λμ ν΅ν΄ λΉλμ€μ μλ§μ λμμ μμ νκ² λ€μ΄λ‘λ. + - **κ²½λ‘ μ κ·ν**: μ μ₯ κ²½λ‘ λ΄ μ€λ³΅ ꡬλΆμ(`//./`) λ°μ λ¬Έμ λ₯Ό μμ² ν΄κ²°. + - **μΆμΆ μ±λ₯**: λΉλμ€ URL μΆμΆ μ νμμμ λ° μμΈ μ²λ¦¬λ₯Ό κ°ννμ¬ UI νλ¦¬μ§ λ°©μ§. + ### v0.7.2 (2026-01-11) - **Linkkf μλ§ μ μ© λ€μ΄λ‘λ μ§μ**: - μνΌμλ λΆμ νμ΄μ§μ **"μλ§λ§ λ€μ΄λ‘λ"** λ²νΌ μΆκ°. (VTT μΆμΆ λ° SRT μλ λ³ν) diff --git a/info.yaml b/info.yaml index 6eddf22..b1ea84c 100644 --- a/info.yaml +++ b/info.yaml @@ -1,5 +1,5 @@ title: "μ λ λ€μ΄λ‘λ" -version: 0.7.2 +version: 0.7.3 package_name: "anime_downloader" developer: "projectdx" description: "anime downloader" diff --git a/mod_linkkf.py b/mod_linkkf.py index 2025f68..544f9b5 100644 --- a/mod_linkkf.py +++ b/mod_linkkf.py @@ -924,9 +924,9 @@ class LogicLinkkf(AnimeModuleBase): logger.info(f"Extracting video URL from: {playid_url}") # Step 1: playid νμ΄μ§μμ iframe src μΆμΆ (cloudscraper μ¬μ©) - html_content = LogicLinkkf.get_html(playid_url) + html_content = LogicLinkkf.get_html(playid_url, timeout=15) if not html_content: - logger.error(f"Failed to fetch playid page: {playid_url}") + logger.error(f"Failed to fetch playid page (Timeout or Error): {playid_url}") return None, None, None soup = BeautifulSoup(html_content, "html.parser") @@ -958,9 +958,9 @@ class LogicLinkkf(AnimeModuleBase): logger.info(f"Found player iframe: {iframe_src}") # Step 2: iframe νμ΄μ§μμ m3u8 URLκ³Ό vtt URL μΆμΆ - iframe_content = LogicLinkkf.get_html(iframe_src) + iframe_content = LogicLinkkf.get_html(iframe_src, timeout=15) if not iframe_content: - logger.error(f"Failed to fetch iframe content: {iframe_src}") + logger.error(f"Failed to fetch iframe content (Timeout or Error): {iframe_src}") return None, iframe_src, None # m3u8 URL ν¨ν΄ μ°ΎκΈ° (λ μ λ°νκ²) @@ -1951,7 +1951,7 @@ class LogicLinkkf(AnimeModuleBase): # Prepare GDM options gdm_options = { "url": entity.url, - "save_path": entity.savepath, + "save_path": os.path.normpath(entity.savepath), "filename": entity.filename, "source_type": gdm_source_type, "caller_plugin": f"{P.package_name}_{self.name}", @@ -1965,7 +1965,7 @@ class LogicLinkkf(AnimeModuleBase): "source": "linkkf" }, "headers": entity.headers, - "subtitles": entity.vtt, + "subtitles": getattr(entity, 'vtt', None), "connections": download_threads, } diff --git a/templates/anime_downloader_anilife_queue.html b/templates/anime_downloader_anilife_queue.html index 20ad6e2..238884d 100644 --- a/templates/anime_downloader_anilife_queue.html +++ b/templates/anime_downloader_anilife_queue.html @@ -77,6 +77,96 @@ /* Smooth Load */ .content-cloak { opacity: 0; transition: opacity 0.5s ease-out; } .content-cloak.visible { opacity: 1; } + + /* Mobile Friendly Card Layout - Revamped */ + .mobile-queue-container { display: none; flex-direction: column; gap: 8px; padding: 2px; width: 100% !important; margin: 0 !important; } + + @media (max-width: 768px) { + .table-responsive-custom { display: none; } + .mobile-queue-container { display: flex; } + .queue-header-container { + flex-direction: column; align-items: flex-start; gap: 8px; + margin-top: 50px; padding: 10px 5px !important; margin-bottom: 10px; + } + .header-buttons { width: 100%; display: flex; gap: 8px; } + .queue-btn-top { flex: 1; justify-content: center; font-size: 11px !important; padding: 10px !important; } + .queue-meta { font-size: 10px; margin-top: 4px; } + + /* Force container padding reduction for mobile queue */ + #main_container { padding-left: 2px !important; padding-right: 2px !important; } + + /* Fix navigation pills overflow */ + #menu_module_div .nav-pills, #menu_page_div .nav-pills { + flex-wrap: nowrap !important; + overflow-x: auto !important; + -webkit-overflow-scrolling: touch; + white-space: nowrap !important; + display: flex !important; + } + #menu_module_div .nav-link, #menu_page_div .nav-link { + padding: 8px 12px !important; + font-size: 12px !important; + } + + /* Header buttons wrap and layout */ + .queue-header-container { padding-top: 60px !important; } + .header-buttons { flex-wrap: wrap !important; gap: 6px !important; } + .queue-btn-top { + flex: 1 1 45% !important; /* Allow two buttons per row if space exists, or wrap */ + min-width: 120px; + } + + /* Ensure breadcrumb span doesn't force width */ + #menu_module_div span.nav-link { + overflow: hidden; + text-overflow: ellipsis; + max-width: 200px; + white-space: nowrap; + } + } + + .mobile-queue-card { + background: linear-gradient(135deg, rgba(6, 78, 59, 0.4) 0%, rgba(2, 44, 34, 0.6) 100%); + border: 1px solid rgba(16, 185, 129, 0.25); + border-radius: 10px; + padding: 12px 10px; + box-shadow: 0 4px 15px rgba(0,0,0,0.3); + width: 100% !important; + box-sizing: border-box; + } + + .mobile-card-top { display: flex; gap: 8px; align-items: flex-start; margin-bottom: 10px; } + .mobile-card-idx-badge { + background: rgba(16, 185, 129, 0.2); color: #6ee7b7; font-size: 10px; + padding: 2px 6px; border-radius: 4px; font-weight: 800; border: 1px solid rgba(16, 185, 129, 0.3); + } + .mobile-card-filename { color: #ecfdf5; font-weight: 700; font-size: 13.5px; line-height: 1.4; word-break: break-all; flex: 1; } + + .mobile-card-progress-section { + background: rgba(0,0,0,0.2); padding: 10px; border-radius: 8px; margin-bottom: 10px; + border: 1px solid rgba(255,255,255,0.05); + } + .mobile-progress-label { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; } + .mobile-status-text { font-size: 11px; font-weight: 800; text-transform: uppercase; } + .mobile-percent-text { font-size: 14px; font-weight: 900; color: #10b981; } + + .mobile-progress-bar-container { height: 8px; background: rgba(0,0,0,0.5); border-radius: 4px; overflow: hidden; margin-top: 2px; } + .mobile-progress-bar { background: linear-gradient(90deg, #10b981, #34d399); height: 100%; border-radius: 4px; transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1); } + + .mobile-card-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 10px; } + .mobile-stat-item { + display: flex; align-items: center; gap: 5px; font-size: 11px; color: #94a3b8; + background: rgba(0,0,0,0.15); padding: 5px 8px; border-radius: 6px; + } + .mobile-stat-item i { color: #10b981; width: 12px; text-align: center; } + + .mobile-card-actions { display: flex; gap: 8px; padding-top: 8px; border-top: 1px solid rgba(255,255,255,0.05); justify-content: flex-end; } + .mobile-action-btn { + padding: 8px 15px; border-radius: 6px; border: none; font-size: 12px; font-weight: 700; + display: flex; align-items: center; gap: 6px; transition: opacity 0.2s; + } + .mobile-action-btn.btn-stop { background: rgba(239, 68, 68, 0.25); color: #f87171; border: 1px solid rgba(239, 68, 68, 0.3); } + .mobile-action-btn.btn-delete { background: rgba(245, 158, 11, 0.2); color: #fbbf24; border: 1px solid rgba(245, 158, 11, 0.3); }