Refactor: CSS theme consolidation & site-specific styles (v0.4.5) | Fix: mod_anilife get_series_info IndexError

This commit is contained in:
2026-01-02 17:48:58 +09:00
parent 84f7ab6670
commit 15a81cc344
24 changed files with 289 additions and 625 deletions

View File

@@ -14,7 +14,8 @@
* **스마트 다운로드 큐**: `ffmpeg``yt-dlp` 기반의 큐 시스템으로 안정적인 이어받기 및 재시도를 지원합니다.
* **사용자 편의성**:
* **Proxy 설정**: IP 차단 시 손쉽게 우회할 수 있도록 웹 설정 UI에서 프록시 서버를 지정할 수 있습니다.
* **반응형 UI**: 데스크탑모바일 모두에 최적화된 Glassmorphism 디자인.
* **모듈형 테마 시스템**: CSS 변수와 동적 로딩을 활용하여 데스크탑/모바일 모두에 최적화된 사이트별 테마(Anilife, Linkkf, Ohli24)를 제공합니다.
* **실시간 피드백**: 다운로드 상태, 중복 파일 감지 등을 사용자에게 실시간 알림으로 제공합니다.
---
@@ -70,6 +71,16 @@
## 📝 변경 이력 (Changelog)
### v0.4.5 (2026-01-02)
- **CSS 테마 아키텍처 전면 개편**:
- 사이트별 독립 테마 파일 분리 (`anilife.css`, `linkkf.css`, `ohli24.css`)
- 공통 모바일 로직 및 알림 스타일을 `mobile_custom.css`로 통합 (중복 코드 ~2,000줄 제거)
- Jinja2 템플릿을 활용한 테마 동적 로딩 시스템 구현
- **백엔드 안정성 및 UX 강화**:
- **Anilife**: `get_series_info` 파싱 로직 개선으로 `IndexError` 방지 및 크롤링 안정성 확보
- **중복 다운로드 알림**: 이미 파일이 존재하거나 DB에 기록이 있을 경우 사용자에게 명확한 알림 메시지 출력
- **CSS 호환성**: `line-clamp` 속성 크로스 브라우저 호환성 패치 적용
### v0.4.3 (2026-01-02)
- **모바일 UX 대폭 개선**:
- 시스템 알림(bootstrap-notify) 커스텀 스타일링 (사이트별 테마 색상 적용)

View File

@@ -1,5 +1,5 @@
title: "애니 다운로더"
version: "0.4.11"
version: "0.4.12"
package_name: "anime_downloader"
developer: "projectdx"
description: "anime downloader"

View File

@@ -861,16 +861,23 @@ class LogicAniLife(AnimeModuleBase):
# tree = html.fromstring(response_data)
# logger.debug(response_data)
main_title = tree.xpath('//div[@class="infox"]/h1/text()')[0]
image = tree.xpath('//div[@class="thumb"]/img/@src')[0]
des_items = tree.xpath(
'//div[@class="info-content"]/div[@class="spe"]/span'
)
des_items1 = (
tree.xpath('//div[@class="info-content"]/div[@class="spe"]')[0]
.text_content()
.strip()
)
try:
main_title_node = tree.xpath('//div[@class="infox"]/h1/text()')
main_title = main_title_node[0] if main_title_node else "Unknown Title"
image_node = tree.xpath('//div[@class="thumb"]/img/@src')
image = image_node[0] if image_node else ""
des_items = tree.xpath(
'//div[@class="info-content"]/div[@class="spe"]/span'
)
des_spe_node = tree.xpath('//div[@class="info-content"]/div[@class="spe"]')
des_items1 = des_spe_node[0].text_content().strip() if des_spe_node else ""
except Exception as e:
logger.error(f"Error parsing series info: {e}")
logger.debug(f"HTML Content: {response.text[:1000]}") # Log first 1000 chars
return {"ret": "error", "log": "HTML 파싱 중 오류가 발생했습니다."}
des = {}
des_key = [

8
static/css/anilife.css Normal file
View File

@@ -0,0 +1,8 @@
/* Anilife Theme Variables */
:root {
--notify-bg: rgba(30, 27, 75, 0.95); /* Cosmic Violet */
--notify-border: rgba(139, 92, 246, 0.4);
--notify-success-bg: rgba(6, 78, 59, 0.95);
--notify-warning-bg: rgba(120, 53, 15, 0.95);
--notify-danger-bg: rgba(127, 29, 29, 0.95);
}

37
static/css/linkkf.css Normal file
View File

@@ -0,0 +1,37 @@
/* Linkkf Theme Variables & Overrides */
:root {
--forest-950: #022c22;
--forest-900: #064e3b;
--forest-800: #065f46;
--forest-500: #10b981;
--forest-400: #34d399;
--forest-100: #d1fae5;
--accent-amber: #fbbf24;
/* Shared Notify Variables */
--notify-bg: rgba(2, 44, 34, 0.95);
--notify-border: rgba(16, 185, 129, 0.3);
--notify-success-bg: rgba(6, 78, 59, 0.95);
--notify-warning-bg: rgba(120, 53, 15, 0.95);
--notify-danger-bg: rgba(127, 29, 29, 0.95);
}
body {
background-color: var(--forest-950) !important;
color: #ecfdf5;
}
/* Linkkf Specific Nav-Pills Overrides */
ul.nav.nav-pills.bg-light {
background-color: rgba(6, 78, 59, 0.4) !important;
border: 1px solid rgba(16, 185, 129, 0.1) !important;
}
ul.nav.nav-pills .nav-link {
color: #d1fae5 !important;
}
ul.nav.nav-pills .nav-link.active {
background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3) !important;
}

