Merge the typing game into the music player as a tab, with lock/unlock UI
Moves tippen from a standalone app into web/ as a third tab (audio player / smarthome / typing), replacing the old single room-toggle corner button with a vertical icon tab rail. Curriculum and progress now come from the backend (musicmouse/tippen/*) instead of a build-time YAML import and localStorage. Adds reward-driven lock rendering: Cover/BrowseView/AlbumModal show a question mark for locked albums/tracks with a hint on what unlocks them, and ResultSheet gets a new unlock-animation block alongside the existing lesson-unlock and aquarium-creature celebrations. CSS from the two apps is merged carefully: identical rules (bubble/card/ key-cap/view-enter/backdrop-enter and their keyframes) are shared as-is, while rules that bake in each app's own hue are kept separate under a `tp-` prefix and scoped to the typing tab's own .tp-stage wrapper, so neither app's look bleeds into the other's. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,8 @@ import { PlayerBar } from "./components/PlayerBar";
|
||||
import { PlayView } from "./components/PlayView";
|
||||
import { RemoteAssignPopup } from "./components/RemoteAssignPopup";
|
||||
import { RoomView } from "./components/RoomView";
|
||||
import { TabRail } from "./components/TabRail";
|
||||
import { TippenApp } from "./components/TippenApp";
|
||||
import { useGridColumns } from "./hooks/useGridColumns";
|
||||
import { useLibrary } from "./hooks/useLibrary";
|
||||
import { usePlayerState } from "./hooks/usePlayerState";
|
||||
@@ -401,8 +403,8 @@ export function App() {
|
||||
}
|
||||
run(browseBackActions(ui));
|
||||
};
|
||||
const onToggleRoom = () =>
|
||||
setUi((previous) => ({ ...previous, page: previous.page === "room" ? "music" : "room" }));
|
||||
const onSelectPage = (page: UiState["page"]) =>
|
||||
setUi((previous) => ({ ...previous, page: previous.page === page ? "music" : page }));
|
||||
|
||||
return (
|
||||
<div className="stage" data-blur={SHOW_GLASS_BLUR ? undefined : "off"}>
|
||||
@@ -497,6 +499,10 @@ export function App() {
|
||||
|
||||
{ui.page === "room" && haConfig && <RoomView config={haConfig} />}
|
||||
|
||||
{ui.page === "typing" && (
|
||||
<TippenApp onExit={() => setUi((previous) => ({ ...previous, page: "music" }))} />
|
||||
)}
|
||||
|
||||
{openAlbum && state && (
|
||||
<AlbumModal
|
||||
album={openAlbum}
|
||||
@@ -522,15 +528,7 @@ export function App() {
|
||||
</CornerButton>
|
||||
)}
|
||||
|
||||
{haConfig && (
|
||||
<CornerButton
|
||||
side="right"
|
||||
onClick={onToggleRoom}
|
||||
label={ui.page === "room" ? "Musik" : "Mein Zimmer"}
|
||||
>
|
||||
{ui.page === "room" ? "🎵" : "💡"}
|
||||
</CornerButton>
|
||||
)}
|
||||
<TabRail page={ui.page} onSelect={onSelectPage} showRoom={haConfig != null} />
|
||||
|
||||
{ui.showHelp && (
|
||||
<HelpOverlay onClose={() => setUi((previous) => ({ ...previous, showHelp: false }))} />
|
||||
|
||||
Reference in New Issue
Block a user