diff --git a/app/globals.css b/app/globals.css index 42aa009..9fe04c0 100644 --- a/app/globals.css +++ b/app/globals.css @@ -684,7 +684,17 @@ body { .pt-safe { padding-top: max(env(safe-area-inset-top), 0.75rem) } .pb-safe { padding-bottom: max(env(safe-area-inset-bottom), 0.75rem) } .pb-tabbar { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 5.25rem) } +/* Trailing room under the sticky "Freeze my deck" strip on /create. + Phones: the strip floats one tab-bar height above the viewport bottom (the + sticky bottom offset in UploadScreen), so the page only needs that much + scroll room under it — the strip settles exactly where it was already + floating, and the bottom bar is never double-counted. Keep 4.6rem in sync + with the sticky offset. Wider screens: the strip docks to the viewport + bottom and keeps the roomier 9rem. */ .pb-cta { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 9rem) } +@media (max-width: 639px) { + .pb-cta { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 4.6rem) } +} @media (display-mode: standalone) { .standalone-hide { display: none } diff --git a/components/LibraryScreen.tsx b/components/LibraryScreen.tsx index ec618ea..2beeea5 100644 --- a/components/LibraryScreen.tsx +++ b/components/LibraryScreen.tsx @@ -5,7 +5,7 @@ import { useMemo, useRef, useState, useSyncExternalStore } from "react"; import { DeckCard } from "@/components/DeckCard"; import { FolderBar } from "@/components/FolderBar"; -import { FolderIcon, UploadIcon } from "@/components/icons"; +import { FolderIcon, SnowflakeIcon, SparklesIcon, UploadIcon } from "@/components/icons"; import { Button, EmptyState } from "@/components/ui"; import { folderStore, renameFolder } from "@/lib/folders"; import { useI18n } from "@/lib/i18n"; @@ -224,9 +224,38 @@ export function LibraryScreen() { - {t("library.makeFirst")} - + /* Two ways in: build a study deck from notes, or hand over an + assignment. Stacked on phones, side by side from 640px up. */ +
+ + + + + + {t("emptyStateCreateDeck")} + + + + + + + + {t("emptyStateHomework")} + + +
} > {t("library.emptyBody")} diff --git a/components/UploadScreen.tsx b/components/UploadScreen.tsx index 8cbac2c..ce488f2 100644 --- a/components/UploadScreen.tsx +++ b/components/UploadScreen.tsx @@ -33,7 +33,7 @@ import { UNORGANIZED_ID, type Difficulty } from "@/lib/schemas"; import { upsertDeck } from "@/lib/storage"; import { openSettings } from "@/lib/ui-events"; import { cn, uid } from "@/lib/utils"; -import { CameraIcon, ChevronRightIcon, FolderIcon, IceCubeIcon, PlusIcon, SnowflakeIcon, SparklesIcon, SunIcon } from "@/components/icons"; +import { CameraIcon, FolderIcon, IceCubeIcon, PlusIcon, SnowflakeIcon, SparklesIcon, SunIcon } from "@/components/icons"; import { Button, ProgressBar } from "@/components/ui"; type Phase = "idle" | "preparing" | "loading" | "error"; @@ -321,23 +321,39 @@ export function UploadScreen() {

- {/* The other thing you can bring here: an assignment. */} - - + - - - - {t("homework.entry")} - {t("homework.nav")} → - - - + + + + + {t("actionStudyDeck")} + + + + + + + + {t("actionHomework")} + + + {error ? ( @@ -676,7 +692,7 @@ export function UploadScreen() { @@ -705,7 +721,7 @@ export function UploadScreen() { {option.icon} {t(option.labelKey)} - {t(option.blurbKey)} + {t(option.blurbKey)} ); })} diff --git a/lib/i18n-dict.ts b/lib/i18n-dict.ts index 337951e..75d59b4 100644 --- a/lib/i18n-dict.ts +++ b/lib/i18n-dict.ts @@ -172,7 +172,6 @@ const en: Record = { "homework.title": "Make my homework", "homework.subtitle": "Paste the assignment, snap a photo or add a document — then choose whether I should just do it, or guide you through it.", - "homework.entry": "Got homework instead of notes?", "homework.source.title": "1. The assignment", "homework.source.help": "Paste its text, drop photos, or add a document.", "homework.source.textLabel": "Assignment text", @@ -224,6 +223,12 @@ const en: Record = { "homework.history.openTitle": "Open “{title}”", "homework.history.deleteConfirm": "Delete this result?", + /* quick actions (library empty state + /create switcher) ----------- */ + "emptyStateCreateDeck": "Create interactive test", + "emptyStateHomework": "Help me with my homework", + "actionStudyDeck": "Study Deck & Quizzes", + "actionHomework": "Homework Solver", + /* library --------------------------------------------------------- */ "library.title": "Your icebox", "library.subtitle": "Decks frozen from your notes, saved in this browser.", @@ -235,7 +240,6 @@ const en: Record = { "library.deckMoved": "Deck moved.", "library.deckMovedUnorganized": "Deck moved to Unorganized.", "library.noDecks": "No decks yet", - "library.makeFirst": "Make your first deck", "library.emptyBody": "Freeze a page of notes into a feed of flashcards and quizzes.", "library.emptyHint": "Using your own Ollama models —", "library.emptySettings": "check the connection in Settings", @@ -752,7 +756,6 @@ const cs: Record = { "homework.title": "Udělej mi úkol", "homework.subtitle": "Vlož zadání, vyfoť ho nebo přidej dokument — a pak si vyber, jestli to mám rovnou udělat, nebo tě tím provést.", - "homework.entry": "Máš místo poznámek úkol?", "homework.source.title": "1. Zadání", "homework.source.help": "Vlož jeho text, přetáhni fotky nebo přidej dokument.", "homework.source.textLabel": "Text zadání", @@ -804,6 +807,12 @@ const cs: Record = { "homework.history.openTitle": "Otevřít „{title}“", "homework.history.deleteConfirm": "Smazat tento výsledek?", + /* quick actions (library empty state + /create switcher) ----------- */ + "emptyStateCreateDeck": "Vytvořit interaktivní test", + "emptyStateHomework": "Pomoct s úkolem", + "actionStudyDeck": "Studijní balíček a testy", + "actionHomework": "Řešitel úkolů", + /* library --------------------------------------------------------- */ "library.title": "Tvoje mraznička", "library.subtitle": "Sady zmrazené z tvých poznámek, uložené v tomto prohlížeči.", @@ -815,7 +824,6 @@ const cs: Record = { "library.deckMoved": "Sada přesunuta.", "library.deckMovedUnorganized": "Sada přesunuta do Nezařazených.", "library.noDecks": "Zatím žádné sady", - "library.makeFirst": "Vytvoř si první sadu", "library.emptyBody": "Zmraz stránku poznámek do feedu kartiček a kvízů.", "library.emptyHint": "S tvými vlastními modely Ollama —", "library.emptySettings": "zkontroluj připojení v Nastavení", diff --git a/public/sw.js b/public/sw.js index 24dc175..717801b 100644 --- a/public/sw.js +++ b/public/sw.js @@ -9,7 +9,7 @@ * * Bumping CACHE_VERSION is how a new deploy invalidates old assets. */ -const CACHE_VERSION = "freezmo-v6"; +const CACHE_VERSION = "freezmo-v8"; const SHELL_CACHE = `${CACHE_VERSION}-shell`; const ASSET_CACHE = `${CACHE_VERSION}-assets`;