Skip to content

Convert stores and page loads to TS#960

Merged
FyreByrd merged 8 commits into
mainfrom
refactor/js-to-ts
May 20, 2026
Merged

Convert stores and page loads to TS#960
FyreByrd merged 8 commits into
mainfrom
refactor/js-to-ts

Conversation

@FyreByrd
Copy link
Copy Markdown
Collaborator

@FyreByrd FyreByrd commented May 19, 2026

Continuation of #959, part 2/3 of #905

Changes:

  • convert all stores to TS
  • convert all page loads to TS
  • convert icon exports to TS
  • remove unused scripts
    • groupStore
    • old proskomma query.js and render.js

Summary by CodeRabbit

  • Bug Fixes

    • Fixed responsive layout in notes editor—divider and reference display now visible on smaller screens.
  • Refactor

    • Modernized modal system with type-safe enum-based identifiers.
    • Enhanced TypeScript type annotations across data stores, database handlers, and page loaders.
    • Consolidated localization module to TypeScript with improved type safety.
    • Improved audio system typing and internal state management.

@FyreByrd FyreByrd requested a review from eomerdws May 19, 2026 14:23
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

Warning

Rate limit exceeded

@FyreByrd has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 29 minutes and 9 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d1b17beb-6dbb-4ddb-91c2-09bc086ea399

📥 Commits

Reviewing files that changed from the base of the PR and between d9f9ee2 and 7e0cc6c.

📒 Files selected for processing (4)
  • src/lib/data/audio.ts
  • src/lib/data/bookmarks.ts
  • src/lib/data/history.ts
  • src/lib/data/notes.ts
📝 Walkthrough

Walkthrough

This PR modernizes the app's architecture by introducing a typed modal system, refactoring audio playback state management with enums, adding comprehensive TypeScript annotations across stores and database layers, converting SvelteKit page loaders to typed const form, and migrating component data access from store to props. It also removes legacy script utilities and strengthens type safety throughout the codebase.

Changes

Modal and Store Refactoring

Layer / File(s) Summary
Modal type enum definition and migration
src/lib/data/stores/view.ts, src/lib/components/AudioBar.svelte, src/lib/components/ScriptureViewSofria.svelte, src/lib/components/Sidebar.svelte, src/lib/components/TextAppearanceSelector.svelte, src/routes/+layout.svelte, src/routes/contents/[id]/+page.svelte, src/routes/contents/[id]/+page.ts, src/routes/lexicon/+layout.svelte, src/routes/quiz/[collection]/[id]/+page.svelte, src/routes/text/+page.svelte
ModalType enum replaces MODAL_* string constants; all components and routes update modal.open calls to use ModalType.
Collection/Note/TextAppearance/Font/StopPlan/PlaybackSpeed values.
Audio play-mode enum refactoring
src/lib/data/stores/audio.ts
Introduces PlayMode enum/union with Continue→Stop→RepeatPage→RepeatSelection cycling logic, introduces AudioPlayer interface and Timing type, refactors audio-state storage to persist booleans via localStorage.
Remove groupStore and add localization store
src/lib/data/stores/store-types.js, src/lib/data/stores/localization.ts
Removes untyped groupStore utility; adds new TypeScript localization store with language and derived t (translations) using fallback chain.
Scripture store generic typing and selection model
src/lib/data/stores/scripture.ts
Makes createStack generic (createStack), adds public Selection type, types all helpers (getReference, getVerseText, addVerse) with explicit parameters, updates composite reference generation with typed verse numbers.
Storage helper and setting store type annotations
src/lib/data/stores/storage.ts, src/lib/data/stores/setting.ts
Adds explicit parameter types to setDefaultStorage(name: string, value: string) and mergeDefaultStorage(name: string, value?: Record), removes unused get import from setting store.
Theme store type hardening
src/lib/data/stores/theme.ts
Adds nullish-coalescing fallback for themeDefault, types resolveColor and convertStyle parameters, refactors styles reduction with explicit accumulator type.
Modal dialog handling
src/routes/+layout.svelte
Updates modal dispatch to use ModalType enum; changes noteDialog invocation to optional chaining with payload cast; retypes noteDialog binding from required to optional.

Audio System Refactoring

