feat(themes): improve workshop filtering and fork controls

Add a compact used-tag filter, preserve workshop ownership across theme
reloads, and let authors disable forking for their themes.
This commit is contained in:
HorizonCode committed 2026-11-03 16:06:11 +01:00
1 parent ebc5fbf9c4
commit 3ef59f94ee
6 files changed
+349 -50

No files matched your search

+31
View File
@@ -44,6 +44,7 @@ export interface CommunityTheme {
downloadCount: number;
likeCount: number;
tags: string[];
allowForking: boolean;
createdAt: string;
updatedAt: string;
author: CommunityThemeAuthor;
@@ -74,6 +75,11 @@ export interface CommunityThemesResponse {
canModerate: boolean;
}
export interface CommunityTagSummary {
tag: string;
count: number;
}
export type ThemeReportStatus = 'open' | 'resolved' | 'dismissed';
export type ThemeReportCategory =
| 'spam'
@@ -224,6 +230,29 @@ export async function fetchCommunityThemes(options?: {
};
}
export async function fetchCommunityTags(): Promise<CommunityTagSummary[]> {
const baseUrl = await getThemesServiceUrl();
const res = await fetch(`${baseUrl}/v1/themes/tags`);
if (!res.ok) {
const errorJson = (await res.json().catch(() => ({}))) as { error?: string };
throw new Error(errorJson.error || `Failed to load tags (HTTP ${res.status})`);
}
const data = (await res.json()) as { tags?: unknown };
if (!Array.isArray(data.tags)) return [];
const tags: CommunityTagSummary[] = [];
for (const item of data.tags) {
if (!item || typeof item !== 'object') continue;
const candidate = item as { tag?: unknown; count?: unknown };
if (typeof candidate.tag !== 'string' || typeof candidate.count !== 'number') continue;
const tag = candidate.tag.trim().toLowerCase();
if (!tag) continue;
tags.push({ tag, count: candidate.count });
}
return tags;
}
export async function fetchCommunityThemeDetails(themeId: string): Promise<CommunityTheme> {
const cleanId = themeId.trim().toLowerCase();
const baseUrl = await getThemesServiceUrl();
@@ -656,6 +685,7 @@ export async function publishThemeToWorkshop(options: {
version?: string;
apiVersion?: string;
tags?: string[];
allowForking?: boolean;
previewImageBase64?: string;
onProgress?: (status: string, percentage: number) => void;
}): Promise<{ success: boolean; themeId: string; theme: unknown }> {
@@ -717,6 +747,7 @@ export async function publishThemeToWorkshop(options: {
totalChunks,
sha256,
tags: options.tags || [],
allowForking: options.allowForking,
}),
});