From d3e1bf049b19659cca0f5b57f205111c1f8ada7b Mon Sep 17 00:00:00 2001 From: Garret Patti <42485635+garretpatti@users.noreply.github.com> Date: Sun, 12 Apr 2026 11:53:27 -0400 Subject: [PATCH 1/3] handle android and swap to os icons --- src/app/icons/android.svg | 6 ++++++ src/app/icons/linux.svg | 6 ++++++ src/app/icons/mac.svg | 19 +++++++++++++++++ src/app/icons/windows.svg | 19 +++++++++++++++++ src/components/games/GameDetailModal.tsx | 25 ++++++++++++++++++++-- src/components/games/GamesView.tsx | 27 ++++++++++++++++++++++-- src/lib/games.ts | 1 + src/types/index.ts | 2 +- 8 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 src/app/icons/android.svg create mode 100644 src/app/icons/linux.svg create mode 100644 src/app/icons/mac.svg create mode 100644 src/app/icons/windows.svg diff --git a/src/app/icons/android.svg b/src/app/icons/android.svg new file mode 100644 index 0000000..b413770 --- /dev/null +++ b/src/app/icons/android.svg @@ -0,0 +1,6 @@ + + + +android + + \ No newline at end of file diff --git a/src/app/icons/linux.svg b/src/app/icons/linux.svg new file mode 100644 index 0000000..2172e59 --- /dev/null +++ b/src/app/icons/linux.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/app/icons/mac.svg b/src/app/icons/mac.svg new file mode 100644 index 0000000..381f84a --- /dev/null +++ b/src/app/icons/mac.svg @@ -0,0 +1,19 @@ + + + + + apple [#173] + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/icons/windows.svg b/src/app/icons/windows.svg new file mode 100644 index 0000000..81dcb9d --- /dev/null +++ b/src/app/icons/windows.svg @@ -0,0 +1,19 @@ + + + + + windows [#174] + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/games/GameDetailModal.tsx b/src/components/games/GameDetailModal.tsx index 8d29e7e..5d857c0 100644 --- a/src/components/games/GameDetailModal.tsx +++ b/src/components/games/GameDetailModal.tsx @@ -4,15 +4,25 @@ import { useEffect, useRef, useState, useCallback } from 'react' import type { Game, GameFile, GamePlatform } from '@/types' import TagSelector from '@/components/tags/TagSelector' +// Import SVG icons +import WindowsIcon from '@/app/icons/windows.svg' +import LinuxIcon from '@/app/icons/linux.svg' +import MacosIcon from '@/app/icons/mac.svg' +import AndroidIcon from '@/app/icons/android.svg' + +// Update the PLATFORM_LABELS to include android const PLATFORM_LABELS: Record = { windows: 'WIN', linux: 'LIN', macos: 'MAC', + android: 'AND', } + const PLATFORM_COLORS: Record = { windows: '#0078d4', linux: '#e95420', macos: '#6e6e73', + android: '#10b981', } interface Props { @@ -516,13 +526,24 @@ export default function GameDetailModal({ game, libraryId, onClose, onTagsChange // ─── Download Button ────────────────────────────────────────────────────────── +const PLATFORM_ICONS: Record = { + windows: (typeof WindowsIcon === 'string' ? WindowsIcon : (WindowsIcon as { src: string }).src), + linux: (typeof LinuxIcon === 'string' ? LinuxIcon : (LinuxIcon as { src: string }).src), + macos: (typeof MacosIcon === 'string' ? MacosIcon : (MacosIcon as { src: string }).src), + android: (typeof AndroidIcon === 'string' ? AndroidIcon : (AndroidIcon as { src: string }).src), +} + function PlatformPill({ platform }: { platform: GamePlatform }) { + const src = PLATFORM_ICONS[platform] + return ( - {PLATFORM_LABELS[platform]} + {/* eslint-disable-next-line @next/next/no-img-element */} + {src && } + {PLATFORM_LABELS[platform]} ) } diff --git a/src/components/games/GamesView.tsx b/src/components/games/GamesView.tsx index 66dc217..0aadb07 100644 --- a/src/components/games/GamesView.tsx +++ b/src/components/games/GamesView.tsx @@ -5,15 +5,37 @@ import type { Game, GamePlatform, GameSeries } from '@/types' import GameDetailModal from './GameDetailModal' import FilterPanel from '@/components/FilterPanel' +// Import SVG icons +import WindowsIcon from '@/app/icons/windows.svg' +import LinuxIcon from '@/app/icons/linux.svg' +import MacosIcon from '@/app/icons/mac.svg' +import AndroidIcon from '@/app/icons/android.svg' + const PLATFORM_LABELS: Record = { windows: 'WIN', linux: 'LIN', macos: 'MAC', + android: 'AND', } const PLATFORM_COLORS: Record = { windows: '#0078d4', linux: '#e95420', macos: '#6e6e73', + android: '#10b981', +} + +const PLATFORM_ICONS: Record = { + windows: (typeof WindowsIcon === 'string' ? WindowsIcon : (WindowsIcon as { src: string }).src), + linux: (typeof LinuxIcon === 'string' ? LinuxIcon : (LinuxIcon as { src: string }).src), + macos: (typeof MacosIcon === 'string' ? MacosIcon : (MacosIcon as { src: string }).src), + android: (typeof AndroidIcon === 'string' ? AndroidIcon : (AndroidIcon as { src: string }).src), +} + +function getPlatformIcon(platform: GamePlatform) { + const src = PLATFORM_ICONS[platform] + if (!src) return null + // eslint-disable-next-line @next/next/no-img-element + return } function PlatformBadges({ platforms }: { platforms: GamePlatform[] }) { @@ -23,10 +45,11 @@ function PlatformBadges({ platforms }: { platforms: GamePlatform[] }) { {platforms.map((p) => ( - {PLATFORM_LABELS[p]} + {getPlatformIcon(p)} + {PLATFORM_LABELS[p]} ))} diff --git a/src/lib/games.ts b/src/lib/games.ts index 8f4c151..cc7ada8 100644 --- a/src/lib/games.ts +++ b/src/lib/games.ts @@ -12,6 +12,7 @@ function platformForFile(name: string): GamePlatform | null { if (lower.endsWith('.zip')) return 'windows' if (lower.endsWith('.tar.gz')) return 'linux' if (lower.endsWith('.dmg')) return 'macos' + if (lower.endsWith('.apk')) return 'android' return null } diff --git a/src/types/index.ts b/src/types/index.ts index 411375a..19d014c 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -8,7 +8,7 @@ export interface Library { coverExt: string | null } -export type GamePlatform = 'windows' | 'linux' | 'macos' +export type GamePlatform = 'windows' | 'linux' | 'macos' | 'android' export interface GameFile { path: string -- 2.49.1 From 080cc011b9b9a0c2defa234a09e768a319fdd52b Mon Sep 17 00:00:00 2001 From: Garret Patti <42485635+garretpatti@users.noreply.github.com> Date: Sun, 12 Apr 2026 12:41:42 -0400 Subject: [PATCH 2/3] icon color and size tweaks --- src/components/games/GameDetailModal.tsx | 14 ++++++++------ src/components/games/GamesView.tsx | 8 ++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/games/GameDetailModal.tsx b/src/components/games/GameDetailModal.tsx index 5d857c0..43ba60a 100644 --- a/src/components/games/GameDetailModal.tsx +++ b/src/components/games/GameDetailModal.tsx @@ -19,10 +19,10 @@ const PLATFORM_LABELS: Record = { } const PLATFORM_COLORS: Record = { - windows: '#0078d4', - linux: '#e95420', - macos: '#6e6e73', - android: '#10b981', + windows: '#85c0ec', + linux: '#efd27b', + macos: '#b0b0b7', + android: '#9ee0ca', } interface Props { @@ -589,8 +589,9 @@ function DownloadButton({ onMouseLeave={(e) => ((e.currentTarget as HTMLElement).style.backgroundColor = 'var(--accent)')} > - - Download {primary.filename} + {primary.filename} + + ) } @@ -610,6 +611,7 @@ function DownloadButton({ {primary.filename} + {/* Divider */} diff --git a/src/components/games/GamesView.tsx b/src/components/games/GamesView.tsx index 0aadb07..a278d1b 100644 --- a/src/components/games/GamesView.tsx +++ b/src/components/games/GamesView.tsx @@ -18,10 +18,10 @@ const PLATFORM_LABELS: Record = { android: 'AND', } const PLATFORM_COLORS: Record = { - windows: '#0078d4', - linux: '#e95420', - macos: '#6e6e73', - android: '#10b981', + windows: '#85c0ec', + linux: '#efd27b', + macos: '#b0b0b7', + android: '#9ee0ca', } const PLATFORM_ICONS: Record = { -- 2.49.1 From 0091606e4d8050f8fc255935855689b07d204b2d Mon Sep 17 00:00:00 2001 From: Garret Patti <42485635+garretpatti@users.noreply.github.com> Date: Sun, 12 Apr 2026 13:09:07 -0400 Subject: [PATCH 3/3] handle other archive types for linux --- src/app/api/file/route.ts | 22 +++++++++++++++++++--- src/components/games/GameDetailModal.tsx | 3 +-- src/lib/games.ts | 4 ++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/app/api/file/route.ts b/src/app/api/file/route.ts index 36d76a2..cb97190 100644 --- a/src/app/api/file/route.ts +++ b/src/app/api/file/route.ts @@ -23,18 +23,34 @@ const MIME_TYPES: Record = { '.zip': 'application/zip', '.dmg': 'application/x-apple-diskimage', '.gz': 'application/gzip', + '.tgz': 'application/gzip', + '.bz2': 'application/x-bzip2', + '.xz': 'application/x-xz', + '.zst': 'application/zstd', } function getMimeType(filePath: string): string { - // Special-case .tar.gz before checking the last extension - if (filePath.toLowerCase().endsWith('.tar.gz')) return 'application/gzip' + // Special-case multi-part extensions before checking the last extension + const lower = filePath.toLowerCase() + if (lower.endsWith('.tar.gz')) return 'application/gzip' + if (lower.endsWith('.tar.bz2')) return 'application/x-bzip2' + if (lower.endsWith('.tar.xz')) return 'application/x-xz' + if (lower.endsWith('.tar.zst')) return 'application/zstd' const ext = path.extname(filePath).toLowerCase() return MIME_TYPES[ext] ?? 'application/octet-stream' } function isDownloadAttachment(filePath: string): boolean { const lower = filePath.toLowerCase() - return lower.endsWith('.zip') || lower.endsWith('.tar.gz') || lower.endsWith('.dmg') + return ( + lower.endsWith('.zip') || + lower.endsWith('.tar.gz') || + lower.endsWith('.tar.bz2') || + lower.endsWith('.tar.xz') || + lower.endsWith('.tar.zst') || + lower.endsWith('.tgz') || + lower.endsWith('.dmg') + ) } export async function GET(request: NextRequest) { diff --git a/src/components/games/GameDetailModal.tsx b/src/components/games/GameDetailModal.tsx index 43ba60a..b9a8508 100644 --- a/src/components/games/GameDetailModal.tsx +++ b/src/components/games/GameDetailModal.tsx @@ -609,7 +609,6 @@ function DownloadButton({ onMouseLeave={(e) => ((e.currentTarget as HTMLElement).style.backgroundColor = 'transparent')} > - {primary.filename} @@ -647,8 +646,8 @@ function DownloadButton({ onMouseLeave={(e) => ((e.currentTarget as HTMLElement).style.backgroundColor = 'transparent')} > - {file.filename} + ))} diff --git a/src/lib/games.ts b/src/lib/games.ts index cc7ada8..30dbba7 100644 --- a/src/lib/games.ts +++ b/src/lib/games.ts @@ -11,6 +11,10 @@ function platformForFile(name: string): GamePlatform | null { const lower = name.toLowerCase() if (lower.endsWith('.zip')) return 'windows' if (lower.endsWith('.tar.gz')) return 'linux' + if (lower.endsWith('.tar.bz2')) return 'linux' + if (lower.endsWith('.tar.xz')) return 'linux' + if (lower.endsWith('.tar.zst')) return 'linux' + if (lower.endsWith('.tgz')) return 'linux' if (lower.endsWith('.dmg')) return 'macos' if (lower.endsWith('.apk')) return 'android' return null -- 2.49.1