Layer / File(s) Summary
Audio module imports, state encapsulation, and subscription logic
src/lib/data/audio.ts
Removes $app/paths import; imports AudioPlayer/PlayMode types; encapsulates currentAudioPlayer and currentPlayMode as internal state; refactors play-mode subscription to use PlayMode enum and conditionally update range.
Audio playback guards and control flow
src/lib/data/audio.ts
Adds optional-chaining guards (currentAudioPlayer?.loaded) throughout getAudio, playPause, playStop, play, updateTime; refactors timing/highlight logic to handle missing state safely; updates toggleTimeRunning and hasAudioPlayed.
Verse navigation and seek functions
src/lib/data/audio.ts
Updates skip, changeVerse, seekOffset with explicit parameter typing; implements seek to update progress and playMode range via getCurrentVerseTiming; adds typed seekToVerse with guard.
Play-mode state machine and warmdown logic
src/lib/data/audio.ts
Rewrites handlePlayMode to use PlayMode enum, implements warmdown: number | undefined for end-of-audio behavior, adds distinct branches for Stop/Continue/RepeatPage/RepeatSelection.
Timing computation and highlighting
src/lib/data/audio.ts
Updates getCurrentVerseTiming to scan currentAudioPlayer?.timing with optional chaining, initializes typed Timing[] array, adds getVerseTimingRange with typed parameters, refactors updateHighlights to iterate timing safely.
Playback speed and audio source info
src/lib/data/audio.ts
Updates updatePlaybackSpeed(playbackSpeed: string), refactors getAudioSourceInfo to accept Partial item and return typed Timing[] or null.
Analytics module audio player import
src/lib/data/analytics.ts
Updates analytics.ts to import AudioPlayer type from stores instead of audio module.

SvelteKit Route Loader and Page Data Modernization

Layer / File(s) Summary
Convert page loaders to typed PageLoad const form
src/routes/+page.ts, src/routes/about/+page.ts, src/routes/bookmarks/+page.ts, src/routes/contents/[id]/+page.ts, src/routes/highlights/+page.ts, src/routes/history/+page.ts, src/routes/notes/+page.ts, src/routes/notes/edit/[noteid]/+page.ts, src/routes/plans/+page.ts, src/routes/plans/[id]/+page.ts, src/routes/plans/[id]/settings/+page.ts, src/routes/share/+page.ts
Converts all route loaders from export async function to export const load: PageLoad, updates closing syntax with semicolons.
Update loaders to use scriptureConfig and optional-chaining filters
src/routes/bookmarks/+page.ts, src/routes/highlights/+page.ts, src/routes/history/+page.ts, src/routes/notes/+page.ts
Changes loaders to import scriptureConfig instead of config, uses optional chaining on bookCollections to tolerate missing collections, updates depends keys from untyped to 'note:*' format.
Text route proskomma initialization
src/routes/text/+page.js, src/routes/text/+page.ts
Removes load function from text/+page.js, adds typed PageLoad-based load to text/+page.ts to initialize Proskomma on each load.
Migrate component page data from store to $props()
src/routes/highlights/+page.svelte, src/routes/share/+page.svelte
Updates components to use typed PageData props from $props() instead of page store, introduces Props interfaces, updates data access for highlights and languages.
Plans loader and plan-state import cleanup
src/routes/plans/+page.ts, src/routes/plans/[id]/+page.svelte, src/routes/plans/[id]/+page.ts
Removes actual data fetching from plans/+page.ts (returns empty array), removes unused getLastPlanState import, updates plan-id page to use $lib alias.

Database Schema and Instance Typing

Layer / File(s) Summary
Type all IndexedDB singleton instances
src/lib/data/plans.ts, src/lib/data/planStates.ts, src/lib/data/planProgressItems.ts, src/lib/data/history.ts, src/lib/data/bookmarks.ts
Adds explicit Awaited<ReturnType<openDB>> | null types to planDB, planStateDB, planProgressItemsDB, historyDB, bookmarkDB, noteDB.
Update IndexedDB schema index types
src/lib/data/bookmarks.ts, src/lib/data/notes.ts
Changes schema index type annotations from string to string[] for compound keys like 'collection, book, chapter, verse'.
Add conditional guards to database mutations
src/lib/data/bookmarks.ts, src/lib/data/notes.ts, src/lib/data/history.ts
Updates addBookmark to guard insert with if (bookIndex), updates addNote conditional persist, updates editNote to only put when record exists, refactors addHistory to use non-null assertions.
Update cache invalidation to note: prefixed keys
src/lib/data/bookmarks.ts, src/lib/data/highlights.ts, src/lib/data/notes.ts, src/lib/data/planProgressItems.ts, src/lib/data/planStates.ts
Changes notifyUpdated calls to invalidate 'note:bookmarks', 'note:highlights', 'note:notes', 'note:planprogressitems', 'note:planstates'.
Fix plan progress return types from tuples to arrays
src/lib/data/planProgressItems.ts
Changes getAllProgressItemsForPlan and getCompletedRefsForDay return types from single-element tuples to proper arrays; updates getFirstIncompleteDay iteration to handle missing items via optional chaining.

