Skip to content

Commit 24bd165

Browse files
authored
Convert svelte components and pages to TS (#961)
* Convert components to TS * Fix leftover component issues * Convert pages to TS * Fix local state warnings * CR feedback * Fix default language fallback * Fix bad options passed to TabsMenu
1 parent 4e1b087 commit 24bd165

56 files changed

Lines changed: 1099 additions & 1204 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

config/index.d.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export type BookTabConfig = {
2222
bookTabID: string;
2323
type: string;
2424
file: string;
25-
features: any;
25+
features: FeatureConfig;
2626
chapters?: number;
2727
chaptersN?: string;
2828
style?: StyleConfig;
@@ -78,7 +78,7 @@ export type BookConfig = {
7878

7979
export type BookCollectionConfig = {
8080
id: string;
81-
features: any;
81+
features: FeatureConfig;
8282
books: BookConfig[];
8383
style?: StyleConfig;
8484
fonts: string[];
@@ -251,7 +251,7 @@ export type AppConfig = {
251251

252252
export type ScriptureConfig = AppConfig & {
253253
programType: 'SAB';
254-
traits?: any;
254+
traits?: FeatureConfig;
255255
bookCollections?: BookCollectionConfig[];
256256
videos?: {
257257
id: string;
@@ -304,20 +304,22 @@ export type ScriptureConfig = AppConfig & {
304304
features: {
305305
[key: string]: string;
306306
};
307-
plans: {
308-
id: string;
309-
days: number;
310-
title: {
311-
[lang: string]: string;
312-
};
313-
filename: string;
314-
jsonFilename: string;
315-
image?: {
316-
width: number;
317-
height: number;
318-
file: string;
319-
};
320-
}[];
307+
plans: PlanItem[];
308+
};
309+
};
310+
311+
export type PlanItem = {
312+
id: string;
313+
days: number;
314+
title: {
315+
[lang: string]: string;
316+
};
317+
filename: string;
318+
jsonFilename: string;
319+
image?: {
320+
width: number;
321+
height: number;
322+
file: string;
321323
};
322324
};
323325

@@ -396,7 +398,7 @@ export type LinkMeta = {
396398
export type ContentItem = {
397399
id: number;
398400
heading?: boolean;
399-
features?: any;
401+
features?: FeatureConfig;
400402
title: LangContainer;
401403
subtitle?: LangContainer;
402404
audioFilename?: LangContainer;
@@ -425,7 +427,7 @@ export type ContentsData = {
425427
title?: {
426428
[lang: string]: string;
427429
};
428-
features?: any;
430+
features?: FeatureConfig;
429431
items?: ContentItem[];
430432
nestedItems?: boolean;
431433
screens?: ContentScreen[];

convert/convertBooks.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ export async function convertBooks(
466466
//loop through books in collection
467467
const ignoredBooks = [];
468468
// If the collection has a glossary, load it
469-
if (scriptureConfig.traits['has-glossary']) {
469+
if (scriptureConfig.traits?.['has-glossary']) {
470470
bcGlossary = loadGlossary(collection, dataDir);
471471
}
472472
//add empty array of quizzes for book collection
@@ -777,7 +777,7 @@ function convertScriptureBook(
777777
'\n' +
778778
remainingLines;
779779
}
780-
if (context.scriptureConfig.traits['has-glossary']) {
780+
if (context.scriptureConfig.traits?.['has-glossary']) {
781781
content = verifyGlossaryEntries(content, bcGlossary);
782782
}
783783
if (context.scriptureConfig.mainFeatures['hide-empty-verses'] === true) {

convert/convertConfig.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,10 @@ function convertConfig(dataDir: string, verbose: number) {
337337
if (videos.length > 0) {
338338
data.videos = videos;
339339
}
340-
data.traits['has-video'] = data.videos && data.videos.length > 0;
340+
const hasVideo = !!data.videos && data.videos.length > 0;
341+
data.traits = data.traits
342+
? { ...data.traits, 'has-video': hasVideo }
343+
: { 'has-video': hasVideo };
341344
data.illustrations = parseIllustrations(document, verbose);
342345

343346
const { layouts, defaultLayout } = parseLayouts(document, data.bookCollections, verbose);

src/app.d.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// <reference types="@sveltejs/kit" />
22
/// <reference types="svelte-gestures" />
33
/// <reference types="$config" />
4+
/// <reference types="svelte" />
45

56
// See https://kit.svelte.dev/docs/types#app
67
// for information about these interfaces
@@ -40,14 +41,16 @@ declare namespace App {
4041
penColor: string;
4142
}
4243

44+
type MenuActionHandler = (args: { text: string; url: string }) => void;
45+
46+
type TabMenuActionHandler = (args: { text: string; url: string; tab: string }) => void;
47+
4348
interface TabMenuOptions {
4449
[key: string]: {
4550
tab?: {
46-
component: any;
47-
props?: any;
51+
icon?: Snippet<[string]>;
4852
};
49-
component: any;
50-
props: any;
53+
snippet?: Snippet<[string, TabMenuActionHandler]>;
5154
visible: boolean;
5255
};
5356
}
@@ -75,8 +78,8 @@ declare namespace App {
7578

7679
interface CollectionGroup {
7780
singlePane?: CollectionEntry;
78-
sideBySide?: FixedLengthArray<[CollectionEntry, CollectionEntry]>;
79-
verseByVerse?: FixedLengthArray<[CollectionEntry, CollectionEntry, CollectionEntry]>;
81+
sideBySide?: [CollectionEntry, CollectionEntry];
82+
verseByVerse?: [CollectionEntry, CollectionEntry, CollectionEntry];
8083
}
8184

8285
interface UserPreferenceSetting {

src/lib/components/AudioBar.svelte

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,32 +25,34 @@ TODO:
2525
refs,
2626
s,
2727
t,
28-
userSettings
28+
userSettings,
29+
type PlayModeSettings
2930
} from '$lib/data/stores';
3031
import { AudioIcon } from '$lib/icons';
3132
import PlayButton from './PlayButton.svelte';
3233
import RepeatButton from './RepeatButton.svelte';
3334
34-
function mayResetPlayMode(hasTiming) {
35+
function mayResetPlayMode(hasTiming: boolean) {
3536
// If the current mode is repeatSelection and the reference is changed to something without timing
3637
// (even chapter without audio), then reset the playMode. This matches how the Android app behaves.
3738
if (!hasTiming && $playMode.mode === 'repeatSelection') {
3839
playMode.reset();
3940
}
4041
}
4142
42-
function seekAudio(event) {
43+
function seekAudio(event: MouseEvent) {
4344
if (!$audioPlayer.loaded) {
4445
return;
4546
}
4647
const progressBar = document.getElementById('progress-bar');
47-
const percent = (event.clientX - progressBar.offsetLeft) / progressBar.offsetWidth;
48+
const percent =
49+
(event.clientX - (progressBar?.offsetLeft ?? 0)) / (progressBar?.offsetWidth ?? 1);
4850
// Set the current time of the audio element to the corresponding time based on the percent
4951
seek($audioPlayer.duration * percent);
5052
}
5153
5254
let lastPlayMode = '';
53-
function playModeChanged(value) {
55+
function playModeChanged(value: PlayModeSettings) {
5456
let key = '';
5557
5658
switch (value.mode) {
@@ -77,8 +79,8 @@ TODO:
7779
7880
let hintText = $state('');
7981
let showHint = $state(false);
80-
let hintTimeoutId = null;
81-
function startShowHint(text) {
82+
let hintTimeoutId: NodeJS.Timeout | null = null;
83+
function startShowHint(text: string) {
8284
showHint = true;
8385
hintText = text;
8486
if (hintTimeoutId) {
@@ -92,14 +94,14 @@ TODO:
9294
9395
const showSpeed = config.mainFeatures['settings-audio-speed'];
9496
const showRepeatMode = config.mainFeatures['audio-repeat-mode-button'];
95-
const hintStyle = convertStyle($s['ui.bar.audio.hint.text']);
97+
const hintStyle = convertStyle($s?.['ui.bar.audio.hint.text']);
9698
const playButtonState = $derived($audioPlayer.playing ? 'pause' : 'play');
97-
const iconColor = $derived($s['ui.bar.audio.icon']['color']);
98-
const iconPlayColor = $derived($s['ui.bar.audio.play.icon']['color']);
99-
const backgroundColor = $derived($s['ui.bar.audio']['background-color']);
99+
const iconColor = $derived($s?.['ui.bar.audio.icon']['color']);
100+
const iconPlayColor = $derived($s?.['ui.bar.audio.play.icon']['color']);
101+
const backgroundColor = $derived($s?.['ui.bar.audio']['background-color']);
100102
const audioBarClass = $derived($refs.hasAudio?.timingFile ? 'audio-bar' : 'audio-bar-progress');
101103
$effect(() => mayResetPlayMode($refs.hasAudio?.timing));
102-
$effect(() => updatePlaybackSpeed($userSettings['audio-speed']));
104+
$effect(() => updatePlaybackSpeed($userSettings['audio-speed'] as string));
103105
</script>
104106

105107
<div class="relative {audioBarClass}" style:background-color={backgroundColor}>

src/lib/components/AudioPlaybackSpeed.svelte

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<script>
1+
<script lang="ts">
22
import { monoIconColor, t, userSettings } from '$lib/data/stores';
33
import Modal from './Modal.svelte';
44
@@ -19,17 +19,17 @@
1919
{ value: '1.6', label: '1.6x' }
2020
];
2121
22-
function setPlaySpeed(event) {
23-
$userSettings['audio-speed'] = event.target.value;
22+
function setPlaySpeed(value: string) {
23+
$userSettings['audio-speed'] = value;
2424
}
2525
26-
let modalThis;
26+
let modalThis: HTMLDialogElement;
2727
export function showModal() {
2828
modalThis.showModal();
2929
}
3030
</script>
3131

32-
<Modal bind:this={modalThis} id={modalId}>
32+
<Modal bind:dialog={modalThis} id={modalId}>
3333
<div style="color: {$monoIconColor}">
3434
<h1>
3535
<b>{$t['Settings_Audio_Speed']}</b>
@@ -41,7 +41,7 @@
4141
type="radio"
4242
name="speed"
4343
{value}
44-
on:click={setPlaySpeed}
44+
on:click={(e) => setPlaySpeed(e.currentTarget.value)}
4545
checked={$userSettings['audio-speed'] === value}
4646
/>
4747
{label}

0 commit comments

Comments
 (0)