Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add autoplay #608

Merged
merged 3 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/components/molecules/player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import IconPlay from '~public/img/icons/icon-play-large.svg';
import useGlobalSpaceDown from '~src/lib/hooks/useGlobalSpaceDown';
import useIsAuthenticated from '~src/lib/hooks/useIsAuthenticated';
import usePlaybackSession from '~src/lib/hooks/usePlaybackSession';
import isServerSide from '~src/lib/isServerSide';

import { PlaybackContext } from '../templates/andPlaybackContext';
import { PlayerFragment } from './__generated__/player';
Expand Down Expand Up @@ -79,6 +80,10 @@ const Player = ({
}
}, []);

useEffect(() => {
if (!isServerSide()) session.play();
}, []); // eslint-disable-line react-hooks/exhaustive-deps

const iconColor = isBackgroundColorDark(backgroundColor)
? BaseColors.WHITE
: BaseColors.DARK;
Expand Down
23 changes: 15 additions & 8 deletions src/components/organisms/passageNavigation/bookGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import clsx from 'clsx';
import React from 'react';

import { Book } from '.';
import { PassageNavigationFragment } from './__generated__/index';
import ChapterGrid from './chapterGrid';
import ChapterGrid, { ChapterId } from './chapterGrid';
import styles from './index.module.scss';

type Props = {
books: Array<PassageNavigationFragment>;
selectedBook: string | number | null;
selectBook: (id: string | number | null) => void;
selectedBook: Book;
selectBook: (book: Book) => void;
chapterId: ChapterId;
};

