Skip to content

Commit

Permalink
Bottom Navigation Bar (#759)
Browse files Browse the repository at this point in the history
* Initial additiona

* Make Book work correctly if opening specific book.  Still have display issue with small screen.

* Fix format errors

* Changed error message

* Trying to get by lint test

* Fix compile test error

* One more lint issue

* Changed message

* again

* Fix so that Book icon going to specific book is not marked as selected when in text

* Fix lint issue

* Convert to grid to get all the items in a single line on a small phone

* Change max width of the buttons to be the width of the text, while still having the bar across the full bottom.  Eliminate unneeded variables.

* Changes to resolve comments
  • Loading branch information
davidmoore1 authored Dec 16, 2024
1 parent 74f2a7e commit 42af36a
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 32 deletions.
37 changes: 19 additions & 18 deletions config/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,23 @@ export type DictionaryWritingSystemConfig = WritingSystemConfig & {
[name: string]: boolean;
};
};

export type MenuItemConfig = {
type: string;
title: {
[lang: string]: string;
};
link?: {
[lang: string]: string;
};
linkId?: {
[lang: string]: string;
};
images?: {
width: number;
height: number;
file: string;
}[];
};
export type AppConfig = {
name?: string;
package?: string;
Expand Down Expand Up @@ -172,23 +188,8 @@ export type AppConfig = {
[name: string]: boolean;
};
};
menuItems?: {
type: string;
title: {
[lang: string]: string;
};
link?: {
[lang: string]: string;
};
linkId?: {
[lang: string]: string;
};
images?: {
width: number;
height: number;
file: string;
}[];
}[];
menuItems?: MenuItemConfig[];
bottomNavBarItems?: MenuItemConfig[];
security?: {
// TODO
features?: {
Expand Down
16 changes: 10 additions & 6 deletions convert/convertConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,16 @@ function convertConfig(dataDir: string, verbose: number) {
data.watermarkImages = watermarkImages;
}

const menuItems = parseMenuItems(document, verbose);
const menuItems = parseMenuItems(document, 'drawer', verbose);
if (menuItems.length > 0) {
data.menuItems = menuItems;
}

const bottomNavigationItems = parseMenuItems(document, 'bottom', verbose);
if (bottomNavigationItems.length > 0) {
data.bottomNavBarItems = bottomNavigationItems;
}

const { features, plans } = parsePlans(document, verbose);
if (plans.length > 0) {
data.plans = {
Expand Down Expand Up @@ -1139,12 +1144,11 @@ function parseWatermarkImages(document: Document, verbose: number) {
return watermarkImages;
}

function parseMenuItems(document: Document, verbose: number) {
const menuItemTags = document
.getElementsByTagName('menu-items')[0]
?.getElementsByTagName('menu-item');
function parseMenuItems(document: Document, type: string, verbose: number) {
const firstMenuItemsByType = document.querySelector(`menu-items[type="${type}"]`);
const menuItemTags = firstMenuItemsByType?.getElementsByTagName('menu-item');
const menuItems = [];
if (menuItemTags?.length > 0) {
if (menuItemTags && menuItemTags?.length > 0) {
for (const menuItem of menuItemTags) {
const type = menuItem.attributes.getNamedItem('type')!.value;
if (verbose >= 2) console.log(`.. Converting menuItem: ${type}`);
Expand Down
153 changes: 153 additions & 0 deletions src/lib/components/BottomNavigationBar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<!--
@component
-->
<script>
import { goto } from '$app/navigation';
import { base } from '$app/paths';
import config from '$lib/data/config';
import { refs, s, language, languageDefault, theme } from '$lib/data/stores';
import contents from '$lib/data/contents';
export let barType = undefined;
const bottomNavBarItems = config?.bottomNavBarItems;
$: barBackgroundColor = $s['ui.bottom-navigation.']['background-color'];
$: barTextColor = $s['ui.bottom-navigation.item.text']['color'];
$: barTextSelectedColor = $s['ui.bottom-navigation.item.text.selected']['color'];
const showContents = contents.screens?.length > 0;
const showSearch = config.mainFeatures['search'];
const showPlans = config.plans?.plans.length > 0;
function showButton(buttonType) {
let value = true;
switch (buttonType) {
case 'contents':
value = showContents;
break;
case 'plans':
value = showPlans;
break;
case 'search':
value = showSearch;
break;
default:
value = true;
}
return value;
}
function selectedLink(buttonType, link) {
let value = buttonType === barType;
if (buttonType === 'book') {
// Don't highlight link for specific book
if (link && link !== '') {
value = false;
}
}
return value;
}
function gridColumns() {
let value = 'grid-cols-5';
if (bottomNavBarItems) {
switch (bottomNavBarItems.length) {
case 2:
value = 'grid-cols-2';
break;
case 3:
value = 'grid-cols-3';
break;
case 4:
value = 'grid-cols-4';
break;
default:
value = 'grid-cols-5';
}
}
return value;
}
function handleClick(buttonType, link) {
switch (buttonType) {
case 'contents':
let gotoLink = link && link !== '' ? link : '1';
goto(`${base}/contents/${gotoLink}`);
break;
case 'about':
goto(`${base}/about`);
break;
case 'book':
if (link && link !== '') {
const [bc, book] = link.split('|');
const refBc = config.bookCollections.find((x) => x.id === bc);
let refDocSet = '';
if (refBc) {
refDocSet = refBc.languageCode + '_' + refBc.id;
} else {
// Invalid collection
return;
}
refs.set({
docSet: refDocSet,
book: book,
chapter: '1',
verse: '1'
});
}
goto(`${base}/text`);
break;
case 'plans':
goto(`${base}/plans`);
break;
case 'search':
goto(`${base}/search/${$refs.collection}`);
break;
case 'settings':
goto(`${base}/settings`);
break;
default:
console.log(
'BottomNavigation Bar: Unknown NavBar button type pressed: ',
buttonType
);
break;
}
}
</script>
<div class="h-16" style:background-color={barBackgroundColor}>
<div class="mx-auto max-w-screen-md">
<div class="grid {gridColumns()} justify-items-center">
<!-- Controls -->
{#if bottomNavBarItems}
{#each bottomNavBarItems as item}
{#if showButton(item.type)}
<button
class="dy-btn dy-btn-ghost flex-col gap-1 my-2"
on:click={() => handleClick(item.type, item.link['default'])}
>
<picture class:invert={$theme === 'Dark'}>
<!-- Image Icon -->
<img
src="{base}/icons/menu-items/{item.images[0].file}"
alt=""
class={selectedLink(item.type, item.link['default'])
? 'opacity-100'
: 'opacity-50'}
/>
</picture>
<!-- Text -->
<span
class="text-center"
style="color: {selectedLink(item.type, item.link['default'])
? barTextSelectedColor
: barTextColor}"
>
{item.title[$language] || item.title[languageDefault]}
</span>
</button>
{/if}
{/each}
{/if}
</div>
</div>
</div>
9 changes: 8 additions & 1 deletion src/routes/about/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
<script lang="ts">
import Navbar from '$lib/components/Navbar.svelte';
import { t } from '$lib/data/stores';
import BottomNavigationBar from '$lib/components/BottomNavigationBar.svelte';
import config from '$lib/data/config';
export let data;
const bottomNavBarEnabled = config?.bottomNavBarItems && config?.bottomNavBarItems.length > 0;
const barType = 'about';
</script>

<div class="grid grid-rows-[auto,1fr]" style="height:100vh;height:100dvh;">
Expand All @@ -20,4 +24,7 @@
{@html data.partial}
</div>
</div>
{#if bottomNavBarEnabled}
<BottomNavigationBar {barType} />
{/if}
</div>
6 changes: 6 additions & 0 deletions src/routes/contents/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import { goto } from '$app/navigation';
import config from '$lib/data/config';
import { AudioIcon, TextAppearanceIcon } from '$lib/icons';
import BottomNavigationBar from '$lib/components/BottomNavigationBar.svelte';
const imageFolder =
compareVersions(config.programVersion, '12.0') < 0 ? 'illustrations' : 'contents';
Expand Down Expand Up @@ -167,6 +168,8 @@
}
}
$: showBackButton = $contentsStack.length > 0;
const bottomNavBarEnabled = config?.bottomNavBarItems && config?.bottomNavBarItems.length > 0;
const barType = 'contents';
</script>
<div class="grid grid-rows-[auto,1fr]" style="height:100vh;height:100dvh;">
Expand Down Expand Up @@ -260,4 +263,7 @@
{/each}
</div>
</div>
{#if bottomNavBarEnabled}
<BottomNavigationBar {barType} />
{/if}
</div>
6 changes: 6 additions & 0 deletions src/routes/plans/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import { getLastPlanState } from '$lib/data/planStates';
import { compareVersions } from '$lib/scripts/stringUtils';
import { goto } from '$app/navigation';
import BottomNavigationBar from '$lib/components/BottomNavigationBar.svelte';
const imageFolder =
compareVersions(config.programVersion, '12.0') < 0 ? 'illustrations' : 'plans';
Expand Down Expand Up @@ -57,6 +58,8 @@
);
usedPlans = plansInUse;
}
const bottomNavBarEnabled = config?.bottomNavBarItems && config?.bottomNavBarItems.length > 0;
const barType = 'plans';
</script>
<div class="grid grid-rows-[auto,1fr]" style="height:100vh;height:100dvh;">
Expand Down Expand Up @@ -212,4 +215,7 @@
{/if}
</div>
</div>
{#if bottomNavBarEnabled}
<BottomNavigationBar {barType} />
{/if}
</div>
8 changes: 1 addition & 7 deletions src/routes/plans/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,7 @@
}
return completed;
}
function checkSelection(day) {
if (day === selectedDay) {
return 'selected plan-day-box-selected';
} else {
return 'plan-day-box-unselected';
}
}
function getReferenceString(ref) {
// Reminder - get book collection id
let currentBookCollectionId = $refs.collection;
Expand Down
21 changes: 21 additions & 0 deletions src/routes/text/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,27 @@
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { onDestroy, onMount, afterUpdate } from 'svelte';
import { slide } from 'svelte/transition';
import { navigateToTextChapterInDirection } from '$lib/navigate';
import BottomNavigationBar from '$lib/components/BottomNavigationBar.svelte';
let scrollingUp = true;
let savedScrollPosition = 0;
let lastChangeTime = 0;
function saveScrollPosition() {
if (scrollingDiv) {
const now = Date.now();
const oldSavedScroll = savedScrollPosition;
savedScrollPosition = scrollingDiv.scrollTop;
const newScrollingUp = oldSavedScroll - savedScrollPosition > 0;
if (newScrollingUp != scrollingUp) {
if (now - lastChangeTime > 500) {
// The timing thing fixes a problem with occasional vibrating
// when you hit the bottom of the screen
scrollingUp = newScrollingUp;
lastChangeTime = now;
}
}
}
}
afterUpdate(() => {
Expand All @@ -86,6 +101,9 @@
}
}
const bottomNavBarEnabled = config?.bottomNavBarItems && config?.bottomNavBarItems.length > 0;
const barType = 'book';
async function prevChapter() {
await navigateToTextChapterInDirection(-1);
}
Expand Down Expand Up @@ -503,6 +521,9 @@
</div>
</div>
{/if}
{#if scrollingUp && bottomNavBarEnabled && !$selectedVerses.length > 0}
<BottomNavigationBar {barType} />
{/if}
</div>
<style>
Expand Down

0 comments on commit 42af36a

Please sign in to comment.