fix: resolve all Required issues from official plugin review (PR #7359)

This commit is contained in:
sean2077 2025-12-05 13:36:47 +08:00
parent 2ed4e7ebd0
commit fd83d70519
No known key found for this signature in database
GPG key ID: 620E0A47DDC73C4E
21 changed files with 310 additions and 133 deletions

48
.gitignore vendored
View file

@ -1,22 +1,26 @@
# vscode
.vscode
# Intellij
*.iml
.idea
# npm
node_modules
# Don't include the compiled main.js file in the repo.
# They should be uploaded to GitHub releases instead.
main.js
# Exclude sourcemaps
*.map
# obsidian
data.json
# Exclude macOS Finder (System Explorer) View States
.DS_Store
# AI tools
.serena
.claude
# vscode
.vscode
# Intellij
*.iml
.idea
# npm
node_modules
# Don't include the compiled main.js file in the repo.
# They should be uploaded to GitHub releases instead.
main.js
# Exclude sourcemaps
*.map
# obsidian
data.json
# Exclude macOS Finder (System Explorer) View States
.DS_Store

97
.internal/issues.md Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,8 +1,12 @@
// eslint.config.js
import obsidianmd from "eslint-plugin-obsidianmd";
import tsParser from "@typescript-eslint/parser";
import tseslint from "typescript-eslint";
import obsidianmd from "eslint-plugin-obsidianmd";
export default [
// TypeScript-ESLint 推荐规则(不含严格类型检查)
...tseslint.configs.recommended,
{
files: ["**/*.ts"],
languageOptions: {
@ -15,11 +19,21 @@ export default [
obsidianmd,
},
rules: {
// The recommended rules from eslint-plugin-obsidianmd
// 使用 obsidianmd 官方推荐规则
...obsidianmd.configs.recommended,
// Override: 降低 UI sentence case 的严格程度,因为表情符号会导致误报
// 官方审查要求的关键规则
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/require-await": "error",
"@typescript-eslint/no-misused-promises": "error",
// 项目特定覆盖
"obsidianmd/ui/sentence-case": ["warn", { enforceCamelCaseLower: false }],
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
},
},
];

32
package-lock.json generated
View file

@ -12,23 +12,23 @@
"jsonpath-plus": "^10.3.0"
},
"devDependencies": {
"@types/node": "*",
"@typescript-eslint/eslint-plugin": "*",
"@typescript-eslint/parser": "*",
"all-contributors-cli": "*",
"builtin-modules": "*",
"esbuild": "*",
"eslint": "*",
"eslint-plugin-obsidianmd": "*",
"obsidian": "*",
"prettier": "*",
"@types/node": "latest",
"@typescript-eslint/eslint-plugin": "latest",
"@typescript-eslint/parser": "latest",
"all-contributors-cli": "^6.26.1",
"builtin-modules": "latest",
"esbuild": "latest",
"eslint": "latest",
"eslint-plugin-obsidianmd": "latest",
"obsidian": "latest",
"prettier": "latest",
"stylelint": "latest",
"stylelint-config-idiomatic-order": "*",
"stylelint-config-recommended": "*",
"stylelint-config-standard": "*",
"stylelint-order": "*",
"tslib": "*",
"typescript": "*"
"stylelint-config-idiomatic-order": "latest",
"stylelint-config-recommended": "latest",
"stylelint-config-standard": "latest",
"stylelint-order": "latest",
"tslib": "latest",
"typescript": "latest"
}
},
"node_modules/@babel/code-frame": {

View file

@ -20,7 +20,7 @@
"@types/node": "latest",
"@typescript-eslint/eslint-plugin": "latest",
"@typescript-eslint/parser": "latest",
"all-contributors-cli": "latest",
"all-contributors-cli": "^6.26.1",
"builtin-modules": "latest",
"esbuild": "latest",
"eslint": "latest",
@ -38,4 +38,4 @@
"dependencies": {
"jsonpath-plus": "^10.3.0"
}
}
}

