优化模板选择的交互逻辑, 支持直接预览选择
@@ -22,7 +22,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Blurred background card style, suitable for graphic content display
|
||||
|
||||
@@ -30,7 +30,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Cartoon style, suitable for light and lively content
|
||||
|
||||
@@ -38,7 +38,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Default template, simple and versatile
|
||||
|
||||
@@ -46,7 +46,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Elegant style, suitable for artistic and intellectual content
|
||||
|
||||
@@ -54,7 +54,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Retro fashion style, suitable for nostalgic themes
|
||||
|
||||
@@ -62,7 +62,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Life insight style, suitable for inspirational content
|
||||
|
||||
@@ -70,7 +70,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Modern minimalist style, suitable for business and tech content
|
||||
|
||||
@@ -78,7 +78,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Neon style, suitable for fashion and trendy content
|
||||
|
||||
@@ -86,7 +86,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Psychology card style, suitable for knowledge popularization
|
||||
|
||||
@@ -94,7 +94,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Purple theme, suitable for dreamy and mysterious styles
|
||||
|
||||
@@ -102,7 +102,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Minimalist style, highlighting the content itself
|
||||
|
||||
@@ -110,7 +110,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
80s satirical cartoon style for spiritual tales
|
||||
|
||||
@@ -118,7 +118,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Simple black background, suitable for inspirational content
|
||||
|
||||
@@ -126,7 +126,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Simple line drawing style for cognitive growth content
|
||||
|
||||
@@ -134,7 +134,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Book style, suitable for book lists
|
||||
|
||||
@@ -142,7 +142,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Long text style, suitable for inspirational content
|
||||
|
||||
@@ -150,7 +150,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Excerpt style, suitable for quotes and book excerpts
|
||||
|
||||
@@ -158,7 +158,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Health preserving tips, suitable for wellness explainers.
|
||||
|
||||
@@ -166,7 +166,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Life insights, conveying warmth and strength
|
||||
|
||||
@@ -174,7 +174,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Full screen display, suitable for book lists
|
||||
|
||||
@@ -182,7 +182,7 @@ Suitable for TikTok, Kuaishou, Xiaohongshu, and other short video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Healing style, suitable for therapeutic content
|
||||
</div>
|
||||
@@ -199,7 +199,7 @@ Suitable for YouTube, Bilibili, and other video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Ultrawide minimalist style, suitable for desktop viewing
|
||||
|
||||
@@ -207,7 +207,7 @@ Suitable for YouTube, Bilibili, and other video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Dark tech style, suitable for technology and gaming content
|
||||
|
||||
@@ -215,7 +215,7 @@ Suitable for YouTube, Bilibili, and other video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Film style, immersive experience
|
||||
|
||||
@@ -223,7 +223,7 @@ Suitable for YouTube, Bilibili, and other video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Full screen display, suitable for book lists
|
||||
|
||||
@@ -231,7 +231,7 @@ Suitable for YouTube, Bilibili, and other video platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Book style, suitable for book lists
|
||||
|
||||
@@ -249,7 +249,7 @@ Suitable for Instagram, WeChat Moments, and other platforms.
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
Minimalist framed style, suitable for social media sharing
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 390 KiB After Width: | Height: | Size: 390 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 202 KiB After Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
@@ -22,7 +22,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
模糊背景卡片风格,适合图文内容展示
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
卡通风格,适合轻松活泼的内容
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
默认模板,简洁通用
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
优雅风格,适合文艺、知性内容
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
复古时尚风格,适合怀旧主题
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
生活感悟风格,适合心灵鸡汤类内容
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
现代简约风格,适合商务、科技内容
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
霓虹灯风格,适合时尚、潮流内容
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
心理学卡片风格,适合知识科普
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
紫色主题,适合梦幻、神秘风格
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
极简风格,突出内容本身
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
80年代讽刺漫画风格,适合精神类小故事
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
极简黑色背景,适合心灵鸡汤类内容
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
简笔画,适合认知成长类内容
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
图书解读,适合科普类内容
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
长文本,适合励志鸡汤类内容
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
图文摘抄,适合图文摘抄,名人名言
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
养生窍门,适合养生科普内容
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
人生感悟,传递温暖与力量
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
全屏模版,适合书单号
|
||||
|
||||
@@ -182,7 +182,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
治愈模版,适合疗愈类内容
|
||||
</div>
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
超宽屏极简风格,适合桌面端观看
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
暗黑科技风格,适合技术、游戏内容
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
电影风格,沉浸式体验
|
||||
|
||||
@@ -223,7 +223,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
全屏显示,适合书单号
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
图书解读,适合科普类内容
|
||||
</div>
|
||||
@@ -248,7 +248,7 @@
|
||||
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
极简边框风格,适合社交媒体分享
|
||||
|
||||
|
||||
@@ -228,6 +228,46 @@ def render_style_config(pixelle_video):
|
||||
# ====================================================================
|
||||
# Storyboard Template Section
|
||||
# ====================================================================
|
||||
|
||||
def get_template_preview_path(template_path: str, language: str = "zh_CN") -> str:
|
||||
"""
|
||||
Get the preview image path for a template based on language.
|
||||
|
||||
Args:
|
||||
template_path: Template path like "1080x1920/image_default.html"
|
||||
language: Language code, either "zh_CN" or "en"
|
||||
|
||||
Returns:
|
||||
Path to preview image in docs/images/
|
||||
"""
|
||||
# Extract size and template name from path
|
||||
# e.g., "1080x1920/image_default.html" -> size="1080x1920", name="image_default"
|
||||
path_parts = template_path.split('/')
|
||||
if len(path_parts) >= 2:
|
||||
size = path_parts[0] # e.g., "1080x1920"
|
||||
template_file = path_parts[1] # e.g., "image_default.html"
|
||||
template_name = template_file.replace('.html', '') # e.g., "image_default"
|
||||
|
||||
# Build preview image path
|
||||
# Format: docs/images/{size}/{template_name}.jpg or {template_name}_en.jpg
|
||||
# Chinese uses Chinese preview, all other languages use English preview for better i18n
|
||||
suffix = "" if language == "zh_CN" else "_en"
|
||||
|
||||
# Try different image extensions
|
||||
for ext in ['.jpg', '.png']:
|
||||
preview_path = f"docs/images/{size}/{template_name}{suffix}{ext}"
|
||||
if os.path.exists(preview_path):
|
||||
return preview_path
|
||||
|
||||
# Fallback: try without language suffix (for templates with only one version)
|
||||
for ext in ['.jpg', '.png']:
|
||||
preview_path = f"docs/images/{size}/{template_name}{ext}"
|
||||
if os.path.exists(preview_path):
|
||||
return preview_path
|
||||
|
||||
# If no preview found, return empty string
|
||||
return ""
|
||||
|
||||
with st.container(border=True):
|
||||
st.markdown(f"**{tr('section.template')}**")
|
||||
|
||||
@@ -284,18 +324,13 @@ def render_style_config(pixelle_video):
|
||||
st.warning(f"No {template_type_options[selected_template_type]} templates found. Please select a different type or add templates.")
|
||||
st.stop()
|
||||
|
||||
# Build display options with group separators
|
||||
# Build orientation i18n mapping
|
||||
ORIENTATION_I18N = {
|
||||
'portrait': tr('orientation.portrait'),
|
||||
'landscape': tr('orientation.landscape'),
|
||||
'square': tr('orientation.square')
|
||||
}
|
||||
|
||||
display_options = []
|
||||
template_paths_ordered = [] # Use ordered list instead of dict to avoid key conflicts
|
||||
default_index = 0
|
||||
current_index = 0
|
||||
|
||||
# Get default template from config
|
||||
template_config = pixelle_video.config.get("template", {})
|
||||
config_default_template = template_config.get("default_template", "1080x1920/image_default.html")
|
||||
@@ -312,68 +347,145 @@ def render_style_config(pixelle_video):
|
||||
}
|
||||
type_specific_default = type_default_templates.get(selected_template_type, config_default_template)
|
||||
|
||||
# Initialize selected template in session state if not exists
|
||||
if 'selected_template' not in st.session_state:
|
||||
st.session_state['selected_template'] = type_specific_default
|
||||
|
||||
# Collect size groups and prepare tabs
|
||||
size_groups = []
|
||||
size_labels = []
|
||||
|
||||
for size, templates in grouped_templates.items():
|
||||
if not templates:
|
||||
continue
|
||||
|
||||
# Filter templates to only include those with proper naming convention
|
||||
# Only show templates starting with static_, image_, or video_
|
||||
valid_templates = []
|
||||
for template in templates:
|
||||
template_name = template.display_info.name
|
||||
if template_name.startswith(('static_', 'image_', 'video_')):
|
||||
valid_templates.append(template)
|
||||
|
||||
# Skip if no valid templates after filtering
|
||||
if not valid_templates:
|
||||
continue
|
||||
|
||||
# Separate templates into two groups: with preview and without preview
|
||||
templates_with_preview = []
|
||||
templates_without_preview = []
|
||||
|
||||
for template in valid_templates:
|
||||
preview_path = get_template_preview_path(template.template_path, current_lang)
|
||||
if preview_path and os.path.exists(preview_path):
|
||||
templates_with_preview.append(template)
|
||||
else:
|
||||
templates_without_preview.append(template)
|
||||
|
||||
# Skip this group if no templates at all
|
||||
if not templates_with_preview and not templates_without_preview:
|
||||
continue
|
||||
|
||||
# Combine: templates with preview first, then without preview
|
||||
all_templates = templates_with_preview + templates_without_preview
|
||||
|
||||
# Get orientation from first template in group
|
||||
orientation = ORIENTATION_I18N.get(
|
||||
templates[0].display_info.orientation,
|
||||
templates[0].display_info.orientation
|
||||
all_templates[0].display_info.orientation,
|
||||
all_templates[0].display_info.orientation
|
||||
)
|
||||
width = templates[0].display_info.width
|
||||
height = templates[0].display_info.height
|
||||
width = all_templates[0].display_info.width
|
||||
height = all_templates[0].display_info.height
|
||||
|
||||
# Add group separator
|
||||
separator = f"─── {orientation} {width}×{height} ───"
|
||||
display_options.append(separator)
|
||||
template_paths_ordered.append(None) # Separator has no template path
|
||||
current_index += 1
|
||||
# Create tab label
|
||||
tab_label = f"{orientation} {width}×{height}"
|
||||
size_labels.append(tab_label)
|
||||
size_groups.append(all_templates)
|
||||
|
||||
# Create tabs for each size group (wrapped in expander)
|
||||
with st.expander(tr("template.gallery_view"), expanded=True):
|
||||
if size_groups:
|
||||
tabs = st.tabs(size_labels)
|
||||
|
||||
for tab, all_templates in zip(tabs, size_groups):
|
||||
with tab:
|
||||
# Create grid layout (5 columns)
|
||||
num_cols = 5
|
||||
cols = st.columns(num_cols)
|
||||
|
||||
for idx, template in enumerate(all_templates):
|
||||
col_idx = idx % num_cols
|
||||
with cols[col_idx]:
|
||||
# Get preview image path
|
||||
preview_path = get_template_preview_path(template.template_path, current_lang)
|
||||
|
||||
# Display preview image or placeholder
|
||||
if preview_path and os.path.exists(preview_path):
|
||||
st.image(preview_path, use_container_width=True)
|
||||
else:
|
||||
# Placeholder for templates without preview (fixed height, compact layout)
|
||||
st.markdown(
|
||||
f"""
|
||||
<div style="
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
height: 150px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
">
|
||||
<div style="
|
||||
font-size: 14px;
|
||||
opacity: 0.95;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 5;
|
||||
-webkit-box-orient: vertical;
|
||||
word-break: break-all;
|
||||
">{template.display_info.name}</div>
|
||||
</div>
|
||||
""",
|
||||
unsafe_allow_html=True
|
||||
)
|
||||
|
||||
# Select button (unified label)
|
||||
is_selected = (st.session_state['selected_template'] == template.template_path)
|
||||
button_label = f"{tr('template.selected')}" if is_selected else tr('template.select_button')
|
||||
button_type = "primary" if is_selected else "secondary"
|
||||
|
||||
if st.button(
|
||||
button_label,
|
||||
key=f"template_{template.template_path}",
|
||||
use_container_width=True,
|
||||
type=button_type,
|
||||
):
|
||||
st.session_state['selected_template'] = template.template_path
|
||||
st.rerun()
|
||||
else:
|
||||
st.warning(tr("template.no_templates_with_preview"))
|
||||
|
||||
# Add templates in this group
|
||||
for t in templates:
|
||||
display_name = f" {t.display_info.name}"
|
||||
display_options.append(display_name)
|
||||
template_paths_ordered.append(t.template_path) # Add to ordered list
|
||||
|
||||
# Set default: priority is config > type-specific default > first in portrait
|
||||
if t.template_path == config_default_template:
|
||||
default_index = current_index
|
||||
elif default_index == 0 and t.template_path == type_specific_default:
|
||||
default_index = current_index
|
||||
elif default_index == 0 and t.display_info.orientation == 'portrait':
|
||||
default_index = current_index
|
||||
|
||||
current_index += 1
|
||||
|
||||
# Dropdown with grouped display
|
||||
# Create unique display strings by appending hidden unique identifier
|
||||
# This ensures Streamlit doesn't confuse templates with same name in different groups
|
||||
unique_display_options = []
|
||||
for i, option in enumerate(display_options):
|
||||
# Add zero-width space characters as unique identifier (invisible to users)
|
||||
unique_option = option + ("\u200B" * i) # \u200B is zero-width space
|
||||
unique_display_options.append(unique_option)
|
||||
|
||||
selected_unique_option = st.selectbox(
|
||||
tr("template.select"),
|
||||
unique_display_options,
|
||||
index=default_index,
|
||||
label_visibility="collapsed",
|
||||
help=tr("template.select_help")
|
||||
)
|
||||
|
||||
# Get index from selected unique option
|
||||
selected_index = unique_display_options.index(selected_unique_option)
|
||||
|
||||
# Check if separator is selected (shouldn't happen, but handle it)
|
||||
if display_options[selected_index].startswith("───"):
|
||||
st.warning(tr("template.separator_selected"))
|
||||
st.stop()
|
||||
|
||||
# Get full template path directly by index
|
||||
frame_template = template_paths_ordered[selected_index]
|
||||
# Display selected template name (inside expander, below tabs)
|
||||
frame_template = st.session_state['selected_template']
|
||||
|
||||
# Find the selected template's display name
|
||||
selected_template_name = None
|
||||
for size, templates in grouped_templates.items():
|
||||
for template in templates:
|
||||
if template.template_path == frame_template:
|
||||
selected_template_name = template.display_info.name
|
||||
break
|
||||
if selected_template_name:
|
||||
break
|
||||
|
||||
if selected_template_name:
|
||||
st.info(f"📋 {tr('template.selected_template')}: **{selected_template_name}**")
|
||||
|
||||
|
||||
# Display video size from template
|
||||
from pixelle_video.utils.template_util import parse_template_size
|
||||
video_width, video_height = parse_template_size(frame_template)
|
||||
|
||||
@@ -103,6 +103,11 @@
|
||||
"template.preview_image_help": "Supports local path or URL",
|
||||
"template.preview_caption": "Template Preview: {template}",
|
||||
"template.custom_parameters": "Custom Parameters",
|
||||
"template.gallery_view": "Template Gallery",
|
||||
"template.select_button": "Check",
|
||||
"template.selected": "Checked",
|
||||
"template.selected_template": "Current Template",
|
||||
"template.no_templates_with_preview": "⚠️ No templates available for this type",
|
||||
"image.not_required": "Current template does not require image generation",
|
||||
"image.not_required_hint": "The selected template is text-only and does not need images. Benefits: ⚡ Faster generation 💰 Lower cost",
|
||||
"video.title": "🎬 Video Settings",
|
||||
|
||||
@@ -103,6 +103,11 @@
|
||||
"template.preview_image_help": "支持本地路径或 URL",
|
||||
"template.preview_caption": "模板预览:{template}",
|
||||
"template.custom_parameters": "自定义参数",
|
||||
"template.gallery_view": "模板库",
|
||||
"template.select_button": "选择",
|
||||
"template.selected": "已选",
|
||||
"template.selected_template": "当前模板",
|
||||
"template.no_templates_with_preview": "⚠️ 该类型暂无可用模板",
|
||||
"image.not_required": "当前模板不需要插图生成",
|
||||
"image.not_required_hint": "您选择的模板是纯文本模板,无需生成图片。这将:⚡ 加快生成速度 💰 降低生成成本",
|
||||
"video.title": "🎬 视频设置",
|
||||
|
||||