Add mode READMEs and move Bigscreen app
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.
This commit is contained in:
@@ -0,0 +1,309 @@
|
||||
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,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user