Scripture Module and Config Loading

Layer / File(s) Summary
Refactor initProskomma signature and asset loading
src/lib/data/scripture.ts
Removes fetch parameter from initProskomma; removes internal config/base computation; casts asset glob to Record<string, string>.
Type docSet loading and fetching functions
src/lib/data/scripture.ts
Introduces Fetch type from LoadEvent; types getDocSetUrl, fetchDocSet, loadDocSet, and loadDocSetIfNotLoaded with explicit parameters.

Script Module Removal and Import Cleanup

Layer / File(s) Summary
Clean up unused imports and store destructuring
src/lib/data/stores/setting.ts, src/routes/share/+page.ts, src/routes/text/+page.svelte, src/routes/notes/+page.svelte
Removes get from svelte/store, removes unused base import, removes themes destructuring, removes modal/MODAL_NOTE imports.
PlayButton size prop stringification and notes layout
src/lib/components/PlayButton.svelte, src/routes/notes/edit/[noteid]/+page.svelte
Changes PlayButton size to String(...) cast; removes hidden class from notes edit divider and reference container for better responsive rendering.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • sillsdev/appbuilder-pwa#846: Both PRs modify share/+page.svelte, updating how page/store state is accessed and derived values (app-store language/badge logic).
  • sillsdev/appbuilder-pwa#879: Main PR's noteDialog modal handling with typed payload casting aligns directly with PR #879's Svelte 5 migration of NoteDialog.showModal signature.
  • sillsdev/appbuilder-pwa#820: Main PR refactors TextAppearanceSelector modal opening to use ModalType enum; retrieved PR refactors the same component's Modal usage to Svelte 5 snippet API.

Suggested reviewers

  • eomerdws
  • chrisvire

🐰 A rabbit hops through modals so neat,
Types strengthen the code, making it complete,
Audio modes spin round and round,
While loaders now type-safe are found,
SvelteKit props sing their sweet refrain,
The codebase is healthier, bright, and plain! 🎵

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main objective of the PR: converting stores and page loads from JavaScript to TypeScript.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/js-to-ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/data/stores/storage.ts (1)

7-21: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard JSON.parse to prevent hard failures on corrupted storage (Line 14).

A malformed localStorage value will throw here and can break initialization paths. Add a safe parse fallback before merging.

