f0d2926872
Add comprehensive READMEs for Bigscreen and Desktop modes, and relocate the Tauri frontend prototype into a new Bigscreen/ subdirectory. This moves package.json/package-lock, src, src-tauri, assets, views, styles and related files into Bigscreen/ to separate the controller-first shell from top-level docs. Update the root README.md to reframe the project as "NebulaOS", describe Bigscreen/Desktop modes, the vision, tech stack and development notes. This reorganizes the repo layout for clearer mode separation and documentation.
310 lines
15 KiB
JavaScript
310 lines
15 KiB
JavaScript
export const LIBRARY_CATEGORIES = [
|
|
{ id: "games", label: "Games" },
|
|
{ id: "software", label: "Software" },
|
|
{ id: "unified", label: "Unified Library" },
|
|
];
|
|
|
|
export const GENRE_FILTERS = [
|
|
"All Genres",
|
|
"Action",
|
|
"RPG",
|
|
"Strategy",
|
|
"Indie",
|
|
"Latest Installed",
|
|
"Recently Played",
|
|
];
|
|
|
|
export const PLATFORM_FILTERS = ["all", "steam", "gog", "epic", "native", "emulated", "other"];
|
|
|
|
export const SORT_OPTIONS = [
|
|
{ id: "recentlyPlayed", label: "Recently played" },
|
|
{ id: "recentlyInstalled", label: "Recently installed" },
|
|
{ id: "alphabetical", label: "Alphabetical" },
|
|
{ id: "playtime", label: "Playtime" },
|
|
{ id: "platform", label: "Platform" },
|
|
];
|
|
|
|
export const SOURCE_LABELS = {
|
|
steam: "Steam",
|
|
gog: "GOG",
|
|
epic: "Epic",
|
|
native: "Native",
|
|
emulated: "Emulated",
|
|
other: "Other",
|
|
};
|
|
|
|
export const TYPE_LABELS = {
|
|
game: "Game",
|
|
software: "Software",
|
|
tool: "Tool",
|
|
launcher: "Launcher",
|
|
};
|
|
|
|
export const PLAY_STATE_LABELS = {
|
|
all: "All play states",
|
|
played: "Played",
|
|
unplayed: "Unplayed",
|
|
};
|
|
|
|
export const createDefaultLibraryQuery = () => ({
|
|
category: "games",
|
|
genre: "All Genres",
|
|
platform: "all",
|
|
installedOnly: false,
|
|
playState: "all",
|
|
coOpOnly: false,
|
|
achievementsOnly: false,
|
|
sortBy: "recentlyPlayed",
|
|
includeHidden: false,
|
|
});
|
|
|
|
const sourceFromBackend = (source) => {
|
|
const normalized = String(source ?? "").toLowerCase();
|
|
if (normalized === "local") return "native";
|
|
if (["steam", "gog", "epic", "native", "emulated"].includes(normalized)) return normalized;
|
|
return "other";
|
|
};
|
|
|
|
const typeFromBackend = (kind) => {
|
|
const normalized = String(kind ?? "").toLowerCase();
|
|
if (["game", "software", "tool", "launcher"].includes(normalized)) return normalized;
|
|
return "game";
|
|
};
|
|
|
|
export const initialsForTitle = (title) =>
|
|
String(title ?? "Nebula")
|
|
.split(/\s+/)
|
|
.filter(Boolean)
|
|
.slice(0, 2)
|
|
.map((part) => part[0]?.toUpperCase())
|
|
.join("") || "OS";
|
|
|
|
export const formatPlaytime = (minutes = 0) => {
|
|
if (!minutes) return "Not played";
|
|
if (minutes < 60) return `${minutes}m`;
|
|
const hours = Math.floor(minutes / 60);
|
|
const remainder = minutes % 60;
|
|
return remainder ? `${hours}h ${remainder}m` : `${hours}h`;
|
|
};
|
|
|
|
export const formatShortDate = (value) => {
|
|
if (!value) return "Never";
|
|
const date = new Date(value);
|
|
if (Number.isNaN(date.getTime())) return "Never";
|
|
return date.toLocaleDateString([], { month: "short", day: "numeric" });
|
|
};
|
|
|
|
export const normalizeLibraryItem = (raw, index = 0, convertFileSrc = null) => {
|
|
const title = raw?.userTitle || raw?.title || "Unknown App";
|
|
const source = sourceFromBackend(raw?.platformSource ?? raw?.source);
|
|
const type = typeFromBackend(raw?.appKind ?? raw?.type);
|
|
const convert = (path) => (path && convertFileSrc ? convertFileSrc(path) : path || null);
|
|
const convertArray = (paths) => (Array.isArray(paths) ? paths.map(convert).filter(Boolean) : []);
|
|
const installed = raw?.installed ?? Boolean(raw?.installPath || raw?.install_path);
|
|
|
|
return {
|
|
id: String(raw?.id ?? `backend-${index}`),
|
|
backendId: raw?.id ?? null,
|
|
title,
|
|
type,
|
|
source,
|
|
genre: Array.isArray(raw?.genre)
|
|
? raw.genre
|
|
: Array.isArray(raw?.genres)
|
|
? raw.genres
|
|
: type === "game"
|
|
? ["Action"]
|
|
: ["Utilities"],
|
|
installed,
|
|
installPath: raw?.installPath ?? raw?.install_path ?? null,
|
|
executablePath: raw?.executablePath ?? raw?.executable_path ?? null,
|
|
coverImage: convert(raw?.coverImage ?? raw?.cover_image),
|
|
bannerImage: convert(raw?.bannerImage ?? raw?.heroImage ?? raw?.hero_image),
|
|
iconImage: convert(raw?.iconImage ?? raw?.icon_image),
|
|
screenshots: convertArray(raw?.screenshots ?? []),
|
|
description:
|
|
raw?.description ||
|
|
"Scanned from your local library. Metadata can be enriched later by Steam, GOG, Epic, emulator, and local metadata providers.",
|
|
longDescription: raw?.longDescription ?? null,
|
|
lastPlayed: raw?.lastPlayed ?? null,
|
|
installedAt: raw?.installedAt ?? raw?.createdAt ?? null,
|
|
playtimeMinutes: Number(raw?.playtimeMinutes ?? 0),
|
|
supportsController: Boolean(raw?.supportsController ?? type === "game"),
|
|
steamDeckVerified: Boolean(raw?.steamDeckVerified ?? source === "steam"),
|
|
achievementsSupported: Boolean(raw?.achievementsSupported ?? false),
|
|
achievementsUnlocked: raw?.achievementsUnlocked ?? null,
|
|
achievementsTotal: raw?.achievementsTotal ?? null,
|
|
hidden: Boolean(raw?.hidden ?? raw?.userHidden ?? false),
|
|
multiplayer: Boolean(raw?.multiplayer ?? false),
|
|
coOp: Boolean(raw?.coOp ?? false),
|
|
accent: raw?.accent ?? ["#4fd8ff", "#9d4fe0", "#1f7aff", "#39ffd2"][index % 4],
|
|
};
|
|
};
|
|
|
|
export const createMockLibraryItems = () =>
|
|
[
|
|
{
|
|
id: "mock-starfall",
|
|
title: "Starfall Protocol",
|
|
type: "game",
|
|
source: "steam",
|
|
genre: ["Action", "RPG"],
|
|
installed: true,
|
|
installPath: "C:/Games/Starfall Protocol",
|
|
executablePath: "C:/Games/Starfall Protocol/starfall.exe",
|
|
description: "Pilot a relic fighter through collapsing gates in a neon campaign built for controller play.",
|
|
longDescription: "Experience a fast-paced action-RPG where you pilot experimental fighter craft through a collapsing interdimensional gateway. Built from the ground up with controller support, Starfall Protocol features real-time combat, intricate level design, and a gripping sci-fi narrative. Perfect for couch co-op sessions or solo playthroughs.",
|
|
lastPlayed: "2026-05-15T21:15:00Z",
|
|
installedAt: "2026-05-01T08:30:00Z",
|
|
playtimeMinutes: 1874,
|
|
supportsController: true,
|
|
steamDeckVerified: true,
|
|
achievementsSupported: true,
|
|
achievementsUnlocked: 28,
|
|
achievementsTotal: 54,
|
|
multiplayer: true,
|
|
coOp: true,
|
|
screenshots: [
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%234fd8ff' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3EStarfall Protocol - Screenshot 1%3C/text%3E%3C/svg%3E",
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%239d4fe0' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3EStarfall Protocol - Screenshot 2%3C/text%3E%3C/svg%3E",
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%231f7aff' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3EStarfall Protocol - Screenshot 3%3C/text%3E%3C/svg%3E",
|
|
],
|
|
accent: "#4fd8ff",
|
|
},
|
|
{
|
|
id: "mock-iron-vault",
|
|
title: "Iron Vault Tactics",
|
|
type: "game",
|
|
source: "gog",
|
|
genre: ["Strategy", "Indie"],
|
|
installed: true,
|
|
installPath: "D:/Games/Iron Vault Tactics",
|
|
executablePath: "D:/Games/Iron Vault Tactics/ivt.exe",
|
|
description: "A turn-based tactics sandbox with long-form campaigns, mod support, and couch co-op skirmishes.",
|
|
longDescription: "Command your squad through dynamic turn-based tactical battles in Iron Vault Tactics. Features mod support, deep unit customization, engaging campaign narratives, and intense couch co-op multiplayer. Each decision matters in this tactical masterpiece.",
|
|
lastPlayed: "2026-05-10T11:00:00Z",
|
|
installedAt: "2026-04-18T18:00:00Z",
|
|
playtimeMinutes: 942,
|
|
supportsController: true,
|
|
achievementsSupported: false,
|
|
multiplayer: true,
|
|
coOp: true,
|
|
screenshots: [
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%2339ffd2' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3EIron Vault Tactics - Screenshot 1%3C/text%3E%3C/svg%3E",
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%234fd8ff' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3EIron Vault Tactics - Screenshot 2%3C/text%3E%3C/svg%3E",
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%239d4fe0' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3EIron Vault Tactics - Screenshot 3%3C/text%3E%3C/svg%3E",
|
|
],
|
|
accent: "#39ffd2",
|
|
},
|
|
{
|
|
id: "mock-nebula-paint",
|
|
title: "Nebula Paint Studio",
|
|
type: "software",
|
|
source: "native",
|
|
genre: ["Creative", "Utilities"],
|
|
installed: true,
|
|
installPath: "C:/Program Files/Nebula Paint",
|
|
executablePath: "C:/Program Files/Nebula Paint/paint.exe",
|
|
description: "A TV-friendly concept art tool for quick capture, markup, and launcher artwork editing.",
|
|
longDescription: "Nebula Paint Studio is a professional-grade digital painting application optimized for controller input and TV display. Create stunning concept art, edit game launcher artwork, and collaborate seamlessly with frame-perfect precision.",
|
|
lastPlayed: "2026-05-11T06:20:00Z",
|
|
installedAt: "2026-03-12T09:00:00Z",
|
|
playtimeMinutes: 223,
|
|
supportsController: true,
|
|
achievementsSupported: false,
|
|
multiplayer: false,
|
|
coOp: false,
|
|
screenshots: [
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%239d4fe0' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3ENebula Paint Studio - Screenshot 1%3C/text%3E%3C/svg%3E",
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%234fd8ff' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3ENebula Paint Studio - Screenshot 2%3C/text%3E%3C/svg%3E",
|
|
],
|
|
accent: "#9d4fe0",
|
|
},
|
|
{
|
|
id: "mock-ember",
|
|
title: "Emberline",
|
|
type: "game",
|
|
source: "epic",
|
|
genre: ["Action", "Indie"],
|
|
installed: false,
|
|
installPath: null,
|
|
executablePath: null,
|
|
description: "Wishlist entry from a linked store. Install support will be routed through the Epic integration later.",
|
|
longDescription: "Emberline is an indie action game with stunning visuals and engaging gameplay. Add it to your library to stay updated on new releases, sales, and updates.",
|
|
lastPlayed: null,
|
|
installedAt: null,
|
|
playtimeMinutes: 0,
|
|
supportsController: true,
|
|
steamDeckVerified: false,
|
|
achievementsSupported: true,
|
|
achievementsUnlocked: 0,
|
|
achievementsTotal: 32,
|
|
multiplayer: false,
|
|
coOp: false,
|
|
screenshots: [
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%231f7aff' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3EEmberline - Screenshot 1%3C/text%3E%3C/svg%3E",
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%239d4fe0' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3EEmberline - Screenshot 2%3C/text%3E%3C/svg%3E",
|
|
],
|
|
accent: "#1f7aff",
|
|
},
|
|
{
|
|
id: "mock-retro-core",
|
|
title: "RetroCore Station",
|
|
type: "launcher",
|
|
source: "emulated",
|
|
genre: ["Launcher", "Retro"],
|
|
installed: true,
|
|
installPath: "D:/Emulation/RetroCore",
|
|
executablePath: "D:/Emulation/RetroCore/retrocore.exe",
|
|
description: "A controller-native emulator hub prepared for future ROM library scanning and save sync.",
|
|
longDescription: "RetroCore Station is your gateway to classic gaming. Play thousands of retro games with full controller support, save synchronization, and achievement tracking across multiple emulation systems.",
|
|
lastPlayed: "2026-05-14T04:10:00Z",
|
|
installedAt: "2026-05-03T15:10:00Z",
|
|
playtimeMinutes: 517,
|
|
supportsController: true,
|
|
achievementsSupported: true,
|
|
achievementsUnlocked: 88,
|
|
achievementsTotal: 210,
|
|
multiplayer: true,
|
|
coOp: true,
|
|
screenshots: [
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%23ffb84f' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3ERetroCore Station - Screenshot 1%3C/text%3E%3C/svg%3E",
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%234fd8ff' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3ERetroCore Station - Screenshot 2%3C/text%3E%3C/svg%3E",
|
|
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='960' height='540'%3E%3Crect fill='%239d4fe0' width='960' height='540'/%3E%3Ctext x='480' y='270' font-size='24' fill='white' text-anchor='middle' dominant-baseline='middle'%3ERetroCore Station - Screenshot 3%3C/text%3E%3C/svg%3E",
|
|
],
|
|
accent: "#ffb84f",
|
|
},
|
|
{
|
|
id: "mock-orbit-tools",
|
|
title: "Orbit Mod Tools",
|
|
type: "tool",
|
|
source: "other",
|
|
genre: ["Utilities", "Game Development"],
|
|
installed: false,
|
|
installPath: null,
|
|
executablePath: null,
|
|
description: "Tooling placeholder for future mod SDK detection, dependency checks, and per-game utilities.",
|
|
longDescription: "Orbit Mod Tools provides a comprehensive suite of utilities for game modding, including SDK management, dependency resolution, and per-game optimization tools. Essential for serious mod creators.",
|
|
lastPlayed: null,
|
|
installedAt: null,
|
|
playtimeMinutes: 0,
|
|
supportsController: false,
|
|
achievementsSupported: false,
|
|
multiplayer: false,
|
|
coOp: false,
|
|
screenshots: [],
|
|
accent: "#ff6b9a",
|
|
},
|
|
].map((item, index) => normalizeLibraryItem(item, index));
|
|
|
|
export const summarizeLibrary = (items) => {
|
|
const visible = items.filter((item) => !item.hidden);
|
|
return {
|
|
total: visible.length,
|
|
games: visible.filter((item) => item.type === "game").length,
|
|
verified: visible.filter((item) => item.steamDeckVerified).length,
|
|
hidden: items.filter((item) => item.hidden).length,
|
|
installed: visible.filter((item) => item.installed).length,
|
|
};
|
|
};
|