View File

@@ -0,0 +1,88 @@
/* Shared Mobile Custom CSS for Anime Downloader */
/* Custom Notify Styling for Mobile */
.bootstrap-notify-container,
[data-notify="container"] {
max-width: 90vw !important;
width: auto !important;
right: 5vw !important;
left: 5vw !important;
padding: 12px 16px !important;
border-radius: 10px !important;
background: var(--notify-bg) !important;
backdrop-filter: blur(10px) !important;
border: 1px solid var(--notify-border) !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4) !important;
color: #e0e7ff !important;
font-size: 13px !important;
z-index: 10000 !important;
}
[data-notify="container"].alert-success {
border-color: rgba(16, 185, 129, 0.4) !important;
background: var(--notify-success-bg, rgba(6, 78, 59, 0.95)) !important;
}
[data-notify="container"].alert-warning {
border-color: rgba(245, 158, 11, 0.4) !important;
background: var(--notify-warning-bg, rgba(120, 53, 15, 0.95)) !important;
}
[data-notify="container"].alert-danger {
border-color: rgba(239, 68, 68, 0.4) !important;
background: var(--notify-danger-bg, rgba(127, 29, 29, 0.95)) !important;
}
[data-notify="message"] {
color: #e0e7ff !important;
}
[data-notify="title"] {
color: #fff !important;
font-weight: 600 !important;
}
/* Common Mobile Responsive Fixes */
@media (max-width: 768px) {
body {
padding-top: 5px !important;
overflow-x: hidden !important;
}
/* Global Navigation Pills Fix */
ul.nav.nav-pills.bg-light {
margin-top: 50px !important;
margin-bottom: 10px !important;
width: 100% !important;
display: flex !important;
flex-wrap: wrap !important;
justify-content: center !important;
border-radius: 10px !important;
padding: 4px !important;
gap: 2px !important;
}
ul.nav.nav-pills .nav-link {
padding: 5px 12px !important;
font-size: 13px !important;
}
/* Layout Expansion on Mobile */
.container, .container-fluid, .row, form, #main_container {
width: 100% !important;
max-width: 100% !important;
padding-left: 8px !important;
padding-right: 8px !important;
margin-left: 0 !important;
margin-right: 0 !important;
box-sizing: border-box !important;
}
/* Card/Table Container Fix */
.card, .table-responsive {
width: 100% !important;
margin-left: 0 !important;
margin-right: 0 !important;
border-radius: 12px !important;
}
}

39
static/css/ohli24.css Normal file
View File

@@ -0,0 +1,39 @@
/* Ohli24 Theme Variables & Overrides */
:root {
--slate-950: #0f172a;
--slate-900: #0f172a; /* Same as 950 for deep background */
--slate-800: #1e293b;
--slate-700: #334155;
--blue-500: #3b82f6;
--blue-600: #2563eb;
--amber-400: #facc15;
/* Shared Notify Variables */
--notify-bg: rgba(15, 23, 42, 0.95);
--notify-border: rgba(59, 130, 246, 0.3);
--notify-success-bg: rgba(6, 78, 59, 0.95);
--notify-warning-bg: rgba(120, 53, 15, 0.95);
--notify-danger-bg: rgba(127, 29, 29, 0.95);
}
body {
background-color: var(--slate-950) !important;
color: #f1f5f9;
background-image: linear-gradient(135deg, #1f2937, #111827, #0f172a) !important;
background-attachment: fixed !important;
}
/* Ohli24 Specific Nav-Pills Overrides */
ul.nav.nav-pills.bg-light {
background-color: rgba(30, 41, 59, 0.6) !important;
border: 1px solid rgba(255, 255, 255, 0.08) !important;
}
ul.nav.nav-pills .nav-link {
color: #94a3b8 !important;
}
ul.nav.nav-pills .nav-link.active {
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4) !important;
}

View File