Proposed change
 export const mergeDefaultStorage = (name: string, value?: Record<string, unknown>) => {
@@
-    } else if (storage && value) {
+    } else if (storage && value) {
         // If it does exist, then set the keys that don't exist
-        const update = JSON.parse(storage);
+        let update: Record<string, unknown>;
+        try {
+            update = JSON.parse(storage) as Record<string, unknown>;
+        } catch {
+            update = {};
+        }
         Object.keys(value).forEach((key) => {
             if (!Object.hasOwn(update, key)) {
                 update[key] = value[key];
             }
         });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/data/stores/storage.ts` around lines 7 - 21, mergeDefaultStorage
currently calls JSON.parse(storage) without guarding against corrupted/malformed
data which can throw; wrap the parse in a safe try/catch (when storage exists)
and if parsing fails treat it as absent (e.g., set update = value or {}), then
proceed with the existing merge logic and write back to localStorage;
specifically modify the mergeDefaultStorage function to catch JSON.parse errors
on the result of localStorage.getItem(name), use a safe fallback for update, and
ensure localStorage.setItem is called with the correct merged object.
🧹 Nitpick comments (5)
src/routes/highlights/+page.svelte (1)

54-58: ⚡ Quick win

Type the Props interface in the $props() destructuring.

The Props interface is declared but not applied to let { data }. Change to let { data }: Props = $props(); to enforce type checking on the data prop. This pattern is already followed in other converted pages (e.g., src/routes/share/+page.svelte and src/routes/quiz/[collection]/[id]/+page.svelte).

Proposed change
-    let { data } = $props();
+    let { data }: Props = $props();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/highlights/`+page.svelte around lines 54 - 58, The Props interface
is declared but not applied to the $props() destructuring; update the
destructuring so the data variable is typed using Props by changing the
declaration of let { data } to use the Props type (i.e., annotate the result of
$props() with Props) so the component enforces type checking for data; locate
the Props interface and the let { data } = $props() line in
src/routes/highlights/+page.svelte and add the type annotation to the
destructuring (using Props).
src/lib/data/stores/audio.ts (1)

43-43: ⚡ Quick win

Use an environment-safe timeout handle type for timer (Line 43).

NodeJS.Timeout is inappropriate for browser-only code. The actual implementation uses setInterval() at line 347, so use ReturnType<typeof setInterval> | null for compatibility. Alternatively, ReturnType<typeof setTimeout> | null works equivalently since both return the same type across all environments.

Proposed change
 export interface AudioPlayer {
-    timer: NodeJS.Timeout | null;
+    timer: ReturnType<typeof setInterval> | null;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/data/stores/audio.ts` at line 43, The field declaration "timer:
NodeJS.Timeout | null;" is using a Node-specific type and should be made
environment-safe; locate the declaration named timer and replace its type with a
platform-agnostic one such as "ReturnType<typeof setInterval> | null" (or
"ReturnType<typeof setTimeout> | null") to match the usage of setInterval at
runtime, ensuring the rest of the code (the setInterval/setTimeout calls and any
clears) continue to accept the updated type.
src/lib/data/stores/scripture.ts (1)

258-288: 💤 Low value

Fallback objects are missing the reference field from Selection type.

getVerseByIndex and getVerseByVerseNumber return an object missing the reference field when the index is invalid. This creates a type inconsistency with the Selection type defined at lines 202-209.

♻️ Suggested fix
             } else {
                 const selection = {
                     docSet: '',
                     collection: '',
                     book: '',
                     chapter: '',
+                    reference: '',
                     verse: ''
                 };
                 return selection;
             }

Apply to both getVerseByIndex (lines 264-272) and getVerseByVerseNumber (lines 280-288).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/data/stores/scripture.ts` around lines 258 - 288, The fallback
objects returned by getVerseByIndex and getVerseByVerseNumber lack the required
Selection.reference field, causing a type mismatch with the Selection type
(defined around Selection). Update the fallback objects in both functions
(getVerseByIndex and getVerseByVerseNumber) to include a reference property
(e.g., reference: '' or other appropriate default) so the returned object
matches the Selection shape.
src/lib/data/stores/view.ts (1)

128-135: 💤 Low value

Consider using get() instead of update() for read-only operations.

The length() method uses update() solely to read the stack length, which is unnecessary overhead. The get() function from svelte/store is already imported and would be simpler.

♻️ Suggested refactor
         length: () => {
-            let length = 0;
-            update((stack) => {
-                length = stack.length;
-                return stack; // No modification to stack, just returning current length
-            });
-            return length;
+            return get({ subscribe }).length;
         }

Or expose subscribe to a local variable and use get() on it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/data/stores/view.ts` around lines 128 - 135, The length() method
currently calls update() only to read the stack length; replace that with a
read-only get() usage (imported from svelte/store) or capture the store's
subscribe into a local variable and call get(stackStore) to obtain stack.length
directly; update the length() implementation to return get(stackStore).length
(or use the local subscribe/get approach) and remove the unnecessary update()
call — reference the length() function and the update/get utilities when making
the change.
src/lib/data/scripture.ts (1)

14-29: 💤 Low value

Commented code references removed config import.

Lines 19-22 reference config.bookCollections[0] but the config import was removed. If this code is ever uncommented, it will fail to compile. Consider either removing the dead code or adding a TODO with context.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/data/scripture.ts` around lines 14 - 29, The commented block inside
initProskomma references config.bookCollections but the config import was
removed; either delete the dead commented lines (lines that use
config.bookCollections and related docSet logic) or restore a proper import and
add a clear TODO explaining why config is needed before uncommenting; target the
initProskomma function and the commented docSet logic (the block that builds
docSet from config.bookCollections and the commented loadDocSet call) and ensure
any future uncommenting also reintroduces a matching import for config or
documents why the config dependency was removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/data/audio.ts`:
- Around line 316-318: The end tag assignment for the last timing entry is using
the first element incorrectly; in the block where you check if (j ===
currentAudioPlayer!.timing!.length - 1) replace end =
currentAudioPlayer!.timing![0].tag with end = currentAudioPlayer!.timing![j].tag
so the last element's tag is used (reference currentAudioPlayer, timing, j, and
end variables).

In `@src/lib/data/bookmarks.ts`:
- Around line 70-74: The current conditional uses if (bookIndex) which treats 0
as falsy and -1 as truthy, causing valid index 0 to be skipped and invalid -1 to
be accepted; change the check around the findIndex() result (bookIndex) to
explicitly test for a non-negative index (e.g., bookIndex >= 0 or bookIndex !==
-1) before creating nextItem and calling bookmarks.add('bookmarks', nextItem)
and notifyUpdated(), so only valid indices are inserted.

In `@src/lib/data/history.ts`:
- Around line 54-63: The setTimeout callback closes over shared mutable
variables nextItem and nextTimer causing races in addHistory; fix by capturing
the values into locals when scheduling (e.g., const capturedItem = nextItem;
const capturedTimer = nextTimer) and have the callback reference those
capturedItem/capturedTimer instead of nextItem/nextTimer, remove the
clearTimeout(nextTimer!) call entirely, and only clear the outer
nextItem/nextTimer if they still strictly equal the capturedTimer (to avoid
wiping a newer scheduled entry) after awaiting history.add and invoking
callback.

In `@src/lib/data/notes.ts`:
- Around line 68-73: The condition using `if (bookIndex)` incorrectly treats 0
as falsy; update the check around where `bookIndex` is used (the block that
creates `nextItem`, calls `notes.add('notes', nextItem)` and `notifyUpdated()`)
to allow a valid index of 0 and reject only missing or not-found values by
explicitly testing for undefined and -1 (e.g., ensure `bookIndex !== undefined
&& bookIndex !== -1`), so notes for the first book are added correctly; keep the
rest of the logic (creating `nextItem`, calling `notes.add` and `notifyUpdated`)
unchanged.

In `@src/routes/plans/`+page.ts:
- Around line 4-10: The route's load function currently returns a hardcoded
empty array, dropping persisted plans; replace the placeholder return in export
const load: PageLoad with actual plan retrieval by calling the app's persistent
plan loader (e.g., await getPlans(), getAllPlans(), or loadPlansFromStore) or
fetching the plans endpoint, keep the depends('note:plans') call, and return the
retrieved plans as { plans: fetchedPlans as PlanItem[] } so the route restores
its previous data contract.

---

Outside diff comments:
In `@src/lib/data/stores/storage.ts`:
- Around line 7-21: mergeDefaultStorage currently calls JSON.parse(storage)
without guarding against corrupted/malformed data which can throw; wrap the
parse in a safe try/catch (when storage exists) and if parsing fails treat it as
absent (e.g., set update = value or {}), then proceed with the existing merge
logic and write back to localStorage; specifically modify the
mergeDefaultStorage function to catch JSON.parse errors on the result of
localStorage.getItem(name), use a safe fallback for update, and ensure
localStorage.setItem is called with the correct merged object.

---

Nitpick comments:
In `@src/lib/data/scripture.ts`:
- Around line 14-29: The commented block inside initProskomma references
config.bookCollections but the config import was removed; either delete the dead
commented lines (lines that use config.bookCollections and related docSet logic)
or restore a proper import and add a clear TODO explaining why config is needed
before uncommenting; target the initProskomma function and the commented docSet
logic (the block that builds docSet from config.bookCollections and the
commented loadDocSet call) and ensure any future uncommenting also reintroduces
a matching import for config or documents why the config dependency was removed.

In `@src/lib/data/stores/audio.ts`:
- Line 43: The field declaration "timer: NodeJS.Timeout | null;" is using a
Node-specific type and should be made environment-safe; locate the declaration
named timer and replace its type with a platform-agnostic one such as
"ReturnType<typeof setInterval> | null" (or "ReturnType<typeof setTimeout> |
null") to match the usage of setInterval at runtime, ensuring the rest of the
code (the setInterval/setTimeout calls and any clears) continue to accept the
updated type.

In `@src/lib/data/stores/scripture.ts`:
- Around line 258-288: The fallback objects returned by getVerseByIndex and
getVerseByVerseNumber lack the required Selection.reference field, causing a
type mismatch with the Selection type (defined around Selection). Update the
fallback objects in both functions (getVerseByIndex and getVerseByVerseNumber)
to include a reference property (e.g., reference: '' or other appropriate
default) so the returned object matches the Selection shape.

In `@src/lib/data/stores/view.ts`:
- Around line 128-135: The length() method currently calls update() only to read
the stack length; replace that with a read-only get() usage (imported from
svelte/store) or capture the store's subscribe into a local variable and call
get(stackStore) to obtain stack.length directly; update the length()
implementation to return get(stackStore).length (or use the local subscribe/get
approach) and remove the unnecessary update() call — reference the length()
function and the update/get utilities when making the change.

In `@src/routes/highlights/`+page.svelte:
- Around line 54-58: The Props interface is declared but not applied to the
$props() destructuring; update the destructuring so the data variable is typed
using Props by changing the declaration of let { data } to use the Props type
(i.e., annotate the result of $props() with Props) so the component enforces
type checking for data; locate the Props interface and the let { data } =
$props() line in src/routes/highlights/+page.svelte and add the type annotation
to the destructuring (using Props).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7eed5b73-6d63-4956-8ba8-f0e8325f3077

📥 Commits

Reviewing files that changed from the base of the PR and between 42c744a and d9f9ee2.

📒 Files selected for processing (57)
  • src/lib/components/AudioBar.svelte
  • src/lib/components/PlayButton.svelte
  • src/lib/components/ScriptureViewSofria.svelte
  • src/lib/components/Sidebar.svelte
  • src/lib/components/TextAppearanceSelector.svelte
  • src/lib/data/analytics.ts
  • src/lib/data/audio.ts
  • src/lib/data/bookmarks.ts
  • src/lib/data/highlights.ts
  • src/lib/data/history.ts
  • src/lib/data/notes.ts
  • src/lib/data/planProgressItems.ts
  • src/lib/data/planStates.ts
  • src/lib/data/plans.ts
  • src/lib/data/scripture.ts
  • src/lib/data/stores/annotation.ts
  • src/lib/data/stores/audio.ts
  • src/lib/data/stores/index.ts
  • src/lib/data/stores/interface.ts
  • src/lib/data/stores/localization.js
  • src/lib/data/stores/localization.ts
  • src/lib/data/stores/log.ts
  • src/lib/data/stores/scripture.ts
  • src/lib/data/stores/setting.ts
  • src/lib/data/stores/storage.ts
  • src/lib/data/stores/store-types.js
  • src/lib/data/stores/theme.ts
  • src/lib/data/stores/view.ts
  • src/lib/icons/audio/index.ts
  • src/lib/icons/image/index.ts
  • src/lib/icons/index.ts
  • src/lib/scripts/query.js
  • src/lib/scripts/render.js
  • src/routes/+layout.svelte
  • src/routes/+page.ts
  • src/routes/about/+page.ts
  • src/routes/bookmarks/+page.ts
  • src/routes/contents/[id]/+page.svelte
  • src/routes/contents/[id]/+page.ts
  • src/routes/highlights/+page.svelte
  • src/routes/highlights/+page.ts
  • src/routes/history/+page.ts
  • src/routes/lexicon/+layout.svelte
  • src/routes/notes/+page.svelte
  • src/routes/notes/+page.ts
  • src/routes/notes/edit/[noteid]/+page.svelte
  • src/routes/notes/edit/[noteid]/+page.ts
  • src/routes/plans/+page.ts
  • src/routes/plans/[id]/+page.svelte
  • src/routes/plans/[id]/+page.ts
  • src/routes/plans/[id]/settings/+page.ts
  • src/routes/quiz/[collection]/[id]/+page.svelte
  • src/routes/share/+page.svelte
  • src/routes/share/+page.ts
  • src/routes/text/+page.js
  • src/routes/text/+page.svelte
  • src/routes/text/+page.ts
💤 Files with no reviewable changes (5)
  • src/lib/scripts/query.js
  • src/lib/scripts/render.js
  • src/lib/data/stores/store-types.js
  • src/routes/text/+page.js
  • src/lib/data/stores/localization.js

Comment thread src/lib/data/audio.ts Outdated
Comment thread src/lib/data/bookmarks.ts Outdated
Comment thread src/lib/data/history.ts Outdated
Comment thread src/lib/data/notes.ts Outdated
Comment thread src/routes/plans/+page.ts
Copy link
Copy Markdown
Contributor

@eomerdws eomerdws left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really good work. My comments aren't blocking an approval review, but one is a question for consideration and the other is I like the approach you took in this area. In fact you did it in at least one other place, but I didn't want you to have to resolve it multiple times.

Comment thread src/lib/data/stores/scripture.ts
Comment thread src/lib/data/stores/audio.ts
@FyreByrd FyreByrd merged commit 4e1b087 into main May 20, 2026
4 checks passed
@FyreByrd FyreByrd deleted the refactor/js-to-ts branch May 20, 2026 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants