Skip to content

Commit

Permalink
added mushaf & supplication link in quran nav modal, added hash based…
Browse files Browse the repository at this point in the history
… routing, major code refactoring (#208)
  • Loading branch information
marwan authored Nov 29, 2024
1 parent da34431 commit 0439881
Show file tree
Hide file tree
Showing 40 changed files with 1,005 additions and 1,364 deletions.
14 changes: 13 additions & 1 deletion src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,26 @@

<!-- set the website theme - we put this code here to avoid the white flash and making people go blind -->
<script>
// Declare the theme variable
let theme;

try {
theme = JSON.parse(localStorage.getItem('userSettings')).displaySettings.websiteTheme;
// Try to retrieve the user settings from localStorage and parse the JSON string
const userSettings = JSON.parse(localStorage.getItem('userSettings'));

// Check if displaySettings and websiteTheme exist in the parsed object
if (userSettings && userSettings.displaySettings && userSettings.displaySettings.websiteTheme !== undefined) {
theme = userSettings.displaySettings.websiteTheme;
} else {
// Default theme in case the properties don't exist
theme = 1;
}
} catch (error) {
// If there's an error during JSON parsing or any other issue, fallback to default theme
theme = 1;
}

// Apply the theme class to the document's root element
document.documentElement.classList = `theme-${theme} ${window.bodyColors[theme]}`;
</script>
%sveltekit.head%
Expand Down
11 changes: 6 additions & 5 deletions src/components/display/morphology/Table.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
const loadAll = params.get('load_all') === 'true';
const totalAvailableWords = Object.keys(wordData).length;
const maxResultsToLoad = 50;
let lastWordToLoad = loadAll ? totalAvailableWords : totalAvailableWords > maxResultsToLoad ? maxResultsToLoad : totalAvailableWords;
let lastWordToLoad = calculateInitialLastWordToLoad(loadAll, totalAvailableWords, maxResultsToLoad);
function calculateInitialLastWordToLoad(loadAll, totalAvailableWords, maxResultsToLoad) {
return loadAll ? totalAvailableWords : Math.min(totalAvailableWords, maxResultsToLoad);
}
function updateLastWordToLoad() {
lastWordToLoad = lastWordToLoad + 50;
if (lastWordToLoad > totalAvailableWords) {
lastWordToLoad = totalAvailableWords;
}
lastWordToLoad = Math.min(lastWordToLoad + 50, totalAvailableWords);
}
</script>

Expand Down
62 changes: 39 additions & 23 deletions src/components/display/verses/VerseOptionButtons.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,60 @@
import { term } from '$utils/terminologies';
import { quranMetaData } from '$data/quranMeta';
const chapter = +key.split(':')[0];
const verse = +key.split(':')[1];
const chapter = parseInt(key.split(':')[0], 10);
const verse = parseInt(key.split(':')[1], 10);
const versesInChapter = quranMetaData[chapter].verses;
const buttonClasses = 'inline-flex items-center justify-center w-10 h-10 transition-colors duration-150 rounded-3xl focus:shadow-outline hover:bg-lightGray print:hidden';
// for chapter page, just show the key, else show the complete chapter transliteration & key
// For chapter page, just show the key, else show the complete chapter transliteration & key
$: verseKeyClasses = `${buttonClasses} w-fit px-4 bg-lightGray font-medium`;
// update userBookmarks whenever the __userSettings changes
// Update userBookmarks whenever the __userSettings changes
$: userBookmarks = JSON.parse($__userSettings).userBookmarks;
function audioHandler(key) {
// stop any audio if something is playing
if ($__audioSettings.isPlaying) resetAudioSettings({ location: 'end' });
// else continue with playing options
else {
// for chapter & mushaf page, respect the user select play button functionality
// Stop any audio if something is playing
if ($__audioSettings.isPlaying) {
resetAudioSettings({ location: 'end' });
} else {
// For chapter & mushaf page, respect the user select play button functionality
if (['chapter', 'mushaf'].includes($__currentPage)) {
// 1. Play selected Ayah (default)
if ($__playButtonsFunctionality.verse === 1) playVerseAudio({ key, language: 'arabic', timesToRepeat: 1 });
// 2. Play from here
else if ($__playButtonsFunctionality.verse === 2) {
setVersesToPlay({ location: 'verseOptionsOrModal', chapter: chapter, startVerse: verse, endVerse: versesInChapter, audioRange: 'playFromHere' });
playVerseAudio({ key: `${window.versesToPlayArray[0]}`, timesToRepeat: 1, language: 'arabic' });
}
// 3. Open Advance Play modal
else if ($__playButtonsFunctionality.verse === 3) showAudioModal(key);
handleAudioPlayOptions(key);
} else {
playVerseAudio({ key, language: 'arabic', timesToRepeat: 1 });
}
}
}
function handleAudioPlayOptions(key) {
const { verse } = $__playButtonsFunctionality;
// for any other page, stick to default
else playVerseAudio({ key, language: 'arabic', timesToRepeat: 1 });
switch (verse) {
case 1:
playVerseAudio({ key, language: 'arabic', timesToRepeat: 1 });
break;
case 2:
setVersesToPlay({
location: 'verseOptionsOrModal',
chapter,
startVerse: verse,
endVerse: versesInChapter,
audioRange: 'playFromHere'
});
playVerseAudio({ key: `${window.versesToPlayArray[0]}`, timesToRepeat: 1, language: 'arabic' });
break;
case 3:
showAudioModal(key);
break;
default:
playVerseAudio({ key, language: 'arabic', timesToRepeat: 1 });
break;
}
}
// function to toggle words block for display mode #7
// Function to toggle words block for display mode #7
function wordsBlockToggler(verse) {
document.querySelectorAll(`#verse-${verse}-words`)[0].classList.toggle('hidden');
document.querySelector(`#verse-${verse}-words`).classList.toggle('hidden');
}
</script>

Expand Down
21 changes: 12 additions & 9 deletions src/components/display/verses/VerseOptionsDropdown.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,29 @@
const dropdownItemClasses = 'font-normal rounded-3xl hover:bg-black/5';
let dropdownOpen = false;
// we need to manually add and/or remove z-index from the verse options dropdown because it becomes transparent due to our themes which we achieve via CSS filters
// we remove z-index from all button blocks, and add it to button block of verse for which the dropdown was opened
$: {
// We need to manually add and/or remove z-index from the verse options dropdown because it becomes transparent due to our themes which we achieve via CSS filters
// We remove z-index from all button blocks, and add it to the button block of the verse for which the dropdown was opened
$: updateZIndex($__verseKey);
function updateZIndex(verseKey) {
try {
if (dropdownOpen) {
document.querySelectorAll('.verseButtons').forEach((element) => {
element.classList.remove('z-10');
});
document.getElementById($__verseKey).firstChild.classList.add('z-10');
document.getElementById(verseKey).firstChild.classList.add('z-10');
}
} catch (error) {}
} catch (error) {
// console.error('Error updating z-index:', error);
}
}
// update userBookmarks whenever the __userSettings changes
// Update userBookmarks whenever the __userSettings changes
$: userBookmarks = JSON.parse($__userSettings).userBookmarks;
// open share menu
// Open share menu
function shareVerse() {
const chapter = +$__verseKey.split(':')[0];
const verse = +$__verseKey.split(':')[1];
const [chapter, verse] = $__verseKey.split(':').map(Number);
if (navigator.share) {
navigator.share({
Expand Down
54 changes: 28 additions & 26 deletions src/components/display/verses/WordsBlock.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
<script>
export let key;
export let value;
export let line = null;
export let exampleVerse = false;
import VerseOptionsDropdown from '$display/verses/VerseOptionsDropdown.svelte';
import Word from '$display/verses/Word.svelte';
import Tooltip from '$ui/FlowbiteSvelte/tooltip/Tooltip.svelte';
Expand All @@ -15,48 +10,52 @@
import { updateSettings } from '$utils/updateSettings';
import { mushafWordFontLink, mushafFontVersion } from '$data/websiteSettings';
const fontSizes = JSON.parse($__userSettings).displaySettings.fontSizes;
export let key;
export let value;
export let line = null;
export let exampleVerse = false;
const fontSizes = JSON.parse($__userSettings).displaySettings.fontSizes;
$: displayIsContinuous = selectableDisplays[$__displayType].continuous;
// if mushaf fonts are selected, then dynamically load the fonts
// Dynamically load the fonts if mushaf fonts are selected
if ([2, 3].includes($__fontType)) {
loadFont(`p${value.meta.page}`, `${mushafWordFontLink}/QCF4${`00${value.meta.page}`.slice(-3)}_COLOR-Regular.woff?version=${mushafFontVersion}`).then(() => {
// we can by default hide the v4 words and show when the font is loaded...
// Hide the v4 words by default and show when the font is loaded...
document.querySelectorAll(`.p${value.meta.page}`).forEach((element) => {
element.classList.remove('invisible');
});
});
}
// handle what happens when a word is clicked depending on page type
// 1. if a word is clicked on the morphology page, show/goto that word's morphology
// 2. if a word is clicked on other pages, play the word's audio
// 3. if the end verse icon is clicked on any page, show the verse options dropdown
// Handle word clicks based on page type
// 1. On morphology page, navigate to word's morphology
// 2. On other pages, play word's audio
// 3. On any page, show verse options dropdown for end verse icon
function wordClickHandler(props) {
// only if its morphology page and a word is clicked
if ($__currentPage === 'morphology' && props.type === 'word') {
__morphologyKey.set(props.key);
goto(`/morphology/${props.key}`, { replaceState: false });
}
// for all other pages
else {
} else {
__verseKey.set(props.key);
// word in verse
if (props.type === 'word') {
wordAudioController({ key: props.key, chapter: +props.key.split(':')[0], verse: +props.key.split(':')[1] });
}
// end verse icon
else if (props.type === 'end') {
// for continuous modes, the verse options dropdown will open, but if its not a continuous mode then un/bookmark verse
if (!displayIsContinuous) updateSettings({ type: 'userBookmarks', key: props.key, set: true });
wordAudioController({
key: props.key,
chapter: +props.key.split(':')[0],
verse: +props.key.split(':')[1]
});
} else if (props.type === 'end') {
if (!displayIsContinuous)
updateSettings({
type: 'userBookmarks',
key: props.key,
set: true
});
}
}
}
// Common classes for words and end icons
$: wordAndEndIconCommonClasses = `
hover:cursor-pointer
${selectableThemes[$__websiteTheme].palette === 1 ? 'hover:bg-white/20' : 'hover:bg-black/10'}
Expand All @@ -65,6 +64,7 @@
${exampleVerse && '!p-0'}
`;
// Classes for word spans
$: wordSpanClasses = `
arabicText leading-normal
arabic-font-${$__fontType}
Expand All @@ -73,12 +73,14 @@
${[1, 4].includes($__fontType) && 'text-black theme'}
`;
// Classes for v4 hafs words
$: v4hafsClasses = `
invisible v4-words
p${value.meta.page}
${$__fontType === 3 ? 'theme-palette-tajweed' : 'theme-palette-normal'}
`;
// Classes for end icons
$: endIconClasses = `rounded-lg ${wordAndEndIconCommonClasses}`;
</script>

Expand Down
22 changes: 10 additions & 12 deletions src/components/display/verses/modes/Chapter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import { __currentPage, __userSettings, __displayType, __chapterNumber, __chapterData, __chapterDataLoaded } from '$utils/stores';
import { buttonOutlineClasses } from '$data/commonClasses';
// load button click options
// Load button click options
const loadButtonOptions = {
rootMargin: '2000px',
unobserveOnEnter: true
Expand All @@ -36,30 +36,28 @@
let nextVersesStart;
let nextVersesEnd;
// function to load the next set of verses
// Function to load the next set of verses
function loadNextVerses() {
versesLoadType = 'next';
// importing the same component to be re-used when the "Load Next Verses" button is pressed
// Importing the same component to be re-used when the "Load Next Verses" button is pressed
import('./Chapter.svelte').then((res) => (Chapter = res.default));
// max verses to load when the next set is requested
// Max verses to load when the next set is requested
const versesToLoad = 5;
// get the last verse number from last prop value
// Get the last verse number from last prop value
const versesOnPage = document.getElementsByClassName('verse');
const lastVerseOnPage = +versesOnPage[versesOnPage.length - 1].id.split(':')[1];
// remove the existing button
// Remove the existing button
document.getElementById('loadVersesButton').remove();
// define the new starting and ending range
(nextVersesStart = lastVerseOnPage + 1), (nextVersesEnd = nextVersesStart + versesToLoad);
// Define the new starting and ending range
nextVersesStart = lastVerseOnPage + 1;
nextVersesEnd = Math.min(nextVersesStart + versesToLoad, chapterTotalVerses);
// if the end verse set above is greater than total verses, then set it as total verses
if (nextVersesEnd > chapterTotalVerses) nextVersesEnd = chapterTotalVerses;
// setting the nextVersesProps
// Setting the nextVersesProps
nextVersesProps = {
startVerse: nextVersesStart,
endVerse: nextVersesEnd
Expand Down
8 changes: 6 additions & 2 deletions src/components/display/verses/modes/Individual.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@
import TranslationTransliteration from '$display/layouts/TranslationTransliteration.svelte';
import { __displayType } from '$utils/stores';
const allowedDisplayTypes = [1, 2, 7];
const displayComponents = {
1: { component: WordByWord },
2: { component: Normal },
7: { component: TranslationTransliteration }
};
// only allow display type 1, 2 & 7, and don't save the layout in settings
if (![1, 2, 7].includes($__displayType)) __displayType.set(1);
// Only allow display type 1, 2, & 7, and don't save the layout in settings if not allowed
if (!allowedDisplayTypes.includes($__displayType)) {
__displayType.set(1);
}
</script>

<svelte:component this={displayComponents[$__displayType].component} {key} {value} />
Loading

0 comments on commit 0439881

Please sign in to comment.