diff --git a/config/index.d.ts b/config/index.d.ts
index 2faad1c67..42fcb01e1 100644
--- a/config/index.d.ts
+++ b/config/index.d.ts
@@ -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;
@@ -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?: {
diff --git a/convert/convertConfig.ts b/convert/convertConfig.ts
index 83f9371ee..ec5a23532 100644
--- a/convert/convertConfig.ts
+++ b/convert/convertConfig.ts
@@ -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 = {
@@ -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}`);
diff --git a/src/lib/components/BottomNavigationBar.svelte b/src/lib/components/BottomNavigationBar.svelte
new file mode 100644
index 000000000..fa2279ae4
--- /dev/null
+++ b/src/lib/components/BottomNavigationBar.svelte
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+ {#if bottomNavBarItems}
+ {#each bottomNavBarItems as item}
+ {#if showButton(item.type)}
+
+ {/if}
+ {/each}
+ {/if}
+
+
+
diff --git a/src/routes/about/+page.svelte b/src/routes/about/+page.svelte
index 5b082ea50..6c47ef13d 100644
--- a/src/routes/about/+page.svelte
+++ b/src/routes/about/+page.svelte
@@ -1,8 +1,12 @@
@@ -20,4 +24,7 @@
{@html data.partial}
+ {#if bottomNavBarEnabled}
+
+ {/if}
diff --git a/src/routes/contents/[id]/+page.svelte b/src/routes/contents/[id]/+page.svelte
index e9e260ea7..b29e7a407 100644
--- a/src/routes/contents/[id]/+page.svelte
+++ b/src/routes/contents/[id]/+page.svelte
@@ -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';
@@ -167,6 +168,8 @@
}
}
$: showBackButton = $contentsStack.length > 0;
+ const bottomNavBarEnabled = config?.bottomNavBarItems && config?.bottomNavBarItems.length > 0;
+ const barType = 'contents';
@@ -260,4 +263,7 @@
{/each}
+ {#if bottomNavBarEnabled}
+
+ {/if}
diff --git a/src/routes/plans/+page.svelte b/src/routes/plans/+page.svelte
index 820241c62..9945d4b58 100644
--- a/src/routes/plans/+page.svelte
+++ b/src/routes/plans/+page.svelte
@@ -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';
@@ -57,6 +58,8 @@
);
usedPlans = plansInUse;
}
+ const bottomNavBarEnabled = config?.bottomNavBarItems && config?.bottomNavBarItems.length > 0;
+ const barType = 'plans';
@@ -212,4 +215,7 @@
{/if}
+ {#if bottomNavBarEnabled}
+
+ {/if}
diff --git a/src/routes/plans/[id]/+page.svelte b/src/routes/plans/[id]/+page.svelte
index d2ef2cd0b..c48db00b7 100644
--- a/src/routes/plans/[id]/+page.svelte
+++ b/src/routes/plans/[id]/+page.svelte
@@ -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;
diff --git a/src/routes/text/+page.svelte b/src/routes/text/+page.svelte
index 5e35d49c7..4937b7f99 100644
--- a/src/routes/text/+page.svelte
+++ b/src/routes/text/+page.svelte
@@ -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(() => {
@@ -86,6 +101,9 @@
}
}
+ const bottomNavBarEnabled = config?.bottomNavBarItems && config?.bottomNavBarItems.length > 0;
+ const barType = 'book';
+
async function prevChapter() {
await navigateToTextChapterInDirection(-1);
}
@@ -503,6 +521,9 @@
{/if}
+ {#if scrollingUp && bottomNavBarEnabled && !$selectedVerses.length > 0}
+
+ {/if}