Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import toml | |
| from pathlib import Path | |
| import os | |
| import time | |
| class ThemeSelector: | |
| def __init__( | |
| self, themes_dir=".streamlit/themes", config_path=".streamlit/config.toml" | |
| ): | |
| self.themes_dir = Path(themes_dir) | |
| self.config_path = Path(config_path) | |
| self.themes = {} | |
| self.load_themes() | |
| def load_themes(self): | |
| """加载所有主题文件""" | |
| self.themes = {} | |
| if not self.themes_dir.exists(): | |
| return | |
| for theme_file in self.themes_dir.glob("*.toml"): | |
| try: | |
| theme_data = toml.load(theme_file) | |
| # 从根级别获取theme_name和theme_poem | |
| theme_name = theme_data.get("theme_name", theme_file.stem) | |
| theme_poem = theme_data.get("theme_poem", "") | |
| theme_config = theme_data.get("theme", {}) | |
| self.themes[theme_name] = { | |
| "file": theme_file, | |
| "name": theme_name, | |
| "poem": theme_poem, | |
| "config": theme_config, | |
| } | |
| except Exception as e: | |
| st.warning(f"读取主题文件 {theme_file} 失败: {e}") | |
| def get_current_theme(self): | |
| """获取当前主题名称""" | |
| if not self.config_path.exists(): | |
| return None | |
| try: | |
| # config = toml.load(self.config_path) | |
| # # 从根级别读取theme_name | |
| # current_theme_name = config.get("theme") or {} | |
| # current_theme_name = current_theme_name.get("theme_name") | |
| # return current_theme_name | |
| theme_toml = self.config_path.parent / "theme.toml" | |
| theme = toml.load(theme_toml) | |
| return theme.get("theme_name") | |
| except Exception: | |
| return None | |
| def apply_theme(self, theme_name): | |
| """应用选定的主题""" | |
| if theme_name not in self.themes: | |
| st.error(f"主题 '{theme_name}' 不存在") | |
| return False | |
| try: | |
| # 确保配置目录存在 | |
| self.config_path.parent.mkdir(parents=True, exist_ok=True) | |
| # 读取现有配置或创建新配置 | |
| config = {} | |
| if self.config_path.exists(): | |
| try: | |
| config = toml.load(self.config_path) | |
| except Exception: | |
| config = {} | |
| # 添加根级别的theme_name和theme_poem | |
| # config["theme_name"] = self.themes[theme_name]["name"] | |
| # config["theme_poem"] = self.themes[theme_name]["poem"] | |
| # 更新主题配置 | |
| theme_config = self.themes[theme_name]["config"].copy() | |
| # theme_config["theme_name"] = self.themes[theme_name]["name"] | |
| # theme_config["theme_poem"] = self.themes[theme_name]["poem"] | |
| config["theme"] |= theme_config | |
| # 写入配置文件 | |
| with open(self.config_path, "w", encoding="utf-8") as f: | |
| toml.dump(config, f) | |
| theme_toml = self.config_path.parent / "theme.toml" | |
| with open(theme_toml, "w", encoding="utf-8") as f: | |
| toml.dump( | |
| dict( | |
| theme_name=self.themes[theme_name]["name"], | |
| theme_poem=self.themes[theme_name]["poem"], | |
| ), | |
| f, | |
| ) | |
| return True | |
| except Exception as e: | |
| st.error(f"应用主题失败: {e}") | |
| return False | |
| def render_theme_selector(self): | |
| """渲染主题选择器UI""" | |
| if not self.themes: | |
| st.warning("未找到可用主题") | |
| return | |
| theme_names = list(self.themes.keys()) | |
| current_theme = self.get_current_theme() | |
| # 确定当前选中的索引 | |
| current_index = 0 | |
| if current_theme and current_theme in theme_names: | |
| current_index = theme_names.index(current_theme) | |
| # 主题选择下拉菜单 | |
| selected_theme = st.selectbox( | |
| "选择主题", | |
| options=theme_names, | |
| index=current_index, | |
| format_func=lambda x: self.themes[x]["name"], | |
| key="theme_selector_widget", | |
| label_visibility="collapsed", | |
| ) | |
| # 如果选择了新主题 | |
| if selected_theme != current_theme: | |
| if self.apply_theme(selected_theme): | |
| # 显示主题诗句 | |
| theme_poem = self.themes[selected_theme]["poem"] | |
| if theme_poem: | |
| st.toast(f"✨ {theme_poem}", icon="🎨") | |
| else: | |
| st.toast(f"已切换到主题: {selected_theme}", icon="🎨") | |
| time.sleep(3) | |
| # 延迟重新运行以应用主题 | |
| st.rerun() | |
| return selected_theme | |
| # 全局主题选择器实例 | |
| _theme_selector = None | |
| def get_theme_selector(): | |
| """获取全局主题选择器实例""" | |
| global _theme_selector | |
| if _theme_selector is None: | |
| _theme_selector = ThemeSelector() | |
| return _theme_selector | |
| def render_theme_selector(): | |
| """便捷函数:渲染主题选择器""" | |
| return get_theme_selector().render_theme_selector() | |