View file

@ -1,9 +1,9 @@
export default {
// ===== 设置标题 =====
settings_title: "🌈 Dynamic Theme Background",
version: "🛠️ Version: ",
author: "🎨 Author: ",
homepage: "🏠 Homepage: ",
settings_title: "Dynamic Theme Background",
version: "Version: ",
author: "Author: ",
homepage: "Homepage: ",
// ===== 基础设置 =====
enable_plugin_name: "Enable dynamic background",

View file

@ -1,9 +1,9 @@
export default {
// ===== 设置标题 =====
settings_title: "🌈 动态主题背景",
version: "🛠️ 版本: ",
author: "🎨 作者: ",
homepage: "🏠 首页: ",
settings_title: "Dynamic Theme Background",
version: "Version: ",
author: "Author: ",
homepage: "Homepage: ",
// ===== 基础设置 =====
enable_plugin_name: "启用动态背景",

View file

@ -178,7 +178,7 @@ export class BackgroundModal extends Modal {
.onClick(() => {
// 清空每背景覆盖,让其回退到全局
this.blurDepth = undefined;
this.bgItem.blurDepth = undefined as any;
this.bgItem.blurDepth = undefined;
this.displayAppearanceSettings(containerEl); // 重新渲染设置
})
);
@ -202,7 +202,7 @@ export class BackgroundModal extends Modal {
.onClick(() => {
// 清空每背景覆盖,让其回退到全局
this.brightness4Bg = undefined;
this.bgItem.brightness4Bg = undefined as any;
this.bgItem.brightness4Bg = undefined;
this.displayAppearanceSettings(containerEl); // 重新渲染设置
})
);
@ -226,7 +226,7 @@ export class BackgroundModal extends Modal {
.onClick(() => {
// 清空每背景覆盖,让其回退到全局
this.saturate4Bg = undefined;
this.bgItem.saturate4Bg = undefined as any;
this.bgItem.saturate4Bg = undefined;
this.displayAppearanceSettings(containerEl); // 重新渲染设置
})
);
@ -284,10 +284,10 @@ export class BackgroundModal extends Modal {
this.bgColorOpacityDark = undefined;
this.bgColorLight = undefined;
this.bgColorOpacityLight = undefined;
this.bgItem.bgColorDark = undefined as any;
this.bgItem.bgColorOpacityDark = undefined as any;
this.bgItem.bgColorLight = undefined as any;
this.bgItem.bgColorOpacityLight = undefined as any;
this.bgItem.bgColorDark = undefined;
this.bgItem.bgColorOpacityDark = undefined;
this.bgItem.bgColorLight = undefined;
this.bgItem.bgColorOpacityLight = undefined;
this.displayAppearanceSettings(containerEl);
})
);
@ -298,10 +298,10 @@ export class BackgroundModal extends Modal {
.setDesc(t("bg_size_desc"))
.addDropdown((dropdown) => {
// 添加下拉选项
dropdown.addOption("intelligent", "intelligent");
dropdown.addOption("cover", "cover");
dropdown.addOption("contain", "contain");
dropdown.addOption("auto", "auto");
dropdown.addOption("intelligent", "Intelligent");
dropdown.addOption("cover", "Cover");
dropdown.addOption("contain", "Contain");
dropdown.addOption("auto", "Auto");
// 使用专门的悬停选项方法添加 tooltip推荐用法
addDropdownOptionHoverTooltip(
dropdown,
@ -331,7 +331,7 @@ export class BackgroundModal extends Modal {
.onClick(() => {
// 清空每背景覆盖,让其回退到全局
this.bgSize = undefined;
this.bgItem.bgSize = undefined as any;
this.bgItem.bgSize = undefined;
this.displayAppearanceSettings(containerEl); // 重新渲染设置
})
);

View file

@ -26,7 +26,7 @@ export class ImageFolderSuggestModal extends SuggestModal<string> {
el.createEl("div", { text: folderPath });
}
onChooseSuggestion(folderPath: string, evt: MouseEvent | KeyboardEvent) {
onChooseSuggestion(folderPath: string, _evt: MouseEvent | KeyboardEvent) {
this.onSubmit(folderPath);
}
}

View file

@ -34,7 +34,7 @@ export class ImagePathSuggestModal extends SuggestModal<string> {
text.textContent = imagePath;
}
onChooseSuggestion(imagePath: string, evt: MouseEvent | KeyboardEvent) {
onChooseSuggestion(imagePath: string, _evt: MouseEvent | KeyboardEvent) {
this.onSubmit(imagePath);
}
}

View file

@ -606,7 +606,7 @@ export class WallpaperApiEditorModal extends Modal {
try {
const extraParams = JSON.parse(this.extraParamsTextarea.value);
Object.assign(params, extraParams);
} catch (error) {
} catch {
new Notice(t("api_modal_invalid_json"));
}
}
@ -657,9 +657,7 @@ export class WallpaperApiEditorModal extends Modal {
value = selectEl.value || undefined;
} else if (input.classList.contains("dtb-multiselect")) {
// 多选
const checkboxes = input.querySelectorAll(
'input[type="checkbox"]:checked'
) as NodeListOf<HTMLInputElement>;
const checkboxes = input.querySelectorAll<HTMLInputElement>('input[type="checkbox"]:checked');
const selectedValues = Array.from(checkboxes).map((cb) => cb.value);
value = selectedValues.length > 0 ? selectedValues : undefined;
}

View file

@ -61,7 +61,7 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
// Wallpaper API 管理器
// 实例化所有已配置的API
for (const apiConfig of this.settings.wallpaperApis) {
apiManager.createApi(apiConfig);
void apiManager.createApi(apiConfig);
}
console.debug("Dynamic Theme Background plugin loaded");
@ -89,13 +89,13 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
/**
*
*/
async activateView() {
activateView(): void {
// 检查是否已经存在该类型的 leaf
const existingLeaf = this.app.workspace.getLeavesOfType(DTB_SETTINGS_VIEW_TYPE)[0];
if (existingLeaf) {
// 如果已存在,则聚焦它
this.app.workspace.revealLeaf(existingLeaf);
void this.app.workspace.revealLeaf(existingLeaf);
} else {
// 如果不存在,则创建新的 leaf
const leaf = this.app.workspace.getLeaf("tab");
@ -105,7 +105,7 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
});
// 确保标签页获得焦点
this.app.workspace.revealLeaf(leaf);
void this.app.workspace.revealLeaf(leaf);
}
}
@ -122,7 +122,7 @@ export default class DynamicThemeBackgroundPlugin extends Plugin {
activateStatusBar() {
this.deactivateStatusBar();
this.statusBar = this.addStatusBarItem();
this.statusBar.setText("🌈 DTB");
this.statusBar.setText("🌈 DTB"); // eslint-disable-line obsidianmd/ui/sentence-case -- acronym
this.statusBar.addClass("dtb-status-bar");
this.statusBar.setAttribute("title", t("status_bar_title"));
this.statusBar.addEventListener("click", (evt) => {

View file

@ -102,8 +102,8 @@ export class DTBSettingTab extends PluginSettingTab {
private displayHeader(containerEl: HTMLElement) {
const headerContainer = containerEl.createDiv("dtb-section-header");
// 创建左侧标题容器
const titleContainer = headerContainer.createDiv();
// 创建左侧标题容器(预留位置)
headerContainer.createDiv();
// 移除顶级标题按照Obsidian指南
// 创建右侧信息容器
@ -349,10 +349,10 @@ export class DTBSettingTab extends PluginSettingTab {
.setDesc(t("bg_size_desc"))
.addDropdown((dropdown) => {
// 添加下拉选项
dropdown.addOption("intelligent", "intelligent");
dropdown.addOption("cover", "cover");
dropdown.addOption("contain", "contain");
dropdown.addOption("auto", "auto");
dropdown.addOption("intelligent", "Intelligent");
dropdown.addOption("cover", "Cover");
dropdown.addOption("contain", "Contain");
dropdown.addOption("auto", "Auto");
// 使用专门的悬停选项方法添加 tooltip推荐用法
addDropdownOptionHoverTooltip(
dropdown,
@ -612,7 +612,7 @@ export class DTBSettingTab extends PluginSettingTab {
enabled: true,
};
const modal = new TimeRuleModal(this.app, editRule, async (updatedRule) => {
const modal = new TimeRuleModal(this.app, editRule, (updatedRule) => {
if (!updatedRule.name.trim() || !updatedRule.startTime || !updatedRule.endTime) {
new Notice(t("notice_all_fields_required"));
return;
@ -643,7 +643,7 @@ export class DTBSettingTab extends PluginSettingTab {
}
this.plugin.startBackgroundManager(); // 重新启动背景管理器以应用更改
await this.plugin.saveSettings();
void this.plugin.saveSettings();
// 这里仅需刷新时间规则列表
this.plugin.refreshActiveTimeRules();
});
@ -731,7 +731,7 @@ export class DTBSettingTab extends PluginSettingTab {
type,
value: "",
};
const modal = new BackgroundModal(this.app, this.plugin, bg, async (newBg: BackgroundItem) => {
const modal = new BackgroundModal(this.app, this.plugin, bg, (newBg: BackgroundItem) => {
if (!newBg.name.trim() || !newBg.value.trim()) {
new Notice(t("notice_name_and_value_required"));
return;
@ -744,7 +744,7 @@ export class DTBSettingTab extends PluginSettingTab {
// 添加到设置中
this.plugin.settings.backgrounds.push(newBg);
await this.plugin.saveSettings();
void this.plugin.saveSettings();
// 这里仅需刷新背景列表和时间规则列表
this.displayBackgrounds();
@ -756,7 +756,7 @@ export class DTBSettingTab extends PluginSettingTab {
// 显示编辑背景的模态窗口
private showEditBackgroundModal(bg: BackgroundItem, index: number): void {
const modal = new BackgroundModal(this.app, this.plugin, bg, async (newBg: BackgroundItem) => {
const modal = new BackgroundModal(this.app, this.plugin, bg, (newBg: BackgroundItem) => {
if (!newBg.name.trim() || !newBg.value.trim()) {
new Notice(t("notice_name_and_value_required"));
return;
@ -767,7 +767,7 @@ export class DTBSettingTab extends PluginSettingTab {
// 更新现有背景项
this.plugin.settings.backgrounds[index] = newBg;
await this.plugin.saveSettings();
void this.plugin.saveSettings();
// 如果当前正在使用这个背景,则更新显示
if (this.plugin.background?.id === bg.id) {
@ -792,8 +792,8 @@ export class DTBSettingTab extends PluginSettingTab {
}, 0);
}
private showAddFolderModal() {
const modal = new ImageFolderSuggestModal(this.app, async (folderPath: string) => {
private showAddFolderModal(): void {
const modal = new ImageFolderSuggestModal(this.app, (folderPath: string) => {
if (!folderPath.trim()) {
new Notice(t("notice_valid_folder_path_required"));
return;
@ -806,14 +806,15 @@ export class DTBSettingTab extends PluginSettingTab {
return;
}
try {
// 处理文件夹中的图片文件
await this.addImagesFromFolder(folderPath);
new Notice(t("notice_folder_added_successfully", { folderPath }));
} catch (error) {
console.error("Error adding images from folder:", error);
new Notice(t("notice_error_adding_folder_images"));
}
// 处理文件夹中的图片文件
this.addImagesFromFolder(folderPath)
.then(() => {
new Notice(t("notice_folder_added_successfully", { folderPath }));
})
.catch((error) => {
console.error("Error adding images from folder:", error);
new Notice(t("notice_error_adding_folder_images"));
});
});
modal.open();
@ -916,7 +917,7 @@ export class DTBSettingTab extends PluginSettingTab {
actions.createEl("button", { text: t("button_preview") }).onclick = () => {
this.plugin.background = bg;
this.plugin.settings.currentIndex = index; // 更新当前索引
this.plugin.saveSettings();
void this.plugin.saveSettings();
this.plugin.updateStyleCss();
this.displayBackgrounds(); // 刷新激活图标
};
@ -983,7 +984,7 @@ export class DTBSettingTab extends PluginSettingTab {
break;
}
default:
console.warn(`DTB: Unknown background type: ${bg.type}`);
console.warn(`DTB: Unknown background type: ${bg.type as string}`);
break;
}
}
@ -1108,7 +1109,7 @@ export class DTBSettingTab extends PluginSettingTab {
if (!existingApi) {
// 如果不存在,则添加并创建 API 实例
this.plugin.settings.wallpaperApis.push(apiConfig);
apiManager.createApi(apiConfig);
void apiManager.createApi(apiConfig);
}
}
new Notice(t("restore_default_apis_success"));
@ -1317,7 +1318,7 @@ export class DTBSettingTab extends PluginSettingTab {
const modal = new WallpaperApiEditorModal(this.app, emptyConfig, (apiConfig) => {
// 创建新的API实例
apiManager.createApi(apiConfig);
void apiManager.createApi(apiConfig);
// 添加到插件设置中
this.plugin.settings.wallpaperApis.push(apiConfig);
void this.plugin.saveSettings();
@ -1332,7 +1333,7 @@ export class DTBSettingTab extends PluginSettingTab {
private showEditWallpaperApiModal(apiConfig: WallpaperApiConfig, index: number) {
const modal = new WallpaperApiEditorModal(this.app, apiConfig, (updatedConfig) => {
// 有可能api类型也修改了干脆重新创建API实例覆盖原来的
apiManager.createApi(updatedConfig);
void apiManager.createApi(updatedConfig);
this.plugin.settings.wallpaperApis[index] = updatedConfig;
void this.plugin.saveSettings();

View file

@ -157,7 +157,7 @@ export class DragSort<T> {
}
};
const dropHandler = async (e: DragEvent) => {
const dropHandler = (e: DragEvent) => {
e.preventDefault();
const draggedId = e.dataTransfer?.getData("text/plain");
@ -172,7 +172,7 @@ export class DragSort<T> {
const midpoint = rect.top + rect.height / 2;
const insertAfter = e.clientY >= midpoint;
await this.reorderItems(draggedId, targetId, insertAfter);
void this.reorderItems(draggedId, targetId, insertAfter);
// 清理样式
element.classList.remove("dtb-drag-over-top", "dtb-drag-over-bottom");

View file

@ -105,7 +105,7 @@ export abstract class BaseWallpaperApi {
return [];
}
static validateParams(params: WallpaperApiParams): { valid: boolean; errors?: string[] } {
static validateParams(_params: WallpaperApiParams): { valid: boolean; errors?: string[] } {
return { valid: true };
}

View file

@ -69,7 +69,7 @@ export class CustomApi extends BaseWallpaperApi {
// 参数验证
// ============================================================================
validateParams(params: WallpaperApiParams): boolean {
validateParams(_params: WallpaperApiParams): boolean {
if (!this.baseUrl) {
console.warn("Custom API: baseUrl is required");
return false;

View file

@ -228,7 +228,7 @@ export class PexelsApi extends BaseWallpaperApi {
// 更新分页信息
this.totalPages = response.total_results ? Math.ceil(response.total_results / this.perPage) : -1;
this.totalCount = response.total_results ?? -1;
this.perPage = Number(this.params.per_page) ?? 15;
this.perPage = Number(this.params.per_page) || 15;
new Notice(
t("api_initialized_notice", {
@ -387,18 +387,32 @@ export class PexelsApi extends BaseWallpaperApi {
return response.json;
}
// 安全地将未知值转换为字符串,避免对象被转换为 [object Object]
private safeString(value: unknown): string {
if (value === null || value === undefined) {
return "";
}
if (typeof value === "string") {
return value;
}
if (typeof value === "number" || typeof value === "boolean") {
return String(value);
}
return "";
}
// 辅助方法:转换 API 返回的图片数据为 WallpaperImage
private transformPhoto(photo: Record<string, unknown>): WallpaperImage {
const src = (photo.src as Record<string, unknown>) ?? {};
return {
id: String(photo.id || ""),
url: String(src.large || src.original || src.large2x || ""),
id: this.safeString(photo.id),
url: this.safeString(src.large) || this.safeString(src.original) || this.safeString(src.large2x),
width: Number(photo.width) || undefined,
height: Number(photo.height) || undefined,
author: String(photo.photographer || ""),
description: String(photo.alt || ""),
downloadUrl: String(src.original || src.large2x || src.large || ""),
author: this.safeString(photo.photographer),
description: this.safeString(photo.alt),
downloadUrl: this.safeString(src.original) || this.safeString(src.large2x) || this.safeString(src.large),
};
}
}

View file

@ -310,7 +310,7 @@ export class PixabayApi extends BaseWallpaperApi {
// 更新分页信息
this.totalPages = response.totalHits ? Math.ceil(response.totalHits / this.perPage) : -1;
this.totalCount = response.total ?? -1;
this.perPage = Number(this.params.per_page) ?? 20;
this.perPage = Number(this.params.per_page) || 20;
new Notice(
t("api_initialized_notice", {
@ -439,19 +439,38 @@ export class PixabayApi extends BaseWallpaperApi {
return response.json;
}
// 安全地将未知值转换为字符串,避免对象被转换为 [object Object]
private safeString(value: unknown): string {
if (value === null || value === undefined) {
return "";
}
if (typeof value === "string") {
return value;
}
if (typeof value === "number" || typeof value === "boolean") {
return String(value);
}
return "";
}
// 辅助方法:转换 API 返回的图片数据为 WallpaperImage
private transformImage(image: Record<string, unknown>): WallpaperImage {
const tagsStr = this.safeString(image.tags);
return {
id: String(image.id ?? ""),
url: String(image.largeImageURL || image.fullHDURL || image.webformatURL || ""),
id: this.safeString(image.id),
url:
this.safeString(image.largeImageURL) ||
this.safeString(image.fullHDURL) ||
this.safeString(image.webformatURL),
width: Number(image.imageWidth) || Number(image.webformatWidth) || undefined,
height: Number(image.imageHeight) || Number(image.webformatHeight) || undefined,
author: String(image.user || ""),
description: String(image.tags || ""),
tags: String(image.tags || "")
.split(", ")
.filter((tag) => tag.trim()),
downloadUrl: String(image.imageURL || image.largeImageURL || image.fullHDURL || ""),
author: this.safeString(image.user),
description: tagsStr,
tags: tagsStr.split(", ").filter((tag) => tag.trim()),
downloadUrl:
this.safeString(image.imageURL) ||
this.safeString(image.largeImageURL) ||
this.safeString(image.fullHDURL),
};
}
}

View file

@ -53,7 +53,7 @@ interface Qihoo360WallpaperResponse {
img_800_600?: string;
img_640_480?: string;
// 支持更多分辨率字段
[key: string]: any;
[key: string]: string | undefined;
}>;
}
@ -457,7 +457,7 @@ export class Qihoo360Api extends BaseWallpaperApi {
/**
* API响应为WallpaperImage格式
*/
private convertToWallpaperImage(item: any, index: number): WallpaperImage {
private convertToWallpaperImage(item: Qihoo360WallpaperResponse["data"][number], index: number): WallpaperImage {
// 获取首选分辨率设置
const preferredResolution = this.params.preferredResolution || "auto";
let imageUrl = item.url;

View file

@ -231,7 +231,7 @@ export class UnsplashApi extends BaseWallpaperApi {
})
);
this.perPage = Number(this.params.per_page) ?? 10;
this.perPage = Number(this.params.per_page) || 10;
// 初始化数据缓存
this.wallpaperImageCache = [];
@ -389,19 +389,33 @@ export class UnsplashApi extends BaseWallpaperApi {
return response.json;
}
// 安全地将未知值转换为字符串,避免对象被转换为 [object Object]
private safeString(value: unknown): string {
if (value === null || value === undefined) {
return "";
}
if (typeof value === "string") {
return value;
}
if (typeof value === "number" || typeof value === "boolean") {
return String(value);
}
return "";
}
// 辅助方法:转换 API 返回的图片数据为 WallpaperImage
private transformPhoto(photo: Record<string, unknown>): WallpaperImage {
const user = (photo.user as Record<string, unknown>) ?? {};
const urls = (photo.urls as Record<string, unknown>) ?? {};
return {
id: String(photo.id ?? ""),
url: String(urls.regular || urls.full || urls.raw || ""),
id: this.safeString(photo.id),
url: this.safeString(urls.regular) || this.safeString(urls.full) || this.safeString(urls.raw),
width: Number(photo.width) || undefined,
height: Number(photo.height) || undefined,
author: String(user.name || user.username || ""),
description: String(photo.description || photo.alt_description || ""),
downloadUrl: String(urls.full || urls.raw || ""),
author: this.safeString(user.name) || this.safeString(user.username),
description: this.safeString(photo.description) || this.safeString(photo.alt_description),
downloadUrl: this.safeString(urls.full) || this.safeString(urls.raw),
};
}
}

View file

@ -117,12 +117,12 @@ export class WallhavenApi extends BaseWallpaperApi {
{ value: "nsfw", label: "NSFW (18+)" },
],
toApiValue: (uiValue: string[]) => {
const arr = Array.isArray(uiValue) ? (uiValue as string[]) : [];
const arr = Array.isArray(uiValue) ? uiValue : [];
let result = "";
result += arr.includes("sfw") ? "1" : "0";
result += arr.includes("sketchy") ? "1" : "0";
result += arr.includes("nsfw") ? "1" : "0";
return result ?? (defaultParams.purity as string);
return result || (defaultParams.purity as string);
},
fromApiValue: (apiValue: string) => {
const str = apiValue?.toString() ?? (defaultParams.purity as string);
@ -381,11 +381,27 @@ export class WallhavenApi extends BaseWallpaperApi {
console.debug(`Fetching Wallhaven search results from: ${url}`);
const response = await requestUrl({ url });
return response.json;
} // 辅助方法:转换 API 返回的图片数据为 WallpaperImage
}
// 安全地将未知值转换为字符串,避免对象被转换为 [object Object]
private safeString(value: unknown): string {
if (value === null || value === undefined) {
return "";
}
if (typeof value === "string") {
return value;
}
if (typeof value === "number" || typeof value === "boolean") {
return String(value);
}
return "";
}
// 辅助方法:转换 API 返回的图片数据为 WallpaperImage
private transformImage(apiImage: Record<string, unknown>): WallpaperImage {
return {
id: String(apiImage.id ?? ""),
url: String(apiImage.path ?? ""),
id: this.safeString(apiImage.id),
url: this.safeString(apiImage.path),
width: Number(apiImage.dimension_x) || undefined,
height: Number(apiImage.dimension_y) || undefined,
};