From 93536af6a69e6cc05531ad36fcb4f9746fc19bf2 Mon Sep 17 00:00:00 2001 From: HorizonCode Date: Tue, 3 Nov 2026 16:21:23 +0100 Subject: [PATCH] chore(lint): resolve launcher lint issues Format files and fix unused code, reactive collection usage, redundant mustaches, and missing each-block keys. --- src/lib/communityThemes.ts | 16 +- .../notifications/NotificationHub.svelte | 316 +- .../theme/CommunityWorkshopView.svelte | 2588 +++++++++-------- .../components/theme/ThemeEditorWindow.svelte | 20 +- .../components/theme/ThemeReportDialog.svelte | 30 +- src/lib/components/ui/dialog/dialog.svelte | 6 +- src/lib/themeMedia.ts | 2 +- src/lib/themes.ts | 27 +- src/lib/utils.ts | 4 +- src/screens/Launch.svelte | 614 ++-- 10 files changed, 1860 insertions(+), 1763 deletions(-) diff --git a/src/lib/communityThemes.ts b/src/lib/communityThemes.ts index 66fbb07..76e4791 100644 --- a/src/lib/communityThemes.ts +++ b/src/lib/communityThemes.ts @@ -1,7 +1,3 @@ -import { invoke } from '@tauri-apps/api/core'; -import { listen } from '@tauri-apps/api/event'; -import * as path from '@tauri-apps/api/path'; -import * as fs from '@tauri-apps/plugin-fs'; import { config } from './config'; import { reloadThemes, @@ -9,6 +5,10 @@ import { updateInstalledThemeTags, updateInstalledThemeWorkshopId, } from './themes'; +import { invoke } from '@tauri-apps/api/core'; +import { listen } from '@tauri-apps/api/event'; +import * as path from '@tauri-apps/api/path'; +import * as fs from '@tauri-apps/plugin-fs'; export interface CommunityThemeAuthor { id: number; @@ -159,7 +159,9 @@ const DEFAULT_THEMES_SERVICE_URL = 'https://themes.ez-pp.farm'; export async function getThemesServiceUrl(): Promise { const customUrl = await config.value('themes_service_url').get(''); - return customUrl.trim().length > 0 ? customUrl.trim().replace(/\/+$/, '') : DEFAULT_THEMES_SERVICE_URL; + return customUrl.trim().length > 0 + ? customUrl.trim().replace(/\/+$/, '') + : DEFAULT_THEMES_SERVICE_URL; } /** @@ -273,7 +275,9 @@ export async function fetchCommunityThemeDetails(themeId: string): Promise { +export async function toggleCommunityThemeLike( + themeId: string +): Promise<{ liked: boolean; likeCount: number }> { const baseUrl = await getThemesServiceUrl(); const headers = await getAuthHeaders(); diff --git a/src/lib/components/notifications/NotificationHub.svelte b/src/lib/components/notifications/NotificationHub.svelte index cbee43d..287254a 100644 --- a/src/lib/components/notifications/NotificationHub.svelte +++ b/src/lib/components/notifications/NotificationHub.svelte @@ -1,8 +1,5 @@ -
- -
-
- -
- {#if selectedView === 'trash'} - - - Your trash - - {:else} - - - - + +
+
+ +
+ {#if selectedView === 'trash'} + + + Your trash + + {:else} + - -
-
- - - {#if tagSearch} - + + + + + {selectedTag === 'all' ? 'Filter by tag' : `#${selectedTag}`} + + {#if tagOptions.length > 0} + + {tagOptions.length} + + {/if} + {#if tagsLoading} + + {:else} + + {/if} + + + +
+
+ + + {#if tagSearch} + + {/if} +
+
+ +
+ + + {#if filteredTagOptions.length === 0} +

+ {tagOptions.length === 0 + ? 'No tags are in use yet.' + : 'No tags match your search.'} +

+ {:else} + {#each filteredTagOptions as option (option.tag)} + + {/each} {/if}
-
+ + -
- + {#if canModerate} + + {#snippet trigger(props)} + + {/snippet} + + {/if} + {/if} +
- {#if filteredTagOptions.length === 0} -

- {tagOptions.length === 0 - ? 'No tags are in use yet.' - : 'No tags match your search.'} -

- {:else} - {#each filteredTagOptions as option (option.tag)} - - {/each} - {/if} -
-
- + +
+ + +
+ + + {#snippet trigger(props)} + + {/snippet} + +
{#if canModerate} - + {#snippet trigger(props)} - + + {/snippet} {/if} - {/if} -
- -
- + {#if $currentUser} + + {#snippet trigger(props)} + + {/snippet} + + {/if} -
- - - {#snippet trigger(props)} - - {/snippet} - -
- - {#if canModerate} - + {#snippet trigger(props)} - {/snippet} - - {/if} - - {#if $currentUser} - - {#snippet trigger(props)} - {/snippet} - {/if} - - - {#snippet trigger(props)} - - {/snippet} - +
-
- -
- - {#if loading && themes.length === 0} -
- -

Connecting to EZPPFarm Community Workshop...

-
- {:else if error && themes.length === 0} -
-
- + +
+ + {#if loading && themes.length === 0} +
+ +

Connecting to EZPPFarm Community Workshop...

-
-

Workshop Offline or Unreachable

-

- {error}. Ensure the themes microservice container is running. -

-
- -
- {:else if themes.length === 0} -
- -

No community themes found matching your search.

-
- {:else} -
- {#each themes as theme (theme.id)} - {@const localTheme = localThemeMap.get(theme.id.toLowerCase()) || localThemeMap.get(theme.name.toLowerCase())} - {@const isInstalled = Boolean(localTheme)} - {@const isActive = Boolean(localTheme && $active_custom_theme?.folder_name === localTheme.folder_name)} - {@const isDownloading = downloadingId === theme.id} - {@const isDeleted = Boolean(theme.deletedAt)} - {@const hasUpdate = Boolean(!isDeleted && localTheme && localTheme.version !== theme.version)} - {@const owned = isOwnedByCurrentUser(theme)} - {@const isLegacy = - theme.apiVersion === '1.0' || Boolean(theme.tags?.includes('legacy'))} - {@const canReport = - Boolean($currentUser) && !owned && !theme.isHidden && !theme.isQuarantined} - {@const canFork = canReport && !isLegacy && theme.allowForking !== false} - {@const showOverflowMenu = !isDeleted && (owned || canModerate || canReport)} - -
+
+ +
+
+

Workshop Offline or Unreachable

+

+ {error}. Ensure the themes microservice container is running. +

+
+ +
+ {:else if themes.length === 0} +
+ +

No community themes found matching your search.

+
+ {:else} +
+ {#each themes as theme (theme.id)} + {@const localTheme = + localThemeMap.get(theme.id.toLowerCase()) || + localThemeMap.get(theme.name.toLowerCase())} + {@const isInstalled = Boolean(localTheme)} + {@const isActive = Boolean( + localTheme && $active_custom_theme?.folder_name === localTheme.folder_name + )} + {@const isDownloading = downloadingId === theme.id} + {@const isDeleted = Boolean(theme.deletedAt)} + {@const hasUpdate = Boolean( + !isDeleted && localTheme && localTheme.version !== theme.version + )} + {@const owned = isOwnedByCurrentUser(theme)} + {@const isLegacy = + theme.apiVersion === '1.0' || Boolean(theme.tags?.includes('legacy'))} + {@const canReport = + Boolean($currentUser) && !owned && !theme.isHidden && !theme.isQuarantined} + {@const canFork = canReport && !isLegacy && theme.allowForking !== false} + {@const showOverflowMenu = !isDeleted && (owned || canModerate || canReport)} - -
- {#if theme.apiVersion === '1.0' || theme.tags?.includes('legacy')} - - {#snippet trigger(props)} - - - Legacy v1 - - {/snippet} - - {:else if theme.hasExecutableCode} - - {#snippet trigger(props)} - - - Svelte Code - - {/snippet} - - {/if} - {#if theme.isHidden} - - {#snippet trigger(props)} - - - Hidden - - {/snippet} - - {/if} - {#if theme.isQuarantined} - - {#snippet trigger(props)} - - - Taken down - - {/snippet} - - {/if} - {#if isDeleted} - - {#snippet trigger(props)} - - - Trash - - {/snippet} - - {/if} -
+
+ +
+ {theme.name} { + // Fallback to default theme preview if server preview not loaded + (e.currentTarget as HTMLImageElement).src = DefaultThemePreview; + }} + /> +
- -
- - v{theme.version} - -
- - -
-
- {theme.author.name} { - (e.currentTarget as HTMLElement).style.display = 'none'; - }} - /> - - {theme.author.name} - - {#if theme.author.role === 'owner'} - + +
+ {#if theme.apiVersion === '1.0' || theme.tags?.includes('legacy')} + {#snippet trigger(props)} - - Owner + + Legacy v1 {/snippet} - {:else if theme.author.role === 'moderator'} - + {:else if theme.hasExecutableCode} + {#snippet trigger(props)} - - Moderator + + Svelte Code {/snippet} - {:else if theme.author.role === 'supporter' || (!theme.author.role && theme.author.donor)} - + {/if} + {#if theme.isHidden} + {#snippet trigger(props)} - - Supporter + + Hidden + + {/snippet} + + {/if} + {#if theme.isQuarantined} + + {#snippet trigger(props)} + + + Taken down + + {/snippet} + + {/if} + {#if isDeleted} + + {#snippet trigger(props)} + + + Trash {/snippet} {/if}
- - {formatBytes(theme.fileSize)} - -
-
- -
-
-
-

- {theme.name} -

+ +
+ + v{theme.version} + +
- - {#if isDeleted} - - Deleted + +
+
+ {theme.author.name} { + (e.currentTarget as HTMLElement).style.display = 'none'; + }} + /> + + {theme.author.name} - {:else} - + {#if theme.author.role === 'owner'} + + {#snippet trigger(props)} + + + Owner + + {/snippet} + + {:else if theme.author.role === 'moderator'} + + {#snippet trigger(props)} + + + Moderator + + {/snippet} + + {:else if theme.author.role === 'supporter' || (!theme.author.role && theme.author.donor)} + + {#snippet trigger(props)} + + + Supporter + + {/snippet} + + {/if} +
+ + {formatBytes(theme.fileSize)} + +
+
+ + +
+
+
+

+ {theme.name} +

+ + + {#if isDeleted} + + Deleted + + {:else} + + {#snippet trigger(props)} + + {/snippet} + + {/if} +
+ + {#if theme.description} +

+ {theme.description} +

+ {/if} + + {#if theme.tags && theme.tags.length > 0} +
+ {#each theme.tags.slice(0, 3) as tag (tag)} + + {/each} +
+ {/if} + + {#if theme.isHidden || theme.isQuarantined} +
+ {#if theme.isHidden} +

+ + Hidden by {theme.hiddenByName ?? 'staff'} + {#if theme.hiddenAt} + · {formatModerationDate(theme.hiddenAt)} + {/if} +

+ {#if theme.hiddenReason} +

{theme.hiddenReason}

+ {/if} + {/if} + {#if theme.isQuarantined} +

+ + Taken down by {theme.quarantinedByName ?? 'staff'} + {#if theme.quarantinedAt} + · {formatModerationDate(theme.quarantinedAt)} + {/if} +

+ {#if theme.quarantineReason} +

{theme.quarantineReason}

+ {/if} + {/if} +
+ {/if} + + {#if theme.forkedFrom} + {@const forkedFrom = theme.forkedFrom} + {#snippet trigger(props)} {/snippet} {/if}
- {#if theme.description} -

- {theme.description} -

- {/if} - - {#if theme.tags && theme.tags.length > 0} -
- {#each theme.tags.slice(0, 3) as tag (tag)} - - {/each} -
- {/if} - - {#if theme.isHidden || theme.isQuarantined} -
- {#if theme.isHidden} -

- - Hidden by {theme.hiddenByName ?? 'staff'} - {#if theme.hiddenAt} - · {formatModerationDate(theme.hiddenAt)} - {/if} -

- {#if theme.hiddenReason} -

{theme.hiddenReason}

- {/if} - {/if} - {#if theme.isQuarantined} -

- - Taken down by {theme.quarantinedByName ?? 'staff'} - {#if theme.quarantinedAt} - · {formatModerationDate(theme.quarantinedAt)} - {/if} -

- {#if theme.quarantineReason} -

{theme.quarantineReason}

- {/if} + Installed + {/if}
- {/if} - {#if theme.forkedFrom} - {@const forkedFrom = theme.forkedFrom} - - {#snippet trigger(props)} - - {/snippet} - - {/if} -
- - -
-
- - - {theme.downloadCount} - - {#if isInstalled && !isActive} - - Installed - - {/if} -
- -
- {#if isDownloading} -
- {downloadProgress}% -
-
-
-
- {:else if deletingId === theme.id} - - Deleting - - {:else if forkingId === theme.id} - - Forking - - {:else if moderatingId === theme.id} - - Updating - - {:else if isDeleted} - {#if owned} - - {:else} - - Deleted - - {/if} - {:else} - {#if owned && !isLegacy && isInstalled} - - {:else if isActive} - - In use - - {:else if isInstalled && hasUpdate} - - {:else if isInstalled} - - {:else} - - {/if} - - {#if showOverflowMenu} - - - {#snippet child({ props })} - - {/snippet} - - + {#if isDownloading} +
+ {downloadProgress}% - {#if owned} - openTagEditor(theme)} - > - - Edit tags - - {#if !isLegacy && isInstalled && hasUpdate} - handleRefreshOwnedTheme(theme)} - > - - Refresh installed copy - - {/if} - {:else if canReport || canFork} - {#if canReport} - openReportDialog(theme)} - > - - Report theme - - {/if} - {#if canFork} - handleForkTheme(theme)} - > - - Fork theme - - {/if} +
+
+
+
+ {:else if deletingId === theme.id} + + Deleting + + {:else if forkingId === theme.id} + + Forking + + {:else if moderatingId === theme.id} + + Updating + + {:else if isDeleted} + {#if owned} + + {:else} + + Deleted + + {/if} + {:else} + {#if owned && !isLegacy && isInstalled} + + {:else if isActive} + + In use + + {:else if isInstalled && hasUpdate} + + {:else if isInstalled} + + {:else} + + {/if} - {#if canModerate} - {#if owned || canReport} - - {/if} - {#if !isLegacy} + {#if showOverflowMenu} + + + {#snippet child({ props })} + + {/snippet} + + + {#if owned} handleToggleVisibility(theme)} + onclick={() => openTagEditor(theme)} > - {#if theme.isHidden} - - Restore visibility + + Edit tags + + {#if !isLegacy && isInstalled && hasUpdate} + handleRefreshOwnedTheme(theme)} + > + + Refresh installed copy + + {/if} + {:else if canReport || canFork} + {#if canReport} + openReportDialog(theme)} + > + + Report theme + + {/if} + {#if canFork} + handleForkTheme(theme)} + > + + Fork theme + + {/if} + {/if} + + {#if canModerate} + {#if owned || canReport} + + {/if} + {#if !isLegacy} + handleToggleVisibility(theme)} + > + {#if theme.isHidden} + + Restore visibility + {:else} + + Hide from workshop + {/if} + + {/if} + handleToggleQuarantine(theme)} + disabled={quarantineId === theme.id} + > + {#if quarantineId === theme.id} + + Updating... {:else} - - Hide from workshop + + {theme.isQuarantined ? 'Lift takedown' : 'Take down theme'} {/if} + void openThemeHistory(theme.id, theme.name)} + > + + Moderation history + {/if} - handleToggleQuarantine(theme)} - disabled={quarantineId === theme.id} - > - {#if quarantineId === theme.id} - - Updating... - {:else} - - {theme.isQuarantined ? 'Lift takedown' : 'Take down theme'} - {/if} - - void openThemeHistory(theme.id, theme.name)} - > - - Moderation history - - {/if} - {#if owned} - - handleDeleteTheme(theme)} - > - - Move to trash - - {/if} - - + {#if owned} + + handleDeleteTheme(theme)} + > + + Move to trash + + {/if} +
+
+ {/if} {/if} - {/if} +
-
- {/each} -
- {#if page < totalPages} -
- + {/each}
+ {#if page < totalPages} +
+ +
+ {/if} {/if} - {/if} - + +
-
- - -
-
- - - Moderation - - - Open reports and recent staff activity. - -
+ + +
+
+ + + Moderation + + + Open reports and recent staff activity. + +
{#snippet trigger(props)} @@ -2281,7 +2298,9 @@
{:else}
-

+

Reports {/if} {#if moderationReports.length === 0} -

+

No reports match these filters.

{:else} @@ -2323,7 +2344,9 @@
-

{report.themeName}

+

+ {report.themeName} +

-

{report.reason}

+

+ {report.reason} +

{#if report.status !== 'open'}

{report.status === 'resolved' ? 'Resolved' : 'Dismissed'} by @@ -2364,7 +2389,9 @@ {/if}

{#if report.resolutionNote} -

+

Note: {report.resolutionNote}

{/if} @@ -2438,7 +2465,9 @@
-

+

Recent activity

@@ -2498,7 +2527,9 @@
{#if moderationEvents.length === 0} -

+

No moderation events yet.

{:else} @@ -2508,9 +2539,9 @@

{event.actorName} - {' · '} + · {moderationActionLabel(event.action)} - {' · '} + · {event.themeName}

@@ -2520,7 +2551,11 @@ {#if event.reason} {#snippet trigger(props)} -

+

{event.reason}

{/snippet} @@ -2546,521 +2581,556 @@
{/if}
- - + + -{#if announcementOpen} -
- -

+

+ This appears as a system notification in the recipient's hub. +

+
+ + {#snippet trigger(props)} + + {/snippet} +
- - {#snippet trigger(props)} - - {/snippet} - -
-
- {#if sourceLoading} -
- Loading original... -
- {:else if sourceError} -

- {sourceError} -

- {:else if sourceTheme} - {sourceTheme.name} { - (e.currentTarget as HTMLImageElement).src = DefaultThemePreview; - }} - /> -
-
-

{sourceTheme.name}

-

- by {sourceTheme.author.name} · v{sourceTheme.version} -

-
- - {sourceTheme.apiVersion === '1.0' ? 'Legacy v1' : 'API 2.x'} - -
- {#if sourceTheme.description} -

- {sourceTheme.description} + + + + + {#if announcementError} +

+ {announcementError}

{/if} - {#if sourceTheme.tags.length > 0} -
- {#each sourceTheme.tags as tag} - - #{tag} - - {/each} -
- {/if} -

- This fork keeps a snapshot of the source at fork time. The original may have changed since. -

- {/if} +
+
+ + +
-
-{/if} + {/if} -{#if tagEditorTarget} -
- -