@@ -1,4 +1,7 @@
{% extends "base.html" %} {% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div id="preloader">
<div class='demo'>
<!-- <div class="loader-inner">-->
@@ -917,20 +920,6 @@
opacity: 0.5;
}
/* Mobile Responsive */
@media (max-width: 768px) {
body { padding-top: 10px !important; }
ul.nav.nav-pills.bg-light {
margin-top: 50px !important;
margin-bottom: 10px !important;
width: 100% !important;
display: flex !important;
border-radius: 12px !important;
}
ul.nav.nav-pills .nav-link {
padding: 6px 12px !important;
font-size: 13px;
}
}
</style>
{% endblock %}

View File

@@ -2,6 +2,8 @@
{% block content %}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<style>
body {
@@ -328,45 +330,10 @@
font-size: 11px !important;
}
}
/* Custom Notify Styling for Mobile */
.bootstrap-notify-container,
[data-notify="container"] {
max-width: 90vw !important;
width: auto !important;
right: 5vw !important;
left: 5vw !important;
padding: 12px 16px !important;
border-radius: 10px !important;
background: rgba(30, 27, 75, 0.95) !important;
backdrop-filter: blur(10px) !important;
border: 1px solid rgba(139, 92, 246, 0.3) !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4) !important;
color: #e0e7ff !important;
font-size: 13px !important;
z-index: 10000 !important;
}
[data-notify="container"].alert-success {
border-color: rgba(16, 185, 129, 0.4) !important;
background: rgba(6, 78, 59, 0.95) !important;
}
[data-notify="container"].alert-warning {
border-color: rgba(245, 158, 11, 0.4) !important;
background: rgba(120, 53, 15, 0.95) !important;
}
[data-notify="container"].alert-danger {
border-color: rgba(239, 68, 68, 0.4) !important;
background: rgba(127, 29, 29, 0.95) !important;
}
[data-notify="message"] {
color: #e0e7ff !important;
}
[data-notify="title"] {
color: #fff !important;
font-weight: 600 !important;
}
</style>
<div class="content-cloak">
<form id="form_search" class="form-inline" style="text-align:left; width:100%;">
<div class="search-container">

View File

@@ -1,5 +1,9 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div class="content-cloak">
<div class="d-flex justify-content-start align-items-center gap-2 mb-4">
@@ -190,6 +194,7 @@
str += ' <div class="meta-item"><i class="fa fa-clock-o"></i> <span id="card_download_time_' + data.idx + '">' + data.download_time + '</span></div>';
str += ' <div class="meta-item"><i class="fa fa-bolt"></i> <span id="card_current_speed_' + data.idx + '">' + data.current_speed + '</span></div>';
str += ' <div class="meta-item"><i class="fa fa-exclamation-triangle"></i> <span id="card_current_pf_count_' + data.idx + '">' + data.current_pf_count + '</span></div>';
str += ' </div>';
str += ' </div>';
str += ' <div id="card_button_' + data.idx + '" class="card-footer-actions">';
@@ -576,25 +581,10 @@
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
}
/* Mobile Logic Fix */
@media (max-width: 768px) {
body {
padding-top: 10px !important;
}
ul.nav.nav-pills.bg-light {
border-radius: 12px !important;
width: 100% !important;
display: flex !important;
margin-top: 50px !important; /* Ensure visibility below SJVA navbar */
margin-bottom: 10px !important;
}
ul.nav.nav-pills .nav-link {
padding: 6px 12px !important;
font-size: 13px;
}
}
</style>
<script type="text/javascript">
$(document).ready(function(){
// Smooth Load Trigger

View File

@@ -1,4 +1,8 @@
{% extends "base.html" %} {% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<style>
/* Global Container Margin Overrides */
@@ -398,8 +402,10 @@
$.notify('<strong>이미 큐에 있습니다. 삭제 후 추가하세요.</strong>', {type: 'warning'});
} else if (data.ret == 'db_completed') {
$.notify('<strong>DB에 완료 기록이 있습니다.</strong>', {type: 'warning'});
} else if (data.ret == 'file_exists') {
$.notify('<strong>파일이 이미 존재합니다.</strong>', {type: 'warning'});
} else {
$.notify('<strong>추가 실패</strong><br>' + ret.log, {type: 'warning'});
$.notify('<strong>추가 실패</strong><br>' + data.log, {type: 'warning'});
}
}
});
@@ -1265,30 +1271,6 @@ $(document).ready(function(){
}, 100);
});
</script>
<style>
/* Mobile Margin Fix */
@media (max-width: 768px) {
body { overflow-x: hidden !important; padding: 0 !important; margin: 0 !important; }
.container, .container-fluid, .row, form, #program_list, #program_auto_form, #episode_list, .queue-container, #yommi_wrapper, #main_container {
width: 100% !important; max-width: 100% !important;
padding-left: 4px !important; padding-right: 4px !important;
margin-left: 0 !important; margin-right: 0 !important;
box-sizing: border-box !important;
}
.form-group, .form-inline, [class*="col-"] {
flex: 0 0 100% !important; max-width: 100% !important; width: 100% !important;
padding-left: 0 !important; padding-right: 0 !important;
}
.row { margin-left: 0 !important; margin-right: 0 !important; }
.card, .card.p-4, .card.p-lg-5, .card.border-light {
width: calc(100% - 8px) !important; max-width: 100% !important;
padding: 8px !important; margin: 4px !important;
border-radius: 12px !important; box-sizing: border-box !important;
}
.badge {
white-space: normal !important; text-align: left !important;
line-height: 1.4 !important; height: auto !important; display: inline-block !important;
}
}
</style>
{% endblock %}

