mirror of
https://github.com/sean2077/obsidian-dynamic-theme-background.git
synced 2026-07-22 16:40:29 +00:00
feat: Add status bar button, support one-button random, one-button save, one-button open settings
添加状态栏按钮,支持一键随机、一键保存、一键打开设置
This commit is contained in:
parent
dd4d3ef951
commit
6ae8d2c72b
9 changed files with 401 additions and 124 deletions
|
|
@ -2,12 +2,13 @@
|
|||
* 命令管理器 - 统一管理所有插件命令
|
||||
*/
|
||||
import { Command } from "obsidian";
|
||||
import DynamicThemeBackgroundPlugin from "../plugin";
|
||||
import type DynamicThemeBackgroundPlugin from "../plugin";
|
||||
|
||||
// 导入所有命令创建函数
|
||||
import { createFetchWallpaperCommand } from "./fetch-wallpaper-command";
|
||||
import { createNextBackgroundCommand } from "./next-background-command";
|
||||
import { createOpenSettingsCommand } from "./open-settings-command";
|
||||
import { createSaveBackgroundCommand } from "./save-background-command";
|
||||
import { createTestBackgroundCommand } from "./test-background-command";
|
||||
import { createToggleCommand } from "./toggle-command";
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ export function registerCommands(plugin: DynamicThemeBackgroundPlugin): void {
|
|||
createTestBackgroundCommand(plugin),
|
||||
createFetchWallpaperCommand(plugin),
|
||||
createOpenSettingsCommand(plugin),
|
||||
createSaveBackgroundCommand(plugin),
|
||||
];
|
||||
|
||||
commands.forEach((command) => {
|
||||
|
|
|
|||
16
src/commands/save-background-command.ts
Normal file
16
src/commands/save-background-command.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* 保存当前背景命令
|
||||
*/
|
||||
import { Command } from "obsidian";
|
||||
import { t } from "../i18n";
|
||||
import DynamicThemeBackgroundPlugin from "../plugin";
|
||||
|
||||
export function createSaveBackgroundCommand(plugin: DynamicThemeBackgroundPlugin): Command {
|
||||
return {
|
||||
id: "save-current-background",
|
||||
name: t("command_save_current_background_name"),
|
||||
callback: async () => {
|
||||
await plugin.saveBackground();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ let DEFAULT_SETTINGS: DTBSettings;
|
|||
function genDefaultSettings(): DTBSettings {
|
||||
DEFAULT_SETTINGS = {
|
||||
enabled: true,
|
||||
statusBarEnabled: true, // 是否激活状态栏
|
||||
|
||||
// 全局背景模糊度、亮度和饱和度变量、背景颜色等
|
||||
blurDepth: 0,
|
||||
|
|
@ -84,6 +85,7 @@ function genDefaultSettings(): DTBSettings {
|
|||
intervalMinutes: 60,
|
||||
|
||||
// 背景管理
|
||||
localBackgroundFolder: "",
|
||||
backgrounds: [
|
||||
{
|
||||
id: "blue-purple-gradient",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ export default {
|
|||
enable_plugin_desc: "Turn the dynamic background feature on or off.",
|
||||
basic_settings_title: "Basic Settings",
|
||||
reload_plugin_tooltip: "Refresh Background",
|
||||
enable_status_bar_name: "Enable Status Bar",
|
||||
enable_status_bar_desc: "Turn the status bar feature on or off.",
|
||||
status_bar_title:
|
||||
"🖱️Left Click: Switch Random Wallpaper\n🖱️Middle Click: Open Settings Tab\n🖱️Right Click: Save Current Background",
|
||||
|
||||
// ===== 外观设置 =====
|
||||
appearance_settings_title: "Appearance Settings",
|
||||
|
|
@ -75,12 +79,12 @@ export default {
|
|||
add_folder_bg_button: "Add Image Folder",
|
||||
restore_default_bg_button: "Restore Defaults",
|
||||
restore_default_bg_tooltip: "Add default gradient backgrounds to the list",
|
||||
restore_default_bg_success: "Successfully added {count} default backgrounds",
|
||||
restore_default_bg_success: "🎉 Successfully added {count} default backgrounds",
|
||||
restore_default_bg_no_new: "All default backgrounds already exist in the list",
|
||||
add_folder_modal_title: "Add Images from Folder",
|
||||
folder_path_label: "Folder Path (vault internal path):",
|
||||
folder_path_placeholder: "e.g., assets/images or photos",
|
||||
folder_scan_success: "Successfully added {count} images from folder",
|
||||
folder_scan_success: "🎉 Successfully added {count} images from folder",
|
||||
folder_scan_error: "Failed to scan folder: {error}",
|
||||
folder_not_found: "Folder not found or empty",
|
||||
folder_no_new_images: "All images in this folder already exist in the background list",
|
||||
|
|
@ -93,12 +97,14 @@ export default {
|
|||
color_value_label: "Color value (e.g. #ff0000):",
|
||||
gradient_css_label: "CSS gradient (e.g. linear-gradient(45deg, #ff0000, #0000ff)):",
|
||||
select_background_option: "Select Background",
|
||||
drag_hint_text: "💡 Tip: You can drag background items to reorder them",
|
||||
background_management_hint: "💡 Tip: You can drag background items to reorder them",
|
||||
drag_handle_tooltip: "Drag to reorder",
|
||||
random_wallpaper_settings_title: "Random Wallpaper Settings",
|
||||
enable_random_wallpaper_name: "Enable Random Wallpaper",
|
||||
enable_random_wallpaper_desc:
|
||||
"When enabled, random wallpapers will be fetched from wallpaper APIs and the background list, otherwise it will use the background list in order.",
|
||||
save_image_path_title: "Save Image Path",
|
||||
save_image_path_placeholder: "Enter the path to save the image",
|
||||
|
||||
// ===== 壁纸API管理 =====
|
||||
wallpaper_api_management_title: "Wallpaper API Management",
|
||||
|
|
@ -121,20 +127,21 @@ export default {
|
|||
// ===== 命令相关 =====
|
||||
command_open_settings_tab_name: "Open Settings in New Tab",
|
||||
command_toggle_name: "Toggle dynamic background",
|
||||
command_toggle_enabled_notice: "Dynamic background enabled",
|
||||
command_toggle_disabled_notice: "Dynamic background disabled",
|
||||
command_toggle_enabled_notice: "✅ DTB: Dynamic background enabled",
|
||||
command_toggle_disabled_notice: "❌ DTB: Dynamic background disabled",
|
||||
command_next_bg_name: "Switch to next background",
|
||||
command_next_bg_notice: "Background switched to: {bgName}",
|
||||
command_next_bg_notice: "🎨 DTB: Background switched to: {bgName}",
|
||||
command_test_bg_name: "Test current time period background",
|
||||
command_test_bg_success_notice: "Current period: {ruleName}, Background: {bgName}",
|
||||
command_test_bg_no_bg_notice: "No background set for period {ruleName}",
|
||||
command_test_bg_no_rule_notice: "No matching rule for the current time",
|
||||
command_test_bg_not_supported_notice: "Current mode does not support background testing",
|
||||
command_test_bg_success_notice: "🕒 DTB: Current period: {ruleName}, Background: {bgName}",
|
||||
command_test_bg_no_bg_notice: "⚠️ DTB: No background set for period {ruleName}",
|
||||
command_test_bg_no_rule_notice: "⚠️ DTB: No matching rule for the current time",
|
||||
command_test_bg_not_supported_notice: "⚠️ DTB: Current mode does not support background testing",
|
||||
command_fetch_random_wallpaper_name: "Fetch Random Wallpaper",
|
||||
command_fetch_random_wallpaper_notice_disabled: "Please enable random wallpaper feature in settings first",
|
||||
command_fetch_random_wallpaper_notice_success: "Applied random wallpaper",
|
||||
command_fetch_random_wallpaper_notice_disabled: "⚠️ DTB: Please enable random wallpaper feature in settings first",
|
||||
command_fetch_random_wallpaper_notice_success: "🎉 DTB: Applied random wallpaper",
|
||||
command_fetch_random_wallpaper_notice_failed:
|
||||
"Failed to fetch random wallpaper, please check API settings and network connection",
|
||||
"❌ DTB: Failed to fetch random wallpaper, please check API settings and network connection",
|
||||
command_save_current_background_name: "Save Current Background",
|
||||
|
||||
// ===== 通用按钮文本 =====
|
||||
button_cancel: "Cancel",
|
||||
|
|
@ -146,6 +153,7 @@ export default {
|
|||
button_test: "Test",
|
||||
button_update: "Update",
|
||||
button_add: "Add",
|
||||
button_save: "Save",
|
||||
|
||||
// ===== 默认配置相关 =====
|
||||
default_morning_rule: "Morning",
|
||||
|
|
@ -164,24 +172,31 @@ export default {
|
|||
dark_blue_gray_gradient_bg: "Dark Blue Gray Gradient",
|
||||
|
||||
// ===== Notice 消息 =====
|
||||
notice_all_fields_required: "Please provide all required fields",
|
||||
notice_name_and_value_required: "Please provide both name and value",
|
||||
notice_valid_folder_path_required: "Please provide a valid folder path",
|
||||
notice_folder_not_found: "Folder not found",
|
||||
notice_folder_added_successfully: 'Images from folder "{folderPath}" added successfully',
|
||||
notice_error_adding_folder_images: "Error adding images from folder",
|
||||
notice_api_failed_enable_disable: "❌ Failed to {action} {apiName}",
|
||||
notice_api_success_enable_disable: "✅ Successfully {action} {apiName}",
|
||||
notice_api_error_enable_disable: "❌ Error {action} {apiName}",
|
||||
notice_api_disabled: "❌ {apiName}: API is disabled",
|
||||
notice_api_fetching: "🔄 Fetching wallpaper from {apiName}...",
|
||||
notice_api_success_applied: "✅ Successfully applied wallpaper from {apiName}",
|
||||
notice_api_failed_fetch: "❌ Failed to fetch wallpaper from {apiName}",
|
||||
notice_api_error_fetch: "❌ Error fetching wallpaper from {apiName}: {error}",
|
||||
notice_api_fetching_generic: "🔄 Fetching wallpaper from API...",
|
||||
notice_api_success_applied_generic: "✅ Successfully applied random wallpaper!",
|
||||
notice_api_no_available: "❌ No wallpaper APIs available or all APIs failed",
|
||||
notice_api_error_generic: "❌ Error fetching wallpaper from API",
|
||||
notice_all_fields_required: "⚠️ DTB: Please provide all required fields",
|
||||
notice_name_and_value_required: "⚠️ DTB: Please provide both name and value",
|
||||
notice_valid_folder_path_required: "⚠️ DTB: Please provide a valid folder path",
|
||||
notice_folder_not_found: "❌ DTB: Folder not found",
|
||||
notice_folder_added_successfully: '🎉 DTB: Images from folder "{folderPath}" added successfully',
|
||||
notice_error_adding_folder_images: "❌ DTB: Error adding images from folder",
|
||||
notice_api_failed_enable_disable: "❌ DTB: Failed to {action} {apiName}",
|
||||
notice_api_success_enable_disable: "🎉 DTB: Successfully {action} {apiName}",
|
||||
notice_api_error_enable_disable: "❌ DTB: Error {action} {apiName}",
|
||||
notice_api_disabled: "❌ DTB: {apiName}: API is disabled",
|
||||
notice_api_fetching: "🔄 DTB: Fetching wallpaper from {apiName}...",
|
||||
notice_api_success_applied: "🎉 DTB: Successfully applied wallpaper from {apiName}",
|
||||
notice_api_failed_fetch: "❌ DTB: Failed to fetch wallpaper from {apiName}",
|
||||
notice_api_error_fetch: "❌ DTB: Error fetching wallpaper from {apiName}: {error}",
|
||||
notice_api_fetching_generic: "🔄 DTB: Fetching wallpaper from API...",
|
||||
notice_api_success_applied_generic: "🎉 DTB: Successfully applied random wallpaper!",
|
||||
notice_api_no_available: "❌ DTB: No wallpaper APIs available or all APIs failed",
|
||||
notice_api_error_generic: "❌ DTB: Error fetching wallpaper from API",
|
||||
notice_save_background_no_need_save_local: "🎉 DTB: Current background is a local image, no need to save",
|
||||
notice_save_background_valid_folder_path_required:
|
||||
"⚠️ DTB: Please provide a valid folder path to save the wallpaper",
|
||||
notice_save_background_only_image_supported: "⚠️ DTB: Only image backgrounds are supported for saving",
|
||||
notice_save_background_success: "🎉 DTB: Current background saved to {folderPath}",
|
||||
notice_save_background_failed:
|
||||
"❌ DTB: Failed to save current background, please check folder path and permissions",
|
||||
|
||||
// ===== API 模态窗口 =====
|
||||
api_modal_invalid_json: "Invalid JSON in extra parameters",
|
||||
|
|
@ -189,7 +204,7 @@ export default {
|
|||
api_modal_invalid_params: "Invalid API parameters: {errors}",
|
||||
api_modal_testing_config: "Testing API configuration...",
|
||||
api_modal_cannot_test_invalid: "Cannot test due to invalid configuration",
|
||||
api_modal_test_successful: "API test successful!",
|
||||
api_modal_test_successful: "🎉 API test successful!",
|
||||
api_modal_test_failed: "API test failed: {error}",
|
||||
api_modal_api_url: "API URL",
|
||||
api_modal_headers_optional: "Headers (optional)",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ export default {
|
|||
enable_plugin_desc: "开启或关闭动态背景功能",
|
||||
basic_settings_title: "基础设置",
|
||||
reload_plugin_tooltip: "刷新背景",
|
||||
enable_status_bar_name: "启用状态栏",
|
||||
enable_status_bar_desc: "开启或关闭状态栏功能: ",
|
||||
status_bar_title: "🖱️左键:切换随机壁纸\n🖱️中键:打开设置标签页\n🖱️右键:保存当前背景",
|
||||
|
||||
// ===== 外观设置 =====
|
||||
appearance_settings_title: "外观设置",
|
||||
|
|
@ -70,12 +73,12 @@ export default {
|
|||
add_folder_bg_button: "添加图片文件夹",
|
||||
restore_default_bg_button: "恢复默认",
|
||||
restore_default_bg_tooltip: "将默认渐变背景添加到列表中",
|
||||
restore_default_bg_success: "成功添加了 {count} 个默认背景",
|
||||
restore_default_bg_success: "🎉 成功添加了 {count} 个默认背景",
|
||||
restore_default_bg_no_new: "所有默认背景已存在于列表中",
|
||||
add_folder_modal_title: "从文件夹添加图片",
|
||||
folder_path_label: "文件夹路径(库内路径):",
|
||||
folder_path_placeholder: "例如:assets/images 或 photos",
|
||||
folder_scan_success: "成功从文件夹添加了 {count} 张图片",
|
||||
folder_scan_success: "🎉 成功从文件夹添加了 {count} 张图片",
|
||||
folder_scan_error: "扫描文件夹失败:{error}",
|
||||
folder_not_found: "文件夹未找到或为空",
|
||||
folder_no_new_images: "此文件夹中的所有图片已存在于背景列表中",
|
||||
|
|
@ -88,11 +91,13 @@ export default {
|
|||
color_value_label: "颜色值(如 #ff0000):",
|
||||
gradient_css_label: "CSS 渐变(如 linear-gradient(45deg, #ff0000, #0000ff)):",
|
||||
select_background_option: "选择背景",
|
||||
drag_hint_text: "💡 提示:您可以拖拽背景项目来重新排序",
|
||||
background_management_hint: "💡 提示:您可以拖拽背景项目来重新排序",
|
||||
drag_handle_tooltip: "拖拽以重新排序",
|
||||
random_wallpaper_settings_title: "随机壁纸设置",
|
||||
enable_random_wallpaper_name: "启用随机壁纸",
|
||||
enable_random_wallpaper_desc: "启用后,将从壁纸网站 API 和背景列表中获取随机壁纸,否则将从背景列表按顺序获取",
|
||||
save_image_path_title: "保存图片路径",
|
||||
save_image_path_placeholder: "请输入保存图片的路径",
|
||||
|
||||
// ===== 壁纸API管理 =====
|
||||
wallpaper_api_management_title: "壁纸 API 管理",
|
||||
|
|
@ -112,19 +117,20 @@ export default {
|
|||
// ===== 命令相关 =====
|
||||
command_open_settings_tab_name: "在新标签页中打开设置",
|
||||
command_toggle_name: "切换动态背景开关",
|
||||
command_toggle_enabled_notice: "动态背景已启用",
|
||||
command_toggle_disabled_notice: "动态背景已禁用",
|
||||
command_toggle_enabled_notice: "✅ DTB: 动态背景已启用",
|
||||
command_toggle_disabled_notice: "❌ DTB: 动态背景已禁用",
|
||||
command_next_bg_name: "切换到下一个背景",
|
||||
command_next_bg_notice: "背景已切换为:{bgName}",
|
||||
command_next_bg_notice: "🔄 DTB: 背景已切换为:{bgName}",
|
||||
command_test_bg_name: "测试当前时间段背景",
|
||||
command_test_bg_success_notice: "当前时间段:{ruleName},背景:{bgName}",
|
||||
command_test_bg_no_bg_notice: "时间段 {ruleName} 没有设置背景",
|
||||
command_test_bg_no_rule_notice: "当前时间没有匹配的规则",
|
||||
command_test_bg_not_supported_notice: "非时段模式不支持该测试命令",
|
||||
command_test_bg_success_notice: "🕒 DTB: 当前时间段:{ruleName},背景:{bgName}",
|
||||
command_test_bg_no_bg_notice: "⚠️ DTB: 时间段 {ruleName} 没有设置背景",
|
||||
command_test_bg_no_rule_notice: "⚠️ DTB: 当前时间没有匹配的规则",
|
||||
command_test_bg_not_supported_notice: "🚫 DTB: 非时段模式不支持该测试命令",
|
||||
command_fetch_random_wallpaper_name: "获取随机壁纸",
|
||||
command_fetch_random_wallpaper_notice_disabled: "请先在设置中启用随机壁纸功能",
|
||||
command_fetch_random_wallpaper_notice_success: "已应用随机壁纸",
|
||||
command_fetch_random_wallpaper_notice_failed: "获取随机壁纸失败,请检查 API 设置和网络连接",
|
||||
command_fetch_random_wallpaper_notice_disabled: "⚠️ DTB: 请先在设置中启用随机壁纸功能",
|
||||
command_fetch_random_wallpaper_notice_success: "✅ DTB: 已应用随机壁纸",
|
||||
command_fetch_random_wallpaper_notice_failed: "❌ DTB: 获取随机壁纸失败,请检查 API 设置和网络连接",
|
||||
command_save_current_background_name: "保存当前背景",
|
||||
|
||||
// ===== 通用按钮文本 =====
|
||||
button_cancel: "取消",
|
||||
|
|
@ -136,6 +142,7 @@ export default {
|
|||
button_test: "测试",
|
||||
button_update: "更新",
|
||||
button_add: "添加",
|
||||
button_save: "保存",
|
||||
|
||||
// ===== 默认配置相关 =====
|
||||
default_morning_rule: "清晨",
|
||||
|
|
@ -154,24 +161,29 @@ export default {
|
|||
dark_blue_gray_gradient_bg: "深蓝灰色渐变",
|
||||
|
||||
// ===== Notice 消息 =====
|
||||
notice_all_fields_required: "请提供所有必填字段",
|
||||
notice_name_and_value_required: "请提供名称和值",
|
||||
notice_valid_folder_path_required: "请提供有效的文件夹路径",
|
||||
notice_folder_not_found: "文件夹未找到",
|
||||
notice_folder_added_successfully: '成功从文件夹 "{folderPath}" 添加图片',
|
||||
notice_error_adding_folder_images: "添加文件夹图片时出错",
|
||||
notice_api_failed_enable_disable: "❌ 无法{action} {apiName}",
|
||||
notice_api_success_enable_disable: "✅ 成功{action} {apiName}",
|
||||
notice_api_error_enable_disable: "❌ {action} {apiName} 时出错",
|
||||
notice_api_disabled: "❌ {apiName}: API 已禁用",
|
||||
notice_api_fetching: "🔄 正在从 {apiName} 获取壁纸...",
|
||||
notice_api_success_applied: "✅ 成功应用来自 {apiName} 的壁纸",
|
||||
notice_api_failed_fetch: "❌ 从 {apiName} 获取壁纸失败",
|
||||
notice_api_error_fetch: "❌ 从 {apiName} 获取壁纸时出错:{error}",
|
||||
notice_api_fetching_generic: "🔄 正在从 API 获取壁纸...",
|
||||
notice_api_success_applied_generic: "✅ 成功应用随机壁纸!",
|
||||
notice_api_no_available: "❌ 没有可用的壁纸 API 或所有 API 都失败了",
|
||||
notice_api_error_generic: "❌ 从 API 获取壁纸时出错",
|
||||
notice_all_fields_required: "⚠️ 请提供所有必填字段",
|
||||
notice_name_and_value_required: "⚠️ 请提供名称和值",
|
||||
notice_valid_folder_path_required: "⚠️ 请提供有效的文件夹路径",
|
||||
notice_folder_not_found: "❌ 文件夹未找到",
|
||||
notice_folder_added_successfully: '🎉 成功从文件夹 "{folderPath}" 添加图片',
|
||||
notice_error_adding_folder_images: "❌ 添加文件夹图片时出错",
|
||||
notice_api_failed_enable_disable: "❌ DTB: 无法{action} {apiName}",
|
||||
notice_api_success_enable_disable: "🎉 DTB: 成功{action} {apiName}",
|
||||
notice_api_error_enable_disable: "❌ DTB: {action} {apiName} 时出错",
|
||||
notice_api_disabled: "❌ DTB: {apiName}: API 已禁用",
|
||||
notice_api_fetching: "🔄 DTB: 正在从 {apiName} 获取壁纸...",
|
||||
notice_api_success_applied: "🎉 DTB: 成功应用来自 {apiName} 的壁纸",
|
||||
notice_api_failed_fetch: "❌ DTB: 从 {apiName} 获取壁纸失败",
|
||||
notice_api_error_fetch: "❌ DTB: 从 {apiName} 获取壁纸时出错:{error}",
|
||||
notice_api_fetching_generic: "🔄 DTB: 正在从 API 获取壁纸...",
|
||||
notice_api_success_applied_generic: "🎉 DTB: 成功应用随机壁纸!",
|
||||
notice_api_no_available: "❌ DTB: 没有可用的壁纸 API 或所有 API 都失败了",
|
||||
notice_api_error_generic: "❌ DTB: 从 API 获取壁纸时出错",
|
||||
notice_save_background_no_need_save_local: "🎉 DTB: 当前背景是本地图片,无需保存",
|
||||
notice_save_background_valid_folder_path_required: "⚠️ 请提供有效的保存壁纸的文件夹路径",
|
||||
notice_save_background_only_image_supported: "⚠️ DTB: 仅支持保存图片作为壁纸",
|
||||
notice_save_background_success: "🎉 DTB: 当前背景已保存至 {folderPath}",
|
||||
notice_save_background_failed: "❌ DTB: 当前背景保存失败,请检查文件夹路径和权限",
|
||||
|
||||
// ===== API 模态窗口 =====
|
||||
api_modal_invalid_json: "额外参数中的 JSON 格式无效",
|
||||
|
|
@ -179,7 +191,7 @@ export default {
|
|||
api_modal_invalid_params: "无效的 API 参数:{errors}",
|
||||
api_modal_testing_config: "正在测试 API 配置...",
|
||||
api_modal_cannot_test_invalid: "由于配置无效无法测试",
|
||||
api_modal_test_successful: "API 测试成功!",
|
||||
api_modal_test_successful: "🎉 API 测试成功!",
|
||||
api_modal_test_failed: "API 测试失败:{error}",
|
||||
api_modal_api_url: "API 地址",
|
||||
api_modal_headers_optional: "请求头(可选)",
|
||||
|
|
|
|||
216
src/plugin.ts
216
src/plugin.ts
|
|
@ -1,10 +1,11 @@
|
|||
/**
|
||||
* 动态主题背景插件 - 主插件类
|
||||
*/
|
||||
import { Plugin } from "obsidian";
|
||||
import { Notice, Plugin, requestUrl } from "obsidian";
|
||||
|
||||
import { registerCommands } from "./commands";
|
||||
import { getDefaultSettings } from "./default-settings";
|
||||
import { t } from "./i18n";
|
||||
import { DTBSettingTab, DTBSettingsView, DTB_SETTINGS_VIEW_TYPE } from "./settings";
|
||||
import type { BackgroundItem, DTBSettings, TimeRule } from "./types";
|
||||
import { hexToRgba } from "./utils";
|
||||
|
|
@ -18,6 +19,8 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
|
|||
intervalId: number | null = null; // 用于间隔模式的定时器 ID
|
||||
timeoutId: number | null = null; // 用于时段规则的定时器 ID
|
||||
|
||||
statusBar: HTMLElement | null = null;
|
||||
|
||||
// ============================================================================
|
||||
// 主要接口方法
|
||||
// ============================================================================
|
||||
|
|
@ -25,6 +28,16 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
|
|||
async onload() {
|
||||
await this.loadSettings();
|
||||
|
||||
// 左侧栏图标
|
||||
this.addRibbonIcon("rainbow", "🌈 Obsidian DTB", async (evt: MouseEvent) => {
|
||||
await this.applyRandomWallpaper();
|
||||
});
|
||||
|
||||
// 状态栏
|
||||
if (this.settings.statusBarEnabled) {
|
||||
this.activateStatusBar();
|
||||
}
|
||||
|
||||
// 注册自定义视图类型
|
||||
this.registerView(DTB_SETTINGS_VIEW_TYPE, (leaf) => new DTBSettingsView(leaf, this));
|
||||
|
||||
|
|
@ -92,6 +105,38 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
|
|||
this.app.workspace.revealLeaf(leaf);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止状态栏
|
||||
*/
|
||||
deactivateStatusBar() {
|
||||
this.statusBar?.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活状态栏,左键点击切换随机壁纸,右键点击保存当前背景,中键打开设置标签页
|
||||
*/
|
||||
activateStatusBar() {
|
||||
this.deactivateStatusBar();
|
||||
this.statusBar = this.addStatusBarItem();
|
||||
this.statusBar.setText("🌈 DTB");
|
||||
this.statusBar.addClass("dtb-status-bar");
|
||||
this.statusBar.setAttribute("title", t("status_bar_title"));
|
||||
this.statusBar.addEventListener("click", async (evt) => {
|
||||
if (evt.button === 0) {
|
||||
await this.applyRandomWallpaper();
|
||||
}
|
||||
});
|
||||
this.statusBar.addEventListener("auxclick", async (evt) => {
|
||||
if (evt.button === 1) {
|
||||
await this.activateView();
|
||||
}
|
||||
});
|
||||
this.statusBar.addEventListener("contextmenu", async (evt) => {
|
||||
evt.preventDefault();
|
||||
await this.saveBackground();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止背景管理器
|
||||
*/
|
||||
|
|
@ -211,43 +256,22 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
|
|||
}
|
||||
// 基于时间间隔切换
|
||||
case "interval": {
|
||||
// 检查是否启用随机壁纸
|
||||
if (this.settings.enableRandomWallpaper) {
|
||||
const randomWallpaperUrl = await this.fetchRandomWallpaper();
|
||||
|
||||
if (randomWallpaperUrl) {
|
||||
// 创建一个临时的背景项用于随机壁纸
|
||||
this.background = {
|
||||
id: `random-wallpaper-${Date.now()}`,
|
||||
name: `Random Wallpaper`,
|
||||
type: "image",
|
||||
value: randomWallpaperUrl,
|
||||
};
|
||||
needsUpdate = true;
|
||||
|
||||
console.debug("DTB: Interval mode - using random wallpaper", randomWallpaperUrl);
|
||||
} else if (this.settings.backgrounds.length > 0) {
|
||||
// API失败时回退到本地背景
|
||||
this.settings.currentIndex =
|
||||
(this.settings.currentIndex + 1) % this.settings.backgrounds.length;
|
||||
this.background = this.settings.backgrounds[this.settings.currentIndex];
|
||||
this.saveSettings();
|
||||
needsUpdate = true;
|
||||
|
||||
console.debug("DTB: Interval mode - fallback to local background", this.background);
|
||||
}
|
||||
const randomWallpaperUrl = await this.fetchRandomWallpaper();
|
||||
if (randomWallpaperUrl) {
|
||||
// 创建一个临时的背景项用于随机壁纸
|
||||
this.background = {
|
||||
id: `random-wallpaper-${Date.now()}`,
|
||||
name: `Random Wallpaper`,
|
||||
type: "image",
|
||||
value: randomWallpaperUrl,
|
||||
};
|
||||
needsUpdate = true;
|
||||
} else if (this.settings.backgrounds.length > 0) {
|
||||
// 使用本地背景
|
||||
this.background = this.settings.backgrounds[this.settings.currentIndex];
|
||||
// API失败时回退到本地背景
|
||||
this.settings.currentIndex = (this.settings.currentIndex + 1) % this.settings.backgrounds.length;
|
||||
this.background = this.settings.backgrounds[this.settings.currentIndex];
|
||||
this.saveSettings();
|
||||
needsUpdate = true; // 每次间隔切换都需要更新背景
|
||||
|
||||
console.debug(
|
||||
"DTB: Interval mode - current index and background",
|
||||
this.settings.currentIndex,
|
||||
this.background
|
||||
);
|
||||
needsUpdate = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -277,9 +301,7 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
|
|||
});
|
||||
} else {
|
||||
const bgCssValue =
|
||||
this.background.type === "image"
|
||||
? this.sanitizeImagePath(this.background.value)
|
||||
: this.background.value;
|
||||
this.background.type === "image" ? this.getBgURL(this.background) : this.background.value;
|
||||
// 模糊度、亮度、饱和度、遮罩颜色和透明度、填充方式的优先级统一为:
|
||||
// 传入的自定义值 > 背景单独的设置 > 全局默认设置
|
||||
const blurDepth = this.background.blurDepth ?? this.settings.blurDepth;
|
||||
|
|
@ -312,6 +334,10 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
|
|||
this.app.workspace.trigger("css-change", { source: "dtb" });
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 辅助方法
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 根据图片和屏幕比例动态选择最佳的background-size
|
||||
* @param imagePath 图片路径
|
||||
|
|
@ -404,6 +430,82 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
async applyRandomWallpaper() {
|
||||
const randomWallpaperUrl = await this.fetchRandomWallpaper();
|
||||
|
||||
if (randomWallpaperUrl) {
|
||||
// 创建一个临时的背景项用于随机壁纸
|
||||
this.background = {
|
||||
id: `random-wallpaper-${Date.now()}`,
|
||||
name: `Random Wallpaper`,
|
||||
type: "image",
|
||||
value: randomWallpaperUrl,
|
||||
};
|
||||
} else if (this.settings.backgrounds.length > 0) {
|
||||
// API失败时回退到本地背景
|
||||
this.settings.currentIndex = (this.settings.currentIndex + 1) % this.settings.backgrounds.length;
|
||||
this.background = this.settings.backgrounds[this.settings.currentIndex];
|
||||
await this.saveSettings();
|
||||
}
|
||||
|
||||
this.updateStyleCss();
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存当前背景设置, 如果已经是本地图片则不操作
|
||||
*/
|
||||
async saveBackground(bg: BackgroundItem | null = this.background) {
|
||||
if (!bg) return;
|
||||
// 判断是否设置了 localBackgroundFolder
|
||||
if (!this.settings.localBackgroundFolder) {
|
||||
new Notice(t("notice_save_background_valid_folder_path_required"));
|
||||
return;
|
||||
}
|
||||
// 判断是否是图片,非图片则不保存
|
||||
if (bg.type !== "image") {
|
||||
new Notice(t("notice_save_background_only_image_supported"));
|
||||
return;
|
||||
}
|
||||
// 如果是本地图片,则不保存
|
||||
if (!this.isRemoteImage(bg.value)) {
|
||||
new Notice(t("notice_save_background_no_need_save_local"));
|
||||
return;
|
||||
}
|
||||
|
||||
const success = await this.saveRemoteImage(bg, this.settings.localBackgroundFolder);
|
||||
if (!success) {
|
||||
new Notice(t("notice_save_background_failed"));
|
||||
return;
|
||||
}
|
||||
new Notice(t("notice_save_background_success", { folderPath: this.settings.localBackgroundFolder }));
|
||||
}
|
||||
|
||||
async saveRemoteImage(bg: BackgroundItem, folderPath: string): Promise<boolean> {
|
||||
if (!folderPath) {
|
||||
new Notice(t("notice_save_background_valid_folder_path_required"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 默认图片名为 bg.name + .jpg , 并规范化路径 移除禁止的字符: \ / : * ? " < > |
|
||||
const imageName = bg.name.replace(/[\\\/:\*\?"<>\|]/g, "_") + ".jpg";
|
||||
const localPath = `${folderPath}/${imageName}`;
|
||||
|
||||
// 这里添加保存远程图片的逻辑
|
||||
const response = await requestUrl({ url: bg.value });
|
||||
if (response.status < 200 || response.status >= 300) {
|
||||
new Notice(t("notice_save_background_failed"), response.status);
|
||||
return false;
|
||||
}
|
||||
const arrayBuffer = response.arrayBuffer;
|
||||
await this.app.vault.createBinary(localPath, arrayBuffer);
|
||||
|
||||
// 默认将bg中的url替换为本地路径,并将remoteUrl设置为原始url以作备份
|
||||
bg.remoteUrl = bg.value;
|
||||
bg.value = localPath;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 从壁纸API获取随机图片URL
|
||||
async fetchRandomWallpaper(): Promise<string | null> {
|
||||
if (!this.settings.enableRandomWallpaper) {
|
||||
|
|
@ -443,28 +545,38 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 辅助方法
|
||||
// ============================================================================
|
||||
|
||||
// 将图片路径转换为可用的 CSS URL
|
||||
sanitizeImagePath(imagePath: string): string {
|
||||
getBgURL(bg: BackgroundItem): string {
|
||||
const imagePath = bg.value;
|
||||
// 判断是否是远程图片
|
||||
if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
|
||||
if (this.isRemoteImage(imagePath)) {
|
||||
return `url(${imagePath})`;
|
||||
}
|
||||
// 本地图片路径(只接受 Vault 内的图片)
|
||||
const file = this.app.vault.getFileByPath(imagePath);
|
||||
if (!file) {
|
||||
console.warn(`DTB: Image ${imagePath} not found`);
|
||||
return "none";
|
||||
if (file) {
|
||||
const p = this.app.vault.getResourcePath(file);
|
||||
if (p) {
|
||||
return `url(${p})`;
|
||||
}
|
||||
} else {
|
||||
console.warn(`DTB: Image ${imagePath} not found or inaccessible`);
|
||||
}
|
||||
const p = this.app.vault.getResourcePath(file);
|
||||
if (!p) {
|
||||
console.warn(`DTB: Cannot get resource path for image ${imagePath}`);
|
||||
return "none";
|
||||
|
||||
// 如果 value 表示的本地路径无效,则查看 bg 有没有 remoteUrl 备份链接
|
||||
if (bg.remoteUrl) {
|
||||
// 这里恢复备份, 按理在这做不太合适
|
||||
bg.value = bg.remoteUrl;
|
||||
this.saveSettings(); // 保存设置
|
||||
return `url(${bg.remoteUrl})`;
|
||||
}
|
||||
return `url(${p})`; // 形如 app://local/path/to/image.jpg
|
||||
|
||||
// 否则
|
||||
return "none";
|
||||
}
|
||||
|
||||
isRemoteImage(imagePath: string): boolean {
|
||||
return imagePath.startsWith("http://") || imagePath.startsWith("https://");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ export class DTBSettingTab extends PluginSettingTab {
|
|||
containerEl.empty();
|
||||
containerEl.createEl("h3", { text: t("basic_settings_title") });
|
||||
|
||||
// 基础设置
|
||||
// 是否启用插件
|
||||
new Setting(containerEl)
|
||||
.setName(t("enable_plugin_name"))
|
||||
.setDesc(t("enable_plugin_desc"))
|
||||
|
|
@ -126,6 +126,22 @@ export class DTBSettingTab extends PluginSettingTab {
|
|||
})
|
||||
);
|
||||
|
||||
// 是否开启状态栏
|
||||
new Setting(containerEl)
|
||||
.setName(t("enable_status_bar_name"))
|
||||
.setDesc(t("enable_status_bar_desc") + t("status_bar_title").replace(/\n/g, " "))
|
||||
.addToggle((toggle) =>
|
||||
toggle.setValue(this.plugin.settings.statusBarEnabled).onChange(async (value) => {
|
||||
this.plugin.settings.statusBarEnabled = value;
|
||||
await this.plugin.saveSettings();
|
||||
if (value) {
|
||||
this.plugin.activateStatusBar();
|
||||
} else {
|
||||
this.plugin.deactivateStatusBar();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// 外观设置
|
||||
containerEl.createEl("h4", { text: t("appearance_settings_title") });
|
||||
// 背景模糊度设置
|
||||
|
|
@ -539,9 +555,33 @@ export class DTBSettingTab extends PluginSettingTab {
|
|||
// 背景管理
|
||||
containerEl.createEl("h3", { text: t("bg_management_title") });
|
||||
|
||||
// 添加拖拽提示
|
||||
const dragHint = containerEl.createDiv("dtb-hint");
|
||||
dragHint.textContent = t("drag_hint_text");
|
||||
// 保存远程图片的本地路径
|
||||
const imageFolderInputContainer = containerEl.createDiv("setting-item dtb-flex-container-spaced");
|
||||
imageFolderInputContainer.createEl("label", { text: t("save_image_path_title") });
|
||||
const valueInput = imageFolderInputContainer.createEl("input", {
|
||||
type: "text",
|
||||
title: t("save_image_path_title"),
|
||||
placeholder: t("save_image_path_placeholder"),
|
||||
value: this.plugin.settings.localBackgroundFolder ?? "",
|
||||
cls: "dtb-flex-1",
|
||||
});
|
||||
valueInput.oninput = () => {
|
||||
this.plugin.settings.localBackgroundFolder = valueInput.value;
|
||||
this.plugin.saveSettings();
|
||||
};
|
||||
const browseButton = imageFolderInputContainer.createEl("button", {
|
||||
type: "button",
|
||||
text: t("button_browse"),
|
||||
cls: "dtb-button",
|
||||
});
|
||||
browseButton.onclick = () => {
|
||||
const modal = new ImageFolderSuggestModal(this.app, (imagePath: string) => {
|
||||
valueInput.value = imagePath;
|
||||
this.plugin.settings.localBackgroundFolder = imagePath;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
modal.open();
|
||||
};
|
||||
|
||||
// 添加背景的一组按钮
|
||||
const buttonContainer = containerEl.createDiv("dtb-large-button-container");
|
||||
|
|
@ -567,6 +607,10 @@ export class DTBSettingTab extends PluginSettingTab {
|
|||
.onClick(() => this.restoreDefaultBackgrounds())
|
||||
);
|
||||
|
||||
// 添加拖拽提示
|
||||
const dragHint = containerEl.createDiv("dtb-hint");
|
||||
dragHint.textContent = t("background_management_hint");
|
||||
|
||||
const backgroundContainer = containerEl.createDiv("dtb-section-container");
|
||||
this.displayBackgrounds(backgroundContainer);
|
||||
}
|
||||
|
|
@ -739,13 +783,14 @@ export class DTBSettingTab extends PluginSettingTab {
|
|||
contentDiv.createSpan({ text: bg.name, cls: "dtb-bg-name" });
|
||||
contentDiv.createSpan({ text: bg.type, cls: "dtb-badge" });
|
||||
|
||||
// 预览
|
||||
// 预览图
|
||||
const preview = contentDiv.createDiv("dtb-bg-preview");
|
||||
this.setPreviewBackground(preview, bg);
|
||||
|
||||
// 操作按钮
|
||||
const actions = contentDiv.createDiv("dtb-button-container");
|
||||
|
||||
// 预览按钮
|
||||
actions.createEl("button", { text: t("button_preview") }).onclick = () => {
|
||||
this.plugin.background = bg;
|
||||
this.plugin.settings.currentIndex = index; // 更新当前索引
|
||||
|
|
@ -753,10 +798,19 @@ export class DTBSettingTab extends PluginSettingTab {
|
|||
this.plugin.updateStyleCss();
|
||||
};
|
||||
|
||||
// 保存按钮
|
||||
actions.createEl("button", { text: t("button_save") }).onclick = async () => {
|
||||
await this.plugin.saveBackground(bg);
|
||||
// 由于保存远程图片时会将本地图片路径替换为远程路径,因此需要更新设置
|
||||
await this.plugin.saveSettings();
|
||||
};
|
||||
|
||||
// 编辑按钮
|
||||
actions.createEl("button", { text: t("button_edit") }).onclick = () => {
|
||||
this.showEditBackgroundModal(bg, index);
|
||||
};
|
||||
|
||||
// 删除按钮
|
||||
actions.createEl("button", { text: t("button_delete") }).onclick = async () => {
|
||||
// 使用 filter 方法删除
|
||||
this.plugin.settings.backgrounds = this.plugin.settings.backgrounds.filter(
|
||||
|
|
@ -786,7 +840,7 @@ export class DTBSettingTab extends PluginSettingTab {
|
|||
switch (bg.type) {
|
||||
case "image": {
|
||||
preview.addClass("dtb-preview-image");
|
||||
const sanitizedImagePath = this.plugin.sanitizeImagePath(bg.value);
|
||||
const sanitizedImagePath = this.plugin.getBgURL(bg);
|
||||
// 只有当图片路径有效时才设置 CSS 变量
|
||||
if (sanitizedImagePath && sanitizedImagePath !== "none") {
|
||||
preview.setCssProps({
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import type { WallpaperApiConfig } from "./wallpaper-apis";
|
|||
|
||||
export interface DTBSettings {
|
||||
enabled: boolean;
|
||||
statusBarEnabled: boolean; // 是否激活状态栏
|
||||
|
||||
// 全局背景模糊度、亮度和饱和度变量、背景颜色
|
||||
blurDepth: number; // 背景模糊度
|
||||
|
|
@ -22,6 +23,7 @@ export interface DTBSettings {
|
|||
intervalMinutes: number;
|
||||
|
||||
// 背景管理
|
||||
localBackgroundFolder: string; // 保存远程背景图片的文件夹路径
|
||||
backgrounds: BackgroundItem[];
|
||||
currentIndex: number; // 当前背景索引
|
||||
|
||||
|
|
@ -44,7 +46,7 @@ export interface BackgroundItem {
|
|||
name: string;
|
||||
type: "image" | "color" | "gradient";
|
||||
value: string; // image URL, color code, or gradient CSS
|
||||
preview?: string;
|
||||
remoteUrl?: string; // 作为备份,防止一些远端保存到本地的图片删除后找不回来,读取图片优先从value读取,如果读取不到再从远端读取,此种情况会将 remoteUrl 变更为 value
|
||||
|
||||
// 每个背景单独的模糊度、亮度和饱和度变量、遮罩颜色和透明度、填充方式,可覆盖全局设置
|
||||
blurDepth?: number;
|
||||
|
|
|
|||
62
styles.css
62
styles.css
|
|
@ -1041,3 +1041,65 @@
|
|||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
/* ===== 炫酷状态栏图标样式 ===== */
|
||||
.dtb-status-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
padding: 0.2em 1em 0.2em 0.8em;
|
||||
border-radius: 1.2em;
|
||||
font-weight: bold;
|
||||
font-size: 1em;
|
||||
background: var(--status-bar-background, rgba(40, 44, 52, 0.85));
|
||||
color: var(--status-bar-text-color, var(--text-normal));
|
||||
box-shadow: 0 1px 6px 0 rgba(80, 180, 255, 0.1);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition:
|
||||
box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
background 0.3s;
|
||||
}
|
||||
.dtb-status-bar:hover {
|
||||
box-shadow:
|
||||
0 2px 12px 0 rgba(80, 180, 255, 0.18),
|
||||
0 0 8px 2px #91eac9;
|
||||
background: linear-gradient(90deg, var(--status-bar-background, rgba(40, 44, 52, 0.92)) 60%, #91eac9 100%);
|
||||
}
|
||||
.dtb-status-bar .dtb-status-icon {
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
margin-right: 0.3em;
|
||||
filter: drop-shadow(0 0 2px #91eac9);
|
||||
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.dtb-status-bar:hover .dtb-status-icon {
|
||||
transform: rotate(-12deg) scale(1.18);
|
||||
}
|
||||
.dtb-status-bar .dtb-status-text {
|
||||
letter-spacing: 0.04em;
|
||||
text-shadow: 0 1px 2px #0002;
|
||||
font-size: 1em;
|
||||
}
|
||||
.dtb-status-bar .dtb-status-dot {
|
||||
width: 0.7em;
|
||||
height: 0.7em;
|
||||
border-radius: 50%;
|
||||
margin-left: 0.5em;
|
||||
background: radial-gradient(circle, #91eac9 60%, var(--status-bar-background, #7f7fd5) 100%);
|
||||
box-shadow: 0 0 4px 1px #91eac9;
|
||||
animation: dtb-dot-pulse 1.2s infinite alternate;
|
||||
}
|
||||
@keyframes dtb-dot-pulse {
|
||||
0% {
|
||||
box-shadow:
|
||||
0 0 8px 2px #91eac9,
|
||||
0 0 2px 1px #fff8;
|
||||
}
|
||||
100% {
|
||||
box-shadow:
|
||||
0 0 16px 4px #91eac9,
|
||||
0 0 4px 2px #fff8;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue