Skip to content

Commit

Permalink
added support for startVerse URL parameter for better offline support (
Browse files Browse the repository at this point in the history
  • Loading branch information
marwan authored Jan 25, 2025
1 parent 741f034 commit a0fde75
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/components/display/verses/VerseOptionButtons.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
<div class="flex flex-row w-full space-x-2">
<!-- verse key -->
<div class="flex flex-row space-x-2">
<a href={$__currentPage === 'chapter' ? `#${key}` : `/${chapter}/${verse}`} class={verseKeyClasses}>
<a href={$__currentPage === 'chapter' ? `#${key}` : `/${chapter}?startVerse=${verse}`} class={verseKeyClasses}>
{#if $__currentPage === 'chapter'}
<div class="text-xs">{key}</div>
{:else}
Expand Down
2 changes: 1 addition & 1 deletion src/components/display/verses/VerseOptionsDropdown.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@

<!-- mode change buttons -->
{#if $__currentPage === 'mushaf'}
<DropdownItem class={dropdownItemClasses} href="/{chapter}/{verse}" on:click={() => window.umami.track('Chapter Mode Button')}>
<DropdownItem class={dropdownItemClasses} href="/{chapter}?startVerse={verse}" on:click={() => window.umami.track('Chapter Mode Button')}>
<ChapterMode />
<span>{term('chapter')} Mode</span>
</DropdownItem>
Expand Down
15 changes: 15 additions & 0 deletions src/components/display/verses/modes/Chapter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
7: { component: TranslationTransliteration }
};
const urlParams = new URLSearchParams(window.location.search);
const startVerseParam = urlParams.get('startVerse');
const chapterTotalVerses = quranMetaData[$__chapterNumber].verses;
let Chapter; // for the "Chapter" component
let versesLoadType; // previous/next
Expand Down Expand Up @@ -63,6 +65,19 @@
endVerse: nextVersesEnd
};
}
// If the startVerse parameter was set, overide the current start and end verse
if (
startVerseParam !== null && // Ensure it's not null
startVerseParam !== undefined && // Ensure it's not undefined
startVerseParam.trim() !== '' && // Ensure it's not empty
!isNaN(startVerseParam) // Ensure it's a valid number
) {
nextVersesProps = {
startVerse: Number(startVerseParam),
endVerse: Number(startVerseParam)
};
}
</script>

