Extract project header, share link, exports, and auth status
- ProjectHeader component replaces the headerButtons JSX in context; it owns the export menu and share panel state. - useShareLink (share status/enable/revoke/copy) and useSharedView (?share= read-only view, now used directly by the router). - utils/projectExport: HTML/Markdown/DOCX download and print-to-PDF. - AuthStatus component replaces the authStatus JSX in context. - Pages import wordStudy helpers directly instead of via context. - Remove dead copyPronunciationGuide (PronunciationPage has its own). - Tests: Markdown export, enabling a share link, the ?share= view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
365fb1b567
commit
4b14b3fbe6
14 files changed
+425
-393
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useApp } from '../context/AppContext.js';
|
||||
import AuthStatus from '../components/AuthStatus.jsx';
|
||||
import { buildExportHtml } from '../utils/bibleUtils.jsx';
|
||||
import {
|
||||
adminListUsers,
|
||||
@@ -11,7 +12,7 @@ import {
|
||||
} from '../syncService.js';
|
||||
|
||||
export default function AdminPage() {
|
||||
const { authUser, authStatus, goHome } = useApp();
|
||||
const { authUser, goHome } = useApp();
|
||||
const [adminTab, setAdminTab] = useState('users'); // 'users' | 'projects'
|
||||
const [adminUsers, setAdminUsers] = useState([]);
|
||||
const [adminProjects, setAdminProjects] = useState([]);
|
||||
@@ -82,7 +83,7 @@ export default function AdminPage() {
|
||||
>
|
||||
← Back
|
||||
</button>
|
||||
{authStatus}
|
||||
<AuthStatus />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useApp } from '../context/AppContext.js';
|
||||
import AuthStatus from '../components/AuthStatus.jsx';
|
||||
import {
|
||||
bookOptions,
|
||||
CHAPTER_COUNTS,
|
||||
@@ -11,7 +12,6 @@ import { loadProjectById } from '../utils/projectStorage.js';
|
||||
|
||||
export default function HomePage() {
|
||||
const {
|
||||
authStatus,
|
||||
autoRestoredCount,
|
||||
staleLocalProjects,
|
||||
projectIndex,
|
||||
@@ -109,7 +109,7 @@ export default function HomePage() {
|
||||
>
|
||||
+ New Project
|
||||
</button>
|
||||
{authStatus}
|
||||
<AuthStatus />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useState } from 'react';
|
||||
import { useApp } from '../context/AppContext.js';
|
||||
import AuthStatus from '../components/AuthStatus.jsx';
|
||||
import { useAvailableTranslations } from '../hooks/useAvailableTranslations.js';
|
||||
import { bookOptions, makeId, parseBibleChapter } from '../utils/bibleUtils.jsx';
|
||||
import { parseEpisodeListDocx, parseEpisodePassage } from '../utils/importParsers.js';
|
||||
|
||||
export default function ImportPage() {
|
||||
const { authStatus, setCurrentPage, setProject, setActiveChapterIndex } = useApp();
|
||||
const { setCurrentPage, setProject, setActiveChapterIndex } = useApp();
|
||||
const availableTranslations = useAvailableTranslations();
|
||||
const [importBookAbbrev, setImportBookAbbrev] = useState(bookOptions[0].abbrev);
|
||||
const [importTranslation, setImportTranslation] = useState('BSB');
|
||||
@@ -165,7 +166,7 @@ export default function ImportPage() {
|
||||
>
|
||||
← Back
|
||||
</button>
|
||||
{authStatus}
|
||||
<AuthStatus />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useState, useEffect, useRef, useMemo, useDeferredValue } from 'react';
|
||||
import { useApp } from '../context/AppContext.js';
|
||||
import { formatCrossRef, speakOriginalWord } from '../utils/wordStudy.js';
|
||||
import AuthStatus from '../components/AuthStatus.jsx';
|
||||
import { bookOptions, BookmarkIcon, CopyIcon } from '../utils/bibleUtils.jsx';
|
||||
import DrawCanvas from './DrawCanvas.jsx';
|
||||
|
||||
@@ -7,7 +9,6 @@ const NO_STROKES = []; // stable fallback so DrawCanvas doesn't redraw every ren
|
||||
|
||||
export default function ReaderPage() {
|
||||
const {
|
||||
authStatus,
|
||||
goHome,
|
||||
readerBookAbbrev,
|
||||
readerChapter, setReaderChapter,
|
||||
@@ -41,9 +42,7 @@ export default function ReaderPage() {
|
||||
handlePlayReaderAudio,
|
||||
handleToggleReaderAudioPause,
|
||||
handleStopBookAudio,
|
||||
speakOriginalWord,
|
||||
copyVerse,
|
||||
formatCrossRef,
|
||||
setReaderCrossRefs,
|
||||
readerInkByPage,
|
||||
updateReaderPageInk,
|
||||
@@ -270,7 +269,7 @@ export default function ReaderPage() {
|
||||
>
|
||||
← Back to Studies
|
||||
</button>
|
||||
{authStatus}
|
||||
<AuthStatus />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { useApp } from '../context/AppContext.js';
|
||||
import AuthStatus from '../components/AuthStatus.jsx';
|
||||
import {
|
||||
startMfaSetup,
|
||||
confirmMfaSetup,
|
||||
@@ -11,7 +12,6 @@ import {
|
||||
export default function SettingsPage() {
|
||||
const {
|
||||
authUser, setAuthUser,
|
||||
authStatus,
|
||||
goHome,
|
||||
} = useApp();
|
||||
const [mfaSetup, setMfaSetup] = useState(null); // { secret, qrCodeDataUrl } while setup is in progress
|
||||
@@ -123,7 +123,7 @@ export default function SettingsPage() {
|
||||
>
|
||||
← Back
|
||||
</button>
|
||||
{authStatus}
|
||||
<AuthStatus />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useApp } from '../context/AppContext.js';
|
||||
import ProjectHeader from '../components/ProjectHeader.jsx';
|
||||
import { useAvailableTranslations } from '../hooks/useAvailableTranslations.js';
|
||||
import { bookOptions, formatChunkReference } from '../utils/bibleUtils.jsx';
|
||||
|
||||
@@ -81,7 +82,6 @@ function SetupForm({ setup, availableTranslations, titleEdited, loadingChapter,
|
||||
|
||||
export default function SetupPage() {
|
||||
const {
|
||||
headerButtons,
|
||||
project,
|
||||
setup,
|
||||
titleEdited, setTitleEdited,
|
||||
@@ -125,7 +125,7 @@ export default function SetupPage() {
|
||||
{project ? project.title : 'New Study'}
|
||||
</h1>
|
||||
</div>
|
||||
{headerButtons}
|
||||
<ProjectHeader loading={loadingChapter} />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { createPortal } from 'react-dom';
|
||||
import DOMPurify from 'dompurify';
|
||||
import { useApp } from '../context/AppContext.js';
|
||||
import { buildGreekDefinitionHtml, externalLookupLinks, speakOriginalWord } from '../utils/wordStudy.js';
|
||||
import ProjectHeader from '../components/ProjectHeader.jsx';
|
||||
import { STUDY_TABS, COMMENTARY_OPTIONS, NT_BOOK_NUMBER, formatChunkReference, CrossRefChip } from '../utils/bibleUtils.jsx';
|
||||
|
||||
export default function StudyPage() {
|
||||
const {
|
||||
headerButtons,
|
||||
project,
|
||||
allChunks,
|
||||
selectedChunk,
|
||||
@@ -50,9 +51,6 @@ export default function StudyPage() {
|
||||
suggestGreekWordsForChunk,
|
||||
suggestHebrewWordsForChunk,
|
||||
confirmSuggestWords,
|
||||
speakOriginalWord,
|
||||
externalLookupLinks,
|
||||
buildGreekDefinitionHtml,
|
||||
loadVerseText,
|
||||
importFinalScriptDocx,
|
||||
formatChunkReference: _ignored,
|
||||
@@ -71,7 +69,7 @@ export default function StudyPage() {
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{headerButtons}
|
||||
<ProjectHeader />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
Reference in new issue
Block a user