Files
study-bible-project/src/hooks/useOutlineShareLink.js
T
nmemmertandClaude Sonnet 5.5 54cb1c217d
Build and Push Docker Image / build-and-push (push) Successful in 6m47s
Invite-only sign-up, present mode, series, handouts, templates, dictation, progress, sharing
- Admin: sign-up Open / Invite only / Closed with single-use invite links
- Present mode for scripts (auto-scroll) and outlines (step through, pace vs planned minutes)
- Series: group studies on the dashboard, filter by series, calendar file for a study's sessions
- Lesson handout: printable page per session (passage, outline, questions, writing lines)
- Save a chunk's notes as your own study template (synced)
- Voice dictation for notes and scripts (browser speech recognition)
- Reading progress: map of the 66 books and a calendar of days read, synced and merged across devices
- Export highlights and bookmarks as Markdown or Word, grouped by named colour
- Verse of the day push to the ntfy topic (needs IQBIBLE_API_KEY)
- Sharing: co-teacher editing via single-use invite links; read-only links can expire and take a passcode

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 10:26:43 -04:00

48 lines
2.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// The read-only link to a study's outlines: status, create, turn off, copy. A separate link from the
// whole-study share link, and it only ever shows outlines.
import { useEffect, useState } from 'react';
import { disableOutlineSharing, enableOutlineSharing, getOutlineShareStatus } from '../syncService.js';
export function useOutlineShareLink(projectId, enabled = true) {
const [token, setToken] = useState(null);
const [expiresAt, setExpiresAt] = useState(null);
const [hasPasscode, setHasPasscode] = useState(false);
const [state, setState] = useState('loading'); // 'loading' | 'ready' | 'unavailable' (no account / server)
const [busy, setBusy] = useState(false);
const [error, setError] = useState('');
useEffect(() => {
setToken(null);
setError('');
if (!projectId || !enabled) return undefined;
let active = true;
setState('loading');
getOutlineShareStatus(projectId).then((result) => {
if (!active) return;
if (result.ok) { setToken(result.data.shareToken); setExpiresAt(result.data.expiresAt ?? null); setHasPasscode(!!result.data.hasPasscode); setState('ready'); } else setState('unavailable');
});
return () => { active = false; };
}, [projectId, enabled]);
const url = token ? `${window.location.origin}${window.location.pathname}?outline=${token}` : '';
// Creates the link, or changes its rules: { expiresInDays?: number | null, passcode?: string | null }
const create = async (options = {}) => {
setBusy(true);
setError('');
const result = await enableOutlineSharing(projectId, options);
setBusy(false);
if (result.ok) { setToken(result.data.shareToken); setExpiresAt(result.data.expiresAt ?? null); setHasPasscode(!!result.data.hasPasscode); }
else setError(result.status === 404 ? 'Your study hasn’t synced to your account yet. Wait a moment and try again.' : 'Couldn’t create the link. Check your connection and try again.');
};
const turnOff = async () => {
setBusy(true);
const result = await disableOutlineSharing(projectId);
setBusy(false);
if (result.ok) { setToken(null); setExpiresAt(null); setHasPasscode(false); } else setError('Couldn’t turn the link off. Try again.');
};
return { token, url, expiresAt, hasPasscode, state, busy, error, create, turnOff };
}