{#if $__currentPage === 'chapter' && $__chapterData}
Expand Down
11 changes: 3 additions & 8 deletions src/components/display/verses/modes/Individual.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import { isValidVerseKey } from '$utils/validateKey';
import { goto } from '$app/navigation';
import { inview } from 'svelte-inview';
import { onMount } from 'svelte';
import { term } from '$utils/terminologies';
import { selectableDisplays } from '$data/options';
import { quranMetaData } from '$data/quranMeta';
Expand Down Expand Up @@ -66,7 +65,9 @@
keyToStartWith = params.get('startKey');
if (isValidVerseKey(keyToStartWith)) {
goto(removeParam('startKey'), { replaceState: false });
const parsedUrl = new URL(window.location.href);
parsedUrl.searchParams.delete('startKey');
goto(parsedUrl.toString(), { replaceState: false });
startIndex = getIndexOfKey(keyToStartWith);
endIndex = keysArrayLength > maxIndexesAllowedToRender ? startIndex + maxIndexesAllowedToRender : keysArrayLength;
Expand Down Expand Up @@ -135,12 +136,6 @@
return index;
}
function removeParam(param) {
const parsedUrl = new URL(window.location.href);
parsedUrl.searchParams.delete(param);
return parsedUrl.toString();
}
function versesRendered() {
renderedVerses += 1;
Expand Down
6 changes: 3 additions & 3 deletions src/components/ui/HomepageTabs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
{@const [bookmarkChapter, bookmarkVerse] = bookmark.split(':').map(Number)}

<div class="flex flex-row space-x-2">
<a href="{bookmarkChapter}/{bookmarkVerse}" class="!justify-start {cardInnerClasses} w-full flex-col">
<a href="{bookmarkChapter}?startVerse={bookmarkVerse}" class="!justify-start {cardInnerClasses} w-full flex-col">
<div class="text-sm truncate max-w-[28vw] md:max-w-[115px]">{quranMetaData[bookmarkChapter].transliteration} ({bookmark})</div>

{#if extrasActiveTab === 1 && totalBookmarks > 0}
Expand Down Expand Up @@ -168,7 +168,7 @@
{:else}
<div class="{cardGridClasses} grid-cols-2 md:!grid-cols-4">
{#each Object.entries($__userNotes) as [verse, note]}
<a href="{verse.split(':')[0]}/{verse.split(':')[1]}" class="!justify-start {cardInnerClasses} w-full flex-col">
<a href="{verse.split(':')[0]}?startVerse={verse.split(':')[1]}" class="!justify-start {cardInnerClasses} w-full flex-col">
<div class="text-sm truncate max-w-[30vw] md:max-w-[115px]">{quranMetaData[verse.split(':')[0]].transliteration} ({verse})</div>
<span class="text-xs truncate opacity-70">{note.note}</span>
</a>
Expand Down Expand Up @@ -223,7 +223,7 @@
{#if lastReadExists}
{@const lastReadChapter = $__lastRead.chapter}
{@const lastReadVerse = $__lastRead.verse}
<a href="/{lastReadChapter}/{lastReadVerse}" class="{continueReadingButtonClasses} mb-2 truncate w-full" on:click={() => window.umami.track('Continue Chapter Button')}>
<a href="/{lastReadChapter}?startVerse={lastReadVerse}" class="{continueReadingButtonClasses} mb-2 truncate w-full" on:click={() => window.umami.track('Continue Chapter Button')}>
<span class="invisible chapter-icons mb-1 text-2xl md:text-3xl" style="color: {window.theme('icon')}">{@html `&#xE9${quranMetaData[lastReadChapter].icon};`}</span>
<span class="truncate">
Continue Reading:
Expand Down
4 changes: 2 additions & 2 deletions src/components/ui/Modals/QuranNavigationModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
<span class="text-xs font-semibold">Current {term('chapter')}</span>
<div class={linkClasses}>
<span>{@html '&#10230'}</span>
<a href="/{$__chapterNumber}/{value}" class={linkTextClasses}>{term('verse')} {value}</a>
<a href="/{$__chapterNumber}?startVerse={value}" class={linkTextClasses}>{term('verse')} {value}</a>
</div>
</div>
{/if}
Expand Down Expand Up @@ -302,7 +302,7 @@
{#key $__chapterNumber}
{#each { length: maxVersesToLoad } as _, verse}
<li>
<a href="/{$__chapterNumber}/{verse + 1}" on:click={() => __pageURL.set(Math.random())}>
<a href="/{$__chapterNumber}?startVerse={verse + 1}">
<div class={listItemClasses}>{term('verse')} {verse + 1}</div>
</a>
</li>
Expand Down
4 changes: 2 additions & 2 deletions src/data/quranMeta.js
Original file line number Diff line number Diff line change
Expand Up @@ -1011,8 +1011,8 @@ export const juzMeta = [
];

export const mostRead = [
{ id: 1, chapter: 2, verses: 'Verse 255', title: "Whoever recites the 'verse of the Throne' after every prescribed prayer, there will be nothing standing between him and entry into Paradise but his death.", url: '/2/255' },
{ id: 2, chapter: 2, verses: 'Verses 285-286', title: 'If anyone recited two verses from the last of Surah al-Baqarah at night, they will be sufficient for him.', url: '/2/285-286' },
{ id: 1, chapter: 2, verses: 'Verse 255', title: "Whoever recites the 'verse of the Throne' after every prescribed prayer, there will be nothing standing between him and entry into Paradise but his death.", url: '/2?startVerse=255' },
{ id: 2, chapter: 2, verses: 'Verses 285-286', title: 'If anyone recited two verses from the last of Surah al-Baqarah at night, they will be sufficient for him.', url: '/2?startVerse=285' },
{ id: 3, chapter: 18, verses: 'Verses 1-10', title: 'Whoever memorizes ten verses from the beginning of Surat al-Kahf will be immune to the False Messiah.', url: '/18/1-10' },
{ id: 4, chapter: 36, verses: 'Verses 1-83', title: 'Everything has a heart, and the heart of the Quran is Yaseen; whoever reads it, it is as if he has read the Quran ten times.', url: '/36' },
{ id: 5, chapter: 55, verses: 'Verses 1-78', title: 'Everything has an adornment, and the adornment of Quran is Surah Ar Rahman.', url: '/55' },
Expand Down
4 changes: 3 additions & 1 deletion src/routes/morphology/[key]/Table.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@
</thead>
<tbody>
{#each Array.from(Array(lastWordToLoad + 1).keys()).slice(1) as word}
{@const wordChapter = wordData[word - 1].key.split(':')[0]}
{@const wordVerse = wordData[word - 1].key.split(':')[1]}
<tr class="{window.theme('bgMain')} border-b {window.theme('border')} {window.theme('hover')}">
<td class="px-6 py-4"> {word} </td>
<td class="px-6 py-4 arabic-font-{$__fontType} text-xl md:text-2xl"> {wordData[word - 1].arabic} </td>
<td class="px-6 py-4"> {wordData[word - 1].translation} </td>
<td class="px-6 py-4"> {wordData[word - 1].transliteration} </td>
<td class="px-6 py-4"> <a class={linkClasses} href="/{wordData[word - 1].key.split(':')[0]}/{wordData[word - 1].key.split(':')[1]}">{wordData[word - 1].key.split(':')[0]}:{wordData[word - 1].key.split(':')[1]}</a> </td>
<td class="px-6 py-4"> <a class={linkClasses} href="/{wordChapter}?startVerse={wordVerse}">{wordChapter}:{wordVerse}</a> </td>
<td class="px-6 py-4"> <a class={linkClasses} href="/morphology/{wordData[word - 1].key}">{wordData[word - 1].key}</a> </td>
</tr>
{/each}
Expand Down
17 changes: 14 additions & 3 deletions src/utils/parseURL.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ import { quranMetaData } from '$data/quranMeta';
// /<chapter>/<verse>-<endVerse> (e.g., /2/285-286)
// /<chapter>-<verse> (e.g., /2-255)
// /<chapter>.<verse> (e.g., /2.255)
// And now supports URL parameter ?startVerse=<verse>
export function parseURL() {
const chapterTotalVerses = quranMetaData[get(__chapterNumber)].verses;
const url = window.location.pathname;
const hash = window.location.hash.slice(1); // Get the hash part of the URL
const queryParams = new URLSearchParams(window.location.search);
const startVerseParam = parseInt(queryParams.get('startVerse'), 10);

let startVerse, endVerse;

// Remove any leading slash and split the URL by '/', '-', ':', or '.'
Expand Down Expand Up @@ -44,21 +48,28 @@ export function parseURL() {
}
}

// check for hash-based verse
// Override startVerse if ?startVerse parameter is present
if (!isNaN(startVerseParam)) {
const chapter = parseInt(urlParts[0], 10) || 1;
startVerse = Math.max(1, Math.min(startVerseParam, quranMetaData[chapter].verses));
endVerse = startVerse; // If only startVerse is provided, set endVerse to the same
}

// Check for hash-based verse
if (hash) {
const hashVerse = parseInt(hash, 10);
if (!isNaN(hashVerse)) {
startVerse = hashVerse;
endVerse = hashVerse;

// limit hash-based verse to valid range
// Limit hash-based verse to valid range
const chapter = parseInt(urlParts[0], 10) || 1;
startVerse = Math.max(1, Math.min(startVerse, quranMetaData[chapter].verses));
endVerse = Math.max(startVerse, Math.min(endVerse, quranMetaData[chapter].verses));
}
}

// fallback for URLs without valid verses or chapters
// Fallback for URLs without valid verses or chapters
if (!startVerse || !endVerse) {
startVerse = 1;
endVerse = chapterTotalVerses;
Expand Down
8 changes: 4 additions & 4 deletions src/views/Chapter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { buttonClasses } from '$data/commonClasses';
import { goto } from '$app/navigation';
import { term } from '$utils/terminologies';
import { page } from '$app/stores';
// Export data and verse range variables
export let data, startVerse, endVerse;
Expand Down Expand Up @@ -48,7 +49,7 @@
__firstVerseOnPage.set(startVerse);
// Check for store updates (page URL, display type, font type, word translation, transliteration)
if ($__pageURL || $__displayType || $__fontType || $__wordTranslation || $__wordTransliteration) {
if ($page.url.href || $__displayType || $__fontType || $__wordTranslation || $__wordTransliteration) {
// Do nothing except re-run the block
}
}
Expand All @@ -69,12 +70,11 @@
}
}
// Function to load the previous set of verses
// Function to load the previous verse
function loadPreviousVerse() {
const versesOnPage = document.getElementsByClassName('verse');
const firstVerseOnPage = +versesOnPage[0].id.split(':')[1];
const lastVerseOnPage = +versesOnPage[versesOnPage.length - 1].id.split(':')[1];
goto(`/${$__chapterNumber}/${+firstVerseOnPage - 1}-${+lastVerseOnPage}`, { replaceState: false });
goto(`?startVerse=${+firstVerseOnPage - 1}`, { replaceState: false });
}
// Set the current page to 'chapter'
Expand Down

0 comments on commit a0fde75

Please sign in to comment.