Skip to content

Commit bd6b1d9

Browse files
committed
setup layout and worker
1 parent 8cbbf9f commit bd6b1d9

File tree

8 files changed

+278
-1
lines changed

8 files changed

+278
-1
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"format": "prettier --plugin-search-dir . --write ."
1313
},
1414
"devDependencies": {
15+
"@rgossiaux/svelte-headlessui": "^1.0.2",
1516
"@sveltejs/adapter-auto": "^2.0.0",
1617
"@sveltejs/kit": "^1.15.0",
1718
"@typescript-eslint/eslint-plugin": "^5.57.0",

src/lib/logger.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'NONE';
3+
4+
const LEVELS: LogLevel[] = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE'];
5+
6+
export default class Logger {
7+
private static instance: Logger;
8+
private logLevel: LogLevel;
9+
10+
private constructor() {
11+
const storedLogLevel = sessionStorage.getItem('logLevel');
12+
13+
if (storedLogLevel && this.isValidLogLevel(storedLogLevel as LogLevel)) {
14+
this.logLevel = storedLogLevel as LogLevel;
15+
} else {
16+
this.logLevel = 'INFO'; // Default log level
17+
sessionStorage.setItem('logLevel', this.logLevel);
18+
}
19+
}
20+
21+
public static getInstance(): Logger {
22+
if (!Logger.instance) {
23+
Logger.instance = new Logger();
24+
}
25+
26+
return Logger.instance;
27+
}
28+
29+
public getAllLevels(): LogLevel[] {
30+
return LEVELS;
31+
}
32+
33+
public getLevel(): LogLevel {
34+
return this.logLevel;
35+
}
36+
37+
private isValidLogLevel(logLevel: LogLevel): boolean {
38+
return LEVELS.includes(logLevel);
39+
}
40+
41+
private shouldLog(level: LogLevel): boolean {
42+
return LEVELS.indexOf(level) >= LEVELS.indexOf(this.logLevel);
43+
}
44+
45+
public debug(message: string, ...args: any[]): void {
46+
if (this.shouldLog('DEBUG')) {
47+
console.debug(`[DEBUG]: ${message}`, ...args);
48+
}
49+
}
50+
51+
public info(message: string, ...args: any[]): void {
52+
if (this.shouldLog('INFO')) {
53+
console.info(`[INFO]: ${message}`, ...args);
54+
}
55+
}
56+
57+
public warn(message: string, ...args: any[]): void {
58+
if (this.shouldLog('WARN')) {
59+
console.warn(`[WARN]: ${message}`, ...args);
60+
}
61+
}
62+
63+
public error(message: string, ...args: any[]): void {
64+
if (this.shouldLog('ERROR')) {
65+
console.error(`[ERROR]: ${message}`, ...args);
66+
}
67+
}
68+
69+
public setLogLevel(level: LogLevel): void {
70+
if (this.isValidLogLevel(level)) {
71+
this.logLevel = level;
72+
this.info(`Log level set to ${level}`);
73+
sessionStorage.setItem('logLevel', level);
74+
} else {
75+
throw new Error(`Invalid log level: ${level}`);
76+
}
77+
}
78+
79+
public getLogLevel(): LogLevel {
80+
return this.logLevel;
81+
}
82+
}

src/lib/sqlite/loadWorker.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { WorkerMessage } from './types';
2+
3+
const workerImp = await import('./worker/worker.ts?worker');
4+
5+
export default function initWorker() {
6+
const worker = new workerImp.default();
7+
8+
const msg: WorkerMessage = { message: 'abc' };
9+
console.log(`Sending message to worker:`, msg);
10+
worker.postMessage(msg);
11+
12+
worker.addEventListener('message', async ({ data }: { data: WorkerMessage }) => {
13+
console.log('Received message from worker:', data.message);
14+
});
15+
}

src/lib/sqlite/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type WorkerMessage = {
2+
message: string;
3+
};

src/lib/sqlite/worker/worker.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { WorkerMessage } from '../types';
2+
3+
console.log('worker loaded');
4+
5+
(async function () {
6+
addEventListener('message', async function ({ data }: { data: WorkerMessage }) {
7+
console.log('worker received message:', data.message);
8+
9+
const res: WorkerMessage = { message: 'xyz' };
10+
console.log('worker sending message back to main:', res);
11+
this.postMessage(res);
12+
});
13+
})();

src/routes/+layout.svelte

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
11
<script>
22
import '../app.css';
3+
import SettingsModal from './SettingsModal.svelte';
4+
import initWorker from '$lib/sqlite/loadWorker';
5+
import { onMount } from 'svelte';
6+
7+
let isOpen = false;
8+
9+
onMount(() => {
10+
initWorker();
11+
});
312
</script>
413

5-
<slot />
14+
<div class="min-h-screen flex flex-col">
15+
<header class="bg-indigo-600 px-2 py-1 flex justify-between items-center">
16+
<div>
17+
<span class="text-2xl font-semibold text-white">SvelteKit Offline</span>
18+
</div>
19+
<div>
20+
<button
21+
class="text-white h-8 w-8 flex items-center hover:text-indigo-200 focus:outline-none focus:ring-1 focus:ring-pink-300 p-1 rounded-md"
22+
on:click={() => (isOpen = true)}
23+
><svg
24+
fill="currentColor"
25+
viewBox="0 0 24 24"
26+
xmlns="http://www.w3.org/2000/svg"
27+
aria-hidden="true"
28+
>
29+
<path
30+
clip-rule="evenodd"
31+
fill-rule="evenodd"
32+
d="M11.078 2.25c-.917 0-1.699.663-1.85 1.567L9.05 4.889c-.02.12-.115.26-.297.348a7.493 7.493 0 00-.986.57c-.166.115-.334.126-.45.083L6.3 5.508a1.875 1.875 0 00-2.282.819l-.922 1.597a1.875 1.875 0 00.432 2.385l.84.692c.095.078.17.229.154.43a7.598 7.598 0 000 1.139c.015.2-.059.352-.153.43l-.841.692a1.875 1.875 0 00-.432 2.385l.922 1.597a1.875 1.875 0 002.282.818l1.019-.382c.115-.043.283-.031.45.082.312.214.641.405.985.57.182.088.277.228.297.35l.178 1.071c.151.904.933 1.567 1.85 1.567h1.844c.916 0 1.699-.663 1.85-1.567l.178-1.072c.02-.12.114-.26.297-.349.344-.165.673-.356.985-.57.167-.114.335-.125.45-.082l1.02.382a1.875 1.875 0 002.28-.819l.923-1.597a1.875 1.875 0 00-.432-2.385l-.84-.692c-.095-.078-.17-.229-.154-.43a7.614 7.614 0 000-1.139c-.016-.2.059-.352.153-.43l.84-.692c.708-.582.891-1.59.433-2.385l-.922-1.597a1.875 1.875 0 00-2.282-.818l-1.02.382c-.114.043-.282.031-.449-.083a7.49 7.49 0 00-.985-.57c-.183-.087-.277-.227-.297-.348l-.179-1.072a1.875 1.875 0 00-1.85-1.567h-1.843zM12 15.75a3.75 3.75 0 100-7.5 3.75 3.75 0 000 7.5z"
33+
/>
34+
</svg>
35+
</button>
36+
</div>
37+
</header>
38+
<main class="flex-grow">
39+
<slot />
40+
<SettingsModal bind:isOpen />
41+
</main>
42+
<footer>...</footer>
43+
</div>

src/routes/SettingsModal.svelte

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<script lang="ts">
2+
import Logger, { type LogLevel } from '$lib/logger';
3+
import {
4+
Dialog,
5+
DialogOverlay,
6+
DialogTitle,
7+
DialogDescription,
8+
TransitionChild,
9+
Transition
10+
} from '@rgossiaux/svelte-headlessui';
11+
import { onMount } from 'svelte';
12+
13+
export let isOpen: boolean;
14+
let allLevels: LogLevel[];
15+
let currLevel: LogLevel;
16+
let logger: Logger;
17+
18+
onMount(() => {
19+
logger = Logger.getInstance();
20+
21+
allLevels = logger.getAllLevels();
22+
currLevel = logger.getLevel();
23+
});
24+
</script>
25+
26+
<Transition show={isOpen}>
27+
<Dialog class="relative z-10" on:close={() => (isOpen = false)}>
28+
<!-- Use one `TransitionChild` to apply one transition to the overlay... -->
29+
<TransitionChild
30+
enter="ease-out duration-300"
31+
enterFrom="opacity-0"
32+
enterTo="opacity-100"
33+
leave="ease-in duration-200"
34+
leaveFrom="opacity-100"
35+
leaveTo="opacity-0"
36+
>
37+
<DialogOverlay class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
38+
</TransitionChild>
39+
40+
<div class="fixed inset-0 z-10 overflow-y-auto">
41+
<div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
42+
<TransitionChild
43+
enter="ease-out duration-300"
44+
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
45+
enterTo="opacity-100 translate-y-0 sm:scale-100"
46+
leave="ease-in duration-200"
47+
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
48+
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
49+
>
50+
<div
51+
class="relative transform overflow-hidden min-w-[480px] rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6"
52+
>
53+
<div class="flex justify-between items-center">
54+
<DialogTitle
55+
><h3 class="text-2xl font-semibold text-black">Preferences</h3></DialogTitle
56+
>
57+
<button
58+
type="button"
59+
class="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-pink-300 focus:ring-offset-2"
60+
on:click={() => (isOpen = false)}
61+
>
62+
<span class="sr-only">Close</span>
63+
<div class="h-6 w-6" aria-hidden="true">
64+
<svg
65+
fill="currentColor"
66+
viewBox="0 0 24 24"
67+
xmlns="http://www.w3.org/2000/svg"
68+
aria-hidden="true"
69+
>
70+
<path
71+
clip-rule="evenodd"
72+
fill-rule="evenodd"
73+
d="M5.47 5.47a.75.75 0 011.06 0L12 10.94l5.47-5.47a.75.75 0 111.06 1.06L13.06 12l5.47 5.47a.75.75 0 11-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 01-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 010-1.06z"
74+
/>
75+
</svg>
76+
</div>
77+
</button>
78+
</div>
79+
<div class="mt-4">
80+
<fieldset>
81+
<legend class="text-sm font-semibold leading-6 text-gray-900">Log Level</legend>
82+
<p class="mt-1 text-sm leading-6 text-gray-600">
83+
Choose the level of logs to display in console.
84+
</p>
85+
<div class="mt-1 space-y-1">
86+
{#each allLevels as level}
87+
<div class="flex items-center gap-x-3">
88+
<input
89+
id="pref-{level}"
90+
name="pref-loglevel"
91+
type="radio"
92+
class="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-600"
93+
bind:group={currLevel}
94+
value={level}
95+
on:change={() => {
96+
logger.setLogLevel(currLevel);
97+
}}
98+
/>
99+
<label
100+
for="pref-{level}"
101+
class="block text-sm font-medium leading-6 text-gray-700"
102+
>
103+
{level}
104+
</label>
105+
</div>
106+
{/each}
107+
</div>
108+
</fieldset>
109+
</div>
110+
</div>
111+
</TransitionChild>
112+
</div>
113+
</div>
114+
</Dialog>
115+
</Transition>

yarn.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,15 @@ __metadata:
311311
languageName: node
312312
linkType: hard
313313

314+
"@rgossiaux/svelte-headlessui@npm:^1.0.2":
315+
version: 1.0.2
316+
resolution: "@rgossiaux/svelte-headlessui@npm:1.0.2"
317+
peerDependencies:
318+
svelte: ^3.44.0
319+
checksum: 54c256923a29beaa70dd271332ca89fc7dd251cd53da42f12fa8ff73f1abf7c82a90266d50fd40442a476c74466908f2a77e3aa086f9ad1073bb46d167f04504
320+
languageName: node
321+
linkType: hard
322+
314323
"@sveltejs/adapter-auto@npm:^2.0.0":
315324
version: 2.0.0
316325
resolution: "@sveltejs/adapter-auto@npm:2.0.0"
@@ -2692,6 +2701,7 @@ __metadata:
26922701
version: 0.0.0-use.local
26932702
resolution: "sk-offline-test-app@workspace:."
26942703
dependencies:
2704+
"@rgossiaux/svelte-headlessui": ^1.0.2
26952705
"@sveltejs/adapter-auto": ^2.0.0
26962706
"@sveltejs/kit": ^1.15.0
26972707
"@typescript-eslint/eslint-plugin": ^5.57.0

0 commit comments

Comments
 (0)