View File

@@ -1,4 +1,8 @@
{% extends "base.html" %} {% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div id="preloader" class="content-cloak">
<div class='demo'>
<!-- <div class="loader-inner">-->
@@ -802,6 +806,7 @@
line-height: 1.3;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
@@ -1226,63 +1231,6 @@ $(document).ready(function(){
}, 100);
});
</script>
<style>
/* Mobile Margin Fix */
@media (max-width: 768px) {
body { overflow-x: hidden !important; padding: 0 !important; margin: 0 !important; padding-top: 5px !important; }
/* First nav (main menu) */
ul.nav.nav-pills.bg-light:first-of-type {
margin-top: 50px !important;
margin-bottom: 5px !important;
}
/* Second nav (sub menu) */
ul.nav.nav-pills.bg-light {
margin-top: 0 !important;
margin-bottom: 8px !important;
width: 100% !important;
display: flex !important;
flex-wrap: wrap !important;
justify-content: center !important;
border-radius: 10px !important;
padding: 4px !important;
gap: 2px !important;
}
ul.nav.nav-pills .nav-link {
padding: 5px 10px !important;
font-size: 12px !important;
}
ul.nav.nav-pills .nav-item {
margin: 1px !important;
}
.container, .container-fluid, .row, form, #program_list, #program_auto_form, #episode_list, .queue-container, #yommi_wrapper, #main_container {
width: 100% !important; max-width: 100% !important;
padding-left: 4px !important; padding-right: 4px !important;
margin-left: 0 !important; margin-right: 0 !important;
box-sizing: border-box !important;
}
.form-group, .form-inline, [class*="col-"] {
flex: 0 0 100% !important; max-width: 100% !important; width: 100% !important;
padding-left: 0 !important; padding-right: 0 !important;
}
.row { margin-left: 0 !important; margin-right: 0 !important; }
.card, .card.p-4, .card.p-lg-5, .card.border-light {
width: calc(100% - 8px) !important; max-width: 100% !important;
padding: 8px !important; margin: 4px !important;
border-radius: 12px !important; box-sizing: border-box !important;
}
.badge {
white-space: normal !important; text-align: left !important;
line-height: 1.4 !important; height: auto !important; display: inline-block !important;
}
/* Search Button Size Reduction */
.input-group #btn_search {
padding: 8px 14px !important;
font-size: 13px !important;
}
}
</style>
{% endblock %}

View File

@@ -1,5 +1,8 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div id="anilife_setting_wrapper" class="container-fluid mt-4 mx-auto content-cloak" style="max-width: 100%;">
<div class="glass-card p-4">
@@ -308,23 +311,9 @@
background: rgba(59, 130, 246, 0.3) !important;
}
/* Mobile Responsive */
@media (max-width: 768px) {
body { padding-top: 10px !important; }
ul.nav.nav-pills.bg-light {
margin-top: 50px !important;
margin-bottom: 10px !important;
width: 100% !important;
display: flex !important;
border-radius: 12px !important;
}
ul.nav.nav-pills .nav-link {
padding: 6px 12px !important;
font-size: 13px;
}
}
</style>
<script type="text/javascript">
var package_name = "{{arg['package_name'] }}";
var sub = "{{arg['sub'] }}";

View File

