feat(ui): label streamed installs as not shareable

NEXT_STEPS item 7 needed the installed-but-not-downloaded state to be
clear to users. Keep streamed installs in the installed visual state so
sorting, filters, and the primary Play action stay unchanged, but make the
sharing limitation visible in the UI.

Cards now label that state as `Not shareable`, while the detail modal
status says `Installed, not shareable`. Downloaded-and-installed games
keep the normal `Installed` wording.

Test Plan:
- just frontend-test
- just build
- git diff --check
- git diff --cached --check

Refs: NEXT_STEPS.md item 7
This commit is contained in:
2026-06-07 22:29:26 +02:00
parent 9288fda037
commit f62515451b
5 changed files with 79 additions and 26 deletions
@@ -1,13 +1,5 @@
import { Game } from '../lib/types';
import { deriveState } from '../lib/gameState';
const LABELS: Record<string, string> = {
installed: 'Installed',
local: 'Local',
downloading: 'Downloading',
busy: 'Working',
none: '',
};
import { deriveState, stateChipLabel } from '../lib/gameState';
interface Props {
game: Game;
@@ -17,7 +9,7 @@ interface Props {
export const StateChip = ({ game, showNone = false }: Props) => {
const state = deriveState(game);
const label = LABELS[state] ?? '';
const label = stateChipLabel(game);
if (!label && !showNone) return null;
return (
<div className="state-chip" data-state={state}>
@@ -5,7 +5,7 @@ import { StateChip } from '../StateChip';
import { ActionButton } from '../ActionButton';
import { Game, InstallStatus } from '../../lib/types';
import { canStreamInstall, deriveState, hasNewerLocalVersion, isInProgress } from '../../lib/gameState';
import { canStreamInstall, gameStatusLabel, hasNewerLocalVersion, isInProgress } from '../../lib/gameState';
import { formatBytes, formatEtiVersion, formatPlayers } from '../../lib/format';
interface Props {
@@ -29,16 +29,6 @@ const tagsFromGame = (game: Game): string[] => {
return tags;
};
const statusLabelFor = (game: Game): string => {
switch (deriveState(game)) {
case 'installed': return 'Installed';
case 'local': return 'Downloaded';
case 'downloading': return 'Downloading';
case 'busy': return 'Working…';
case 'none': return 'Not downloaded';
}
};
export const GameDetailModal = ({
game,
thumbnailUrl,
@@ -115,7 +105,7 @@ export const GameDetailModal = ({
</div>
<div className="meta-cell">
<div className="meta-label">Status</div>
<div className="meta-value">{statusLabelFor(game)}</div>
<div className="meta-value">{gameStatusLabel(game)}</div>
</div>
</div>