export default function BookGrid({ books, selectedBook, selectBook }: Props) {
export default function BookGrid({
books,
selectedBook,
selectBook,
chapterId,
}: Props) {
return (
<ul className={clsx(styles.books, styles.grid)}>
{books.map((book) => {
Expand All @@ -22,15 +29,15 @@ export default function BookGrid({ books, selectedBook, selectBook }: Props) {
<li
key={book.id}
className={clsx(styles.book, {
active: book.id === selectedBook,
active: book.id === selectedBook.id,
})}
>
<button onClick={() => selectBook(book.id)}>
<button onClick={() => selectBook(book)}>
{book.title.replace(' ', '').substring(0, 3)}
</button>
</li>
{book.id === selectedBook && chapters && (
<ChapterGrid chapters={chapters} />
{book.id === selectedBook.id && chapters && (
<ChapterGrid chapters={chapters} chapterId={chapterId} />
)}
</>
);
Expand Down
23 changes: 15 additions & 8 deletions src/components/organisms/passageNavigation/bookList.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import clsx from 'clsx';
import React from 'react';

import { Book } from '.';
import { PassageNavigationFragment } from './__generated__/index';
import ChapterGrid from './chapterGrid';
import ChapterGrid, { ChapterId } from './chapterGrid';
import styles from './index.module.scss';

type Props = {
books: Array<PassageNavigationFragment>;
selectedBook: string | number | null;
selectBook: (id: string | number | null) => void;
selectedBook: Book;
selectBook: (book: Book) => void;
chapterId: ChapterId;
};

export default function BookList({ books, selectedBook, selectBook }: Props) {
export default function BookList({
books,
selectedBook,
selectBook,
chapterId,
}: Props) {
return (
<ul className={clsx(styles.books)}>
{books.map((book) => {
Expand All @@ -22,13 +29,13 @@ export default function BookList({ books, selectedBook, selectBook }: Props) {
<li
key={book.id}
className={clsx(styles.book, {
active: book.id === selectedBook,
active: book.id === selectedBook.id,
})}
>
<button onClick={() => selectBook(book.id)}>{book.title}</button>
<button onClick={() => selectBook(book)}>{book.title}</button>
</li>
{book.id === selectedBook && chapters && (
<ChapterGrid chapters={chapters} />
{book.id === selectedBook.id && chapters && (
<ChapterGrid chapters={chapters} chapterId={chapterId} />
)}
</>
);
Expand Down
15 changes: 4 additions & 11 deletions src/components/organisms/passageNavigation/chapterGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import React from 'react';

import Link from '~components/atoms/linkWithoutPrefetch';
import { useLocalStorage } from '~src/lib/hooks/useLocalStorage';

import { PassageNavigationFragment } from './__generated__/index';
import styles from './index.module.scss';

type Chapter = NonNullable<PassageNavigationFragment['recordings']['nodes']>[0];
type ChapterId = Chapter['id'];
export type ChapterId = Chapter['id'] | null;

type Props = {
chapters: Array<Chapter>;
chapterId: ChapterId;
};

export default function ChapterGrid({ chapters }: Props) {
const [selectedChapterId] = useLocalStorage<ChapterId | null>(
'selectedChapterId',
null,
);

export default function ChapterGrid({ chapters, chapterId }: Props) {
return (
<li className={styles.chaptersWrapper}>
<ul className={styles.chapters}>
Expand All @@ -27,9 +22,7 @@ export default function ChapterGrid({ chapters }: Props) {
return (
<li key={n} className={styles.chapter}>
<Link
className={
chapter.id === selectedChapterId ? styles.active : ''
}
className={chapter.id === chapterId ? styles.active : ''}
href={chapter.canonicalPath}
>
{n}
Expand Down
128 changes: 36 additions & 92 deletions src/components/organisms/passageNavigation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Button from '~src/components/molecules/button';
import Dropdown from '~src/components/molecules/dropdown';
import IconButton from '~src/components/molecules/iconButton';
import { GetAudiobibleIndexDataQuery } from '~src/containers/bible/__generated__';
import { BaseColors } from '~src/lib/constants';
import { BaseColors, BIBLE_BOOKS } from '~src/lib/constants';
import { getBibleAcronym } from '~src/lib/getBibleAcronym';
import { useLocalStorage } from '~src/lib/hooks/useLocalStorage';

Expand All @@ -20,93 +20,33 @@ import styles from './index.module.scss';
export type Version = NonNullable<
GetAudiobibleIndexDataQuery['collections']['nodes']
>[0];

type Book = NonNullable<Version['sequences']['nodes']>[0];
type Chapter = NonNullable<Book['recordings']['nodes']>[0];

type BookId = string | number | null;
type ChapterId = string | number;
export type Book = NonNullable<Version['sequences']['nodes']>[0];
export type Chapter = NonNullable<Book['recordings']['nodes']>[0];

type Props = {
versions: Array<Version>;
chapterId?: ChapterId;
chapter?: Chapter;
children?: ReactNode;
};

// FIXME
const OT = [
'genesis',
'exodus',
'leviticus',
'numbers',
'deuteronomy',
'joshua',
'judges',
'ruth',
'1 samuel',
'2 samuel',
'1 kings',
'2 kings',
'1 chronicles',
'2 chronicles',
'ezra',
'nehemiah',
'esther',
'job',
'psalms',
'proverbs',
'ecclesiastes',
'song of solomon',
'isaiah',
'jeremiah',
'lamentations',
'ezekiel',
'daniel',
'hosea',
'joel',
'amos',
'obadiah',
'jonah',
'micah',
'nahum',
'habakkuk',
'zephaniah',
'haggai',
'zechariah',
'malachi',
];

function getBibleData(
function resolveChapterPath(
versions: Array<Version>,
chapterId: ChapterId,
chapter: Chapter,
): [Version, Book, Chapter] {
for (const version of versions) {
for (const book of version.sequences.nodes || []) {
const chapter = book.recordings.nodes?.find((r) => r.id === chapterId);
if (chapter) {
const found = book.recordings.nodes?.some((r) => r.id === chapter.id);
if (found) {
return [version, book, chapter];
}
}
}
throw Error("Couldn't find the chapter");
}

function getLabelText(
versions: Array<Version>,
chapterId: ChapterId | null,
): string {
if (chapterId) {
const [_version, _book, chapter] = getBibleData(versions, chapterId);

return `${chapter.title}`;
}

return `Bible`;
}

export default function PassageNavigation({
versions,
chapterId,
chapter,
children,
}: Props): ReactNode {
const [open, setOpen] = useState<boolean>(!children);
Expand All @@ -115,22 +55,26 @@ export default function PassageNavigation({

const books = selectedVersion.sequences.nodes || [];

const [selectedBookId, setSelectedBookId] = useState<BookId>(books[0].id);
const [selectedBook, setSelectedBook] = useState<Book>(books[0]);

const [selectedChapterId, setSelectedChapterId] =
useLocalStorage<ChapterId | null>('selectedChapterId', chapterId || null);
const [selectedChapterId, setSelectedChapterId] = useLocalStorage(
'selectedChapterId',
chapter?.id || null,
);

useEffect(() => {
if (chapterId !== undefined) {
setSelectedChapterId(chapterId);
}
if (chapter) {
setSelectedChapterId(chapter.id);

if (selectedChapterId !== null) {
const [version, book] = getBibleData(versions, selectedChapterId);
const [version, book] = resolveChapterPath(versions, chapter);
setSelectedVersion(version);
setSelectedBookId(book.id);
setSelectedBook(book);
}
}, [selectedChapterId, chapterId, setSelectedChapterId, versions]);
}, [chapter, versions, setSelectedChapterId]);

useEffect(() => {
setOpen(false);
}, [selectedChapterId]);

const [selectedView, setSelectedView] = useLocalStorage<'grid' | 'list'>(
'passageNavLayout',
Expand All @@ -140,10 +84,7 @@ export default function PassageNavigation({
return (
<div className={styles.base}>
<div className={styles.hat} onClick={() => setOpen(!open)}>
<BibleVersionTypeLockup
unpadded
label={getLabelText(versions, selectedChapterId)}
/>
<BibleVersionTypeLockup unpadded label={chapter?.title || 'Bible'} />
<a className={styles.historyButton} href="https://www.example.com">
<FormattedMessage id="bibles__history" defaultMessage="History" />
</a>
Expand Down Expand Up @@ -214,24 +155,27 @@ export default function PassageNavigation({
{selectedView === 'list' ? (
<BookList
books={books}
selectedBook={selectedBookId}
selectBook={setSelectedBookId}
selectedBook={selectedBook}
selectBook={setSelectedBook}
chapterId={selectedChapterId}
/>
) : (
<>
<BookGrid
books={books.filter((book) =>
OT.includes(book.title.toLocaleLowerCase()),
BIBLE_BOOKS.slice(0, 39).includes(book.title),
)}
selectedBook={selectedBookId}
selectBook={setSelectedBookId}
selectedBook={selectedBook}
selectBook={setSelectedBook}
chapterId={selectedChapterId}
/>
<BookGrid
books={books.filter(
(book) => !OT.includes(book.title.toLocaleLowerCase()),
books={books.filter((book) =>
BIBLE_BOOKS.slice(39).includes(book.title),
)}
selectedBook={selectedBookId}
selectBook={setSelectedBookId}
selectedBook={selectedBook}
selectBook={setSelectedBook}
chapterId={selectedChapterId}
/>
</>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/organisms/recording.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export function Recording(
</Head>

{'data' in params ? (
<PassageNavigation versions={params.data} chapterId={recording.id}>
<PassageNavigation versions={params.data} chapter={recording}>
<RecordingInner
recording={recording}
overrideSequence={overrideSequence}
Expand Down
Loading