@@ -1,4 +1,7 @@
{% extends "base.html" %} {% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div class="input-group mb-2">
<input

View File

@@ -1,67 +1,13 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<style>
:root {
--forest-950: #022c22;
--forest-900: #064e3b;
--forest-800: #065f46;
--forest-500: #10b981;
--forest-400: #34d399;
--forest-100: #d1fae5;
--accent-amber: #fbbf24;
}
body { background-color: var(--forest-950); color: #ecfdf5; font-family: 'Inter', 'Noto Sans KR', sans-serif; }
/* Layout Expansion */
#main_container, .container, .container-fluid, .content-cloak {
max-width: 100% !important;
padding-left: 5px !important;
padding-right: 5px !important;
margin: 0 auto !important;
}
.content-cloak { padding-top: 10px; }
/* Navigation (Tabs) Optimization */
/* Navigation Menu Override */
ul.nav.nav-pills.bg-light {
background-color: rgba(6, 78, 59, 0.4) !important;
backdrop-filter: blur(10px);
border: 1px solid rgba(16, 185, 129, 0.1);
border-radius: 50rem !important;
padding: 6px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2) !important;
display: inline-flex !important;
gap: 4px;
margin-bottom: 20px;
}
ul.nav.nav-pills .nav-link {
color: #d1fae5 !important;
font-weight: 600 !important;
padding: 8px 20px !important;
border-radius: 50rem !important;
transition: all 0.3s ease !important;
border: 1px solid transparent !important;
}
ul.nav.nav-pills .nav-link:hover {
background-color: rgba(16, 185, 129, 0.1) !important;
color: #fff !important;
transform: translateY(-1px);
}
ul.nav.nav-pills .nav-link.active {
background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
color: #fff !important;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3) !important;
}
/* Search Container */
.search-container {
background: rgba(6, 78, 59, 0.3);
backdrop-filter: blur(10px);
@@ -402,52 +348,6 @@ $(document).ready(function(){
--accent-amber: #fbbf24;
}
body { background-color: var(--forest-950); color: #ecfdf5; font-family: 'Inter', 'Noto Sans KR', sans-serif; }
/* Layout Expansion */
#main_container, .container, .container-fluid, .content-cloak {
max-width: 100% !important;
padding-left: 5px !important;
padding-right: 5px !important;
margin: 0 auto !important;
}
.content-cloak { padding-top: 10px; }
/* Navigation (Tabs) Optimization */
/* Navigation Menu Override */
ul.nav.nav-pills.bg-light {
background-color: rgba(6, 78, 59, 0.4) !important;
backdrop-filter: blur(10px);
border: 1px solid rgba(16, 185, 129, 0.1);
border-radius: 50rem !important;
padding: 6px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2) !important;
display: inline-flex !important;
gap: 4px;
margin-bottom: 20px;
}
ul.nav.nav-pills .nav-link {
color: #d1fae5 !important;
font-weight: 600 !important;
padding: 8px 20px !important;
border-radius: 50rem !important;
transition: all 0.3s ease !important;
border: 1px solid transparent !important;
}
ul.nav.nav-pills .nav-link:hover {
background-color: rgba(16, 185, 129, 0.1) !important;
color: #fff !important;
transform: translateY(-1px);
}
ul.nav.nav-pills .nav-link.active {
background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
color: #fff !important;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3) !important;
}
/* Search Container */
.search-container {
@@ -647,42 +547,6 @@ $(document).ready(function(){
}
}
/* Custom Notify Styling (Forest Theme) */
.bootstrap-notify-container,
[data-notify="container"] {
max-width: 90vw !important;
width: auto !important;
right: 5vw !important;
left: 5vw !important;
padding: 12px 16px !important;
border-radius: 10px !important;
background: rgba(2, 44, 34, 0.95) !important;
backdrop-filter: blur(10px) !important;
border: 1px solid rgba(16, 185, 129, 0.3) !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4) !important;
color: #ecfdf5 !important;
font-size: 13px !important;
z-index: 10000 !important;
}
[data-notify="container"].alert-success {
border-color: rgba(52, 211, 153, 0.4) !important;
background: rgba(6, 78, 59, 0.95) !important;
}
[data-notify="container"].alert-warning {
border-color: rgba(251, 191, 36, 0.4) !important;
background: rgba(120, 53, 15, 0.95) !important;
}
[data-notify="container"].alert-danger {
border-color: rgba(239, 68, 68, 0.4) !important;
background: rgba(127, 29, 29, 0.95) !important;
}
[data-notify="message"] {
color: #ecfdf5 !important;
}
[data-notify="title"] {
color: #fff !important;
font-weight: 600 !important;
}
</style>
<script type="text/javascript">

View File

@@ -1,59 +1,9 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<style>
:root {
--forest-950: #022c22;
--forest-900: #064e3b;
--forest-800: #065f46;
--forest-500: #10b981;
--forest-400: #34d399;
--forest-accent: #6ee7b7;
}
body { background-color: var(--forest-950) !important; color: #ecfdf5; }
/* Layout Expansion */
#main_container, .container, .container-fluid, #anime_downloader_wrapper {
max-width: 100% !important;
padding-left: 5px !important;
padding-right: 5px !important;
margin: 0 auto !important;
}
/* Navigation Menu Override */
ul.nav.nav-pills.bg-light {
background-color: rgba(6, 78, 59, 0.4) !important;
backdrop-filter: blur(10px);
border: 1px solid rgba(16, 185, 129, 0.1);
border-radius: 50rem !important;
padding: 6px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2) !important;
display: inline-flex !important;
gap: 4px;
margin-bottom: 20px;
}
ul.nav.nav-pills .nav-link {
color: #d1fae5 !important;
font-weight: 600 !important;
padding: 8px 20px !important;
border-radius: 50rem !important;
transition: all 0.3s ease !important;
border: 1px solid transparent !important;
}
ul.nav.nav-pills .nav-link:hover {
background-color: rgba(16, 185, 129, 0.1) !important;
color: #fff !important;
transform: translateY(-1px);
}
ul.nav.nav-pills .nav-link.active {
background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
color: #fff !important;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3) !important;
}
.queue-header-container {
display: flex; justify-content: space-between; align-items: flex-end;

View File

@@ -1,4 +1,7 @@
{% extends "base.html" %} {% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div id="anime_downloader_wrapper" class="content-cloak" style="max-width: 100%;">
<div id="preloader">
<div class='demo'>
@@ -317,6 +320,8 @@
$.notify('<strong>이미 큐에 있습니다. 삭제 후 추가하세요.</strong>', {type: 'warning'});
} else if (data.ret == 'db_completed') {
$.notify('<strong>DB에 완료 기록이 있습니다.</strong>', {type: 'warning'});
} else if (data.ret == 'file_exists') {
$.notify('<strong>파일이 이미 존재합니다.</strong>', {type: 'warning'});
} else {
$.notify('<strong>추가 실패</strong><br>' + ret.log, {type: 'warning'});
}

View File

@@ -1,4 +1,7 @@
{% extends "base.html" %} {% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<!--<div id="preloader"></div>-->
<div id="anime_downloader_wrapper" class="content-cloak">
<div id="preloader" class="loader">
@@ -978,6 +981,7 @@
padding: 0 !important;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}

View File

@@ -1,5 +1,8 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div id="linkkf_setting_wrapper" class="container-fluid mt-4 mx-auto content-cloak" style="max-width: 100%; padding-left: 5px; padding-right: 5px;">
<div class="glass-card p-4">

View File

@@ -1,5 +1,8 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div class="content-cloak">
<form id="form_search" class="form-inline" style="text-align:left; width:100%;">
@@ -97,40 +100,8 @@
</div>
<style>
.playlist-nav-btn {
width: 40px; height: 40px;
background: linear-gradient(135deg, #3b82f6, #2563eb);
border: none; border-radius: 50%;
color: white; font-size: 14px;
cursor: pointer; transition: all 0.2s ease;
display: flex; align-items: center; justify-content: center;
}
.playlist-nav-btn:hover { transform: scale(1.1); box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); }
.playlist-nav-btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }
.playlist-toggle-btn {
padding: 8px 14px;
background: rgba(100, 116, 139, 0.3);
border: 1px solid rgba(148, 163, 184, 0.3);
border-radius: 8px;
color: #94a3b8; font-size: 13px;
cursor: pointer; transition: all 0.2s ease;
}
.playlist-toggle-btn:hover { background: rgba(100, 116, 139, 0.5); color: #e2e8f0; }
.playlist-toggle-btn.active { background: rgba(59, 130, 246, 0.3); border-color: #3b82f6; color: #60a5fa; }
.playlist-item {
padding: 8px 12px; margin: 4px 0;
background: rgba(255,255,255,0.05);
border-radius: 6px; cursor: pointer;
color: #cbd5e1; font-size: 13px;
transition: all 0.2s ease;
display: flex; align-items: center; gap: 8px;
}
.playlist-item:hover { background: rgba(59, 130, 246, 0.2); }
.playlist-item.active { background: linear-gradient(135deg, rgba(59, 130, 246, 0.4), rgba(37, 99, 235, 0.4)); color: #fbbf24; font-weight: 600; }
.playlist-item .ep-num { color: #64748b; font-size: 11px; min-width: 40px; }
</style>
</style>
</div>
</div>
</div>
@@ -541,105 +512,6 @@
</script>
<style>
/* Navigation Menu Override */
ul.nav.nav-pills.bg-light {
background-color: rgba(30, 41, 59, 0.6) !important;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 50rem !important;
padding: 6px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2) !important;
display: inline-flex !important;
flex-wrap: wrap;
justify-content: center;
width: auto !important;
margin-bottom: 20px;
}
ul.nav.nav-pills .nav-item {
margin: 0 2px;
}
ul.nav.nav-pills .nav-link {
border-radius: 50rem !important;
padding: 8px 20px !important;
color: #94a3b8 !important;
font-weight: 600;
transition: all 0.3s ease;
}
ul.nav.nav-pills .nav-link:hover {
background-color: rgba(255, 255, 255, 0.1);
color: #fff !important;
transform: translateY(-1px);
}
ul.nav.nav-pills .nav-link.active {
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
color: #fff !important;
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
}
</style>
<style>
/* Smooth Load Transition */
.content-cloak,
#menu_module_div,
#menu_page_div {
opacity: 0;
transition: opacity 0.5s ease-out;
}
/* Staggered Delays for Natural Top-Down Flow */
#menu_module_div.visible {
opacity: 1;
transition-delay: 0ms;
}
#menu_page_div.visible {
opacity: 1;
transition-delay: 150ms;
}
.content-cloak.visible {
opacity: 1;
transition-delay: 300ms;
}
/* Navigation Menu Override (Top Sub-menu) */
ul.nav.nav-pills.bg-light {
background-color: rgba(30, 41, 59, 0.6) !important;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 50rem !important;
padding: 6px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2) !important;
display: inline-flex !important;
flex-wrap: wrap;
justify-content: center;
width: auto !important;
margin-bottom: 20px;
}
ul.nav.nav-pills .nav-item { margin: 0 2px; }
ul.nav.nav-pills .nav-link {
border-radius: 50rem !important;
padding: 8px 20px !important;
color: #94a3b8 !important;
font-weight: 600;
transition: all 0.3s ease;
}
ul.nav.nav-pills .nav-link:hover {
background-color: rgba(255, 255, 255, 0.1);
color: #fff !important;
transform: translateY(-1px);
}
ul.nav.nav-pills .nav-link.active {
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
color: #fff !important;
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
}
/* General Layout Tweaks */
.container-fluid {
@@ -1148,41 +1020,6 @@ $(document).ready(function(){
}
}
/* Custom Notify Styling (Slate Blue Theme) */
.bootstrap-notify-container,
[data-notify="container"] {
max-width: 90vw !important;
width: auto !important;
right: 5vw !important;
left: 5vw !important;
padding: 12px 16px !important;
border-radius: 10px !important;
background: rgba(15, 23, 42, 0.95) !important;
backdrop-filter: blur(10px) !important;
border: 1px solid rgba(59, 130, 246, 0.3) !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4) !important;
color: #e2e8f0 !important;
font-size: 13px !important;
z-index: 10000 !important;
}
[data-notify="container"].alert-success {
border-color: rgba(34, 197, 94, 0.4) !important;
background: rgba(21, 128, 61, 0.95) !important;
}
[data-notify="container"].alert-warning {
border-color: rgba(251, 191, 36, 0.4) !important;
background: rgba(120, 53, 15, 0.95) !important;
}
[data-notify="container"].alert-danger {
border-color: rgba(239, 68, 68, 0.4) !important;
background: rgba(127, 29, 29, 0.95) !important;
}
[data-notify="message"] {
color: #e2e8f0 !important;
}
[data-notify="title"] {
color: #fff !important;
font-weight: 600 !important;
}
</style>
{% endblock %}

View File

@@ -1,5 +1,8 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div class="queue-container content-cloak">
<!-- 헤더 버튼 그룹 -->
@@ -33,14 +36,6 @@
</div>
<style>
/* 상위 컨테이너 오버라이드 */
.container, .container-fluid, .row {
max-width: 100% !important;
padding-left: 16px !important;
padding-right: 16px !important;
margin-left: 0 !important;
margin-right: 0 !important;
}
/* 컨테이너 */
.queue-container {
@@ -425,44 +420,6 @@
animation: spin 0.8s linear infinite;
}
/* Navigation Menu Override */
ul.nav.nav-pills.bg-light {
background-color: rgba(30, 41, 59, 0.6) !important;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 50rem !important;
padding: 6px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2) !important;
display: inline-flex !important;
flex-wrap: wrap;
justify-content: center;
width: auto !important;
margin-bottom: 20px;
}
ul.nav.nav-pills .nav-item {
margin: 0 2px;
}
ul.nav.nav-pills .nav-link {
border-radius: 50rem !important;
padding: 8px 20px !important;
color: #94a3b8 !important;
font-weight: 600;
transition: all 0.3s ease;
}
ul.nav.nav-pills .nav-link:hover {
background-color: rgba(255, 255, 255, 0.1);
color: #fff !important;
transform: translateY(-1px);
}
ul.nav.nav-pills .nav-link.active {
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
color: #fff !important;
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
}
</style>
<script src="{{ url_for('.static', filename='js/sjva_ui14.js') }}"></script>
@@ -709,30 +666,5 @@ $(document).ready(function(){
}, 100);
});
</script>
<style>
/* Mobile Margin Fix */
@media (max-width: 768px) {
body { overflow-x: hidden !important; padding: 0 !important; margin: 0 !important; }
.container, .container-fluid, .row, form, #program_list, #program_auto_form, #episode_list, .queue-container, #yommi_wrapper, #main_container {
width: 100% !important; max-width: 100% !important;
padding-left: 4px !important; padding-right: 4px !important;
margin-left: 0 !important; margin-right: 0 !important;
box-sizing: border-box !important;
}
.form-group, .form-inline, [class*="col-"] {
flex: 0 0 100% !important; max-width: 100% !important; width: 100% !important;
padding-left: 0 !important; padding-right: 0 !important;
}
.row { margin-left: 0 !important; margin-right: 0 !important; }
.card, .card.p-4, .card.p-lg-5, .card.border-light {
width: calc(100% - 8px) !important; max-width: 100% !important;
padding: 8px !important; margin: 4px !important;
border-radius: 12px !important; box-sizing: border-box !important;
}
.badge {
white-space: normal !important; text-align: left !important;
line-height: 1.4 !important; height: auto !important; display: inline-block !important;
}
}
</style>
{% endblock %}

View File

@@ -1,4 +1,7 @@
{% extends "base.html" %} {% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div id="preloader">
<div class="demo">
<!-- <div class="loader-inner">-->
@@ -51,7 +54,7 @@
const package_name = "{{arg['package_name'] }}";
const sub = "{{arg['sub'] }}";
const ohli24_url = "{{arg['ohli24_url']}}";
{#let current_data = '';#}
// let current_data = '';
let accessibleCount = 1;
@@ -88,7 +91,7 @@
}
function analyze(wr_id, bo_table) {
{#e.preventDefault();#}
// e.preventDefault();
const code = document.getElementById("code").value
// // console.log(code)
@@ -265,7 +268,7 @@
// // console.log("{{ arg['code'] }}")
// // console.log('wr_id::', params.wr_id)
if (document.getElementById("code").value !== "") {
{#document.getElementById("analysis_btn").click()#}
// document.getElementById("analysis_btn").click()
$('#analysis_btn').click();
}
@@ -294,7 +297,7 @@
dataType: "json",
success: function (ret) {
if (ret.ret === 'success' && ret.data != null) {
// {#// // console.log(ret.code)#}
// console.log(ret.code)
// // console.log(ret.data)
make_program(ret.data)
} else {
@@ -371,8 +374,10 @@
$.notify('<strong>이미 큐에 있습니다. 삭제 후 추가하세요.</strong>', {type: 'warning'});
} else if (data.ret == 'db_completed') {
$.notify('<strong>DB에 완료 기록이 있습니다.</strong>', {type: 'warning'});
} else if (data.ret == 'file_exists') {
$.notify('<strong>파일이 이미 존재합니다.</strong>', {type: 'warning'});
} else {
$.notify('<strong>추가 실패</strong><br>' + ret.log, {type: 'warning'});
$.notify('<strong>추가 실패</strong><br>' + data.log, {type: 'warning'});
}
}
});

View File

@@ -1,4 +1,7 @@
{% extends "base.html" %} {% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div id="preloader" class="loader">
<div class="loader-inner">
@@ -147,18 +150,18 @@
if (current_screen_movie_data !== '') {
if (type === "ing") {
make_airing_list(ret.data, page)
{#observer.observe();#}
// observer.observe();
} else if (type === "fin") {
make_screen_movie_list(ret.data, page)
{#observer.observe();#}
// observer.observe();
} else if (type === "theater") {
make_screen_movie_list(ret.data, page)
{#observer.observe();#}
// observer.observe();
} else {
make_screen_movie_list(ret.data, page)
}
{#div_visible = true#}
{#// console.log(div_visible)#}
// div_visible = true
// // console.log(div_visible)
}
next_page = page + 1
}
@@ -483,7 +486,7 @@
// const observer = lozad(el); // passing a `NodeList` (e.g. `document.querySelectorAll()`) is also valid
// observer.observe();
const loadNextAnimes = (cate, page) => {
{#spinner.style.display = "block";#}
// spinner.style.display = "block";
let data = {type: cate, page: String(page)};
let url = ''
switch (cate) {
@@ -543,7 +546,7 @@
console.dir(e.target.scrollingElement.scrollHeight);
const {scrollTop, scrollHeight, clientHeight} = e.target.scrollingElement;
if (Math.round(scrollHeight - scrollTop) <= clientHeight) {
{#document.getElementById("spinner").style.display = "block";#}
// document.getElementById("spinner").style.display = "block";
// console.log("loading");
// console.log("now page::> ", page);
// console.log("next_page::> ", String(next_page));

View File

@@ -1,5 +1,8 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('.static', filename='css/mobile_custom.css') }}"/>
<link rel="stylesheet" href="{{ url_for('.static', filename='css/' ~ arg['sub'] ~ '.css') }}"/>
<div id="ohli24_setting_wrapper" class="container-fluid mt-4 mx-auto content-cloak" style="max-width: 100%;">
<div class="glass-card p-4">