feat: show message when loading the database
This commit is contained in:
parent
dbd0b12b3d
commit
84b5ef9755
12 changed files with 99 additions and 150 deletions
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -7,4 +7,4 @@
|
|||
"editor.formatOnSave": true
|
||||
},
|
||||
"typescript.inlayHints.parameterNames.enabled": "all"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
"noUnreachable": "error",
|
||||
"noUnreachableSuper": "error",
|
||||
"noUnsafeFinally": "error",
|
||||
"noUnusedImports": "error",
|
||||
"noUnsafeOptionalChaining": "error",
|
||||
"noUnusedLabels": "error",
|
||||
"noUnusedPrivateClassMembers": "error",
|
||||
|
@ -107,13 +108,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"ignore": [
|
||||
"dist/**/*.ts",
|
||||
"dist/**",
|
||||
"**/*.mjs",
|
||||
"eslint.config.js",
|
||||
"**/*.js"
|
||||
]
|
||||
"ignore": ["dist/**/*.ts", "dist/**", "**/*.mjs", "eslint.config.js", "**/*.js"]
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { type Component } from "solid-js";
|
||||
import { Route } from "@solidjs/router";
|
||||
|
||||
import { allThreadsOverviewQuery } from "./db";
|
||||
import { DmId, GroupId, Home, Overview } from "./pages";
|
||||
|
||||
import "./app.css";
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
import type { Component, ComponentProps } from "solid-js"
|
||||
import { mergeProps, splitProps } from "solid-js"
|
||||
import type { Component, ComponentProps } from "solid-js";
|
||||
import { mergeProps, splitProps } from "solid-js";
|
||||
|
||||
import { cn } from "~/lib/utils"
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
type Cols = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
|
||||
type Span = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13
|
||||
type Cols = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||
type Span = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13;
|
||||
|
||||
type GridProps = ComponentProps<"div"> & {
|
||||
cols?: Cols
|
||||
colsSm?: Cols
|
||||
colsMd?: Cols
|
||||
colsLg?: Cols
|
||||
}
|
||||
cols?: Cols;
|
||||
colsSm?: Cols;
|
||||
colsMd?: Cols;
|
||||
colsLg?: Cols;
|
||||
};
|
||||
|
||||
const Grid: Component<GridProps> = (rawProps) => {
|
||||
const props = mergeProps({ cols: 1 } satisfies GridProps, rawProps)
|
||||
const [local, others] = splitProps(props, ["cols", "colsSm", "colsMd", "colsLg", "class"])
|
||||
const props = mergeProps({ cols: 1 } satisfies GridProps, rawProps);
|
||||
const [local, others] = splitProps(props, ["cols", "colsSm", "colsMd", "colsLg", "class"]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -25,23 +25,23 @@ const Grid: Component<GridProps> = (rawProps) => {
|
|||
local.colsSm && gridColsSm[local.colsSm],
|
||||
local.colsMd && gridColsMd[local.colsMd],
|
||||
local.colsLg && gridColsLg[local.colsLg],
|
||||
local.class
|
||||
local.class,
|
||||
)}
|
||||
{...others}
|
||||
/>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
type ColProps = ComponentProps<"div"> & {
|
||||
span?: Span
|
||||
spanSm?: Span
|
||||
spanMd?: Span
|
||||
spanLg?: Span
|
||||
}
|
||||
span?: Span;
|
||||
spanSm?: Span;
|
||||
spanMd?: Span;
|
||||
spanLg?: Span;
|
||||
};
|
||||
|
||||
const Col: Component<ColProps> = (rawProps) => {
|
||||
const props = mergeProps({ span: 1 as Span }, rawProps)
|
||||
const [local, others] = splitProps(props, ["span", "spanSm", "spanMd", "spanLg", "class"])
|
||||
const props = mergeProps({ span: 1 as Span }, rawProps);
|
||||
const [local, others] = splitProps(props, ["span", "spanSm", "spanMd", "spanLg", "class"]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -50,14 +50,14 @@ const Col: Component<ColProps> = (rawProps) => {
|
|||
local.spanSm && colSpanSm[local.spanSm],
|
||||
local.spanMd && colSpanMd[local.spanMd],
|
||||
local.spanLg && colSpanLg[local.spanLg],
|
||||
local.class
|
||||
local.class,
|
||||
)}
|
||||
{...others}
|
||||
/>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export { Grid, Col }
|
||||
export { Grid, Col };
|
||||
|
||||
const gridCols: { [key in Cols]: string } = {
|
||||
0: "grid-cols-none",
|
||||
|
@ -72,8 +72,8 @@ const gridCols: { [key in Cols]: string } = {
|
|||
9: "grid-cols-9",
|
||||
10: "grid-cols-10",
|
||||
11: "grid-cols-11",
|
||||
12: "grid-cols-12"
|
||||
}
|
||||
12: "grid-cols-12",
|
||||
};
|
||||
|
||||
const gridColsSm: { [key in Cols]: string } = {
|
||||
0: "sm:grid-cols-none",
|
||||
|
@ -88,8 +88,8 @@ const gridColsSm: { [key in Cols]: string } = {
|
|||
9: "sm:grid-cols-9",
|
||||
10: "sm:grid-cols-10",
|
||||
11: "sm:grid-cols-11",
|
||||
12: "sm:grid-cols-12"
|
||||
}
|
||||
12: "sm:grid-cols-12",
|
||||
};
|
||||
|
||||
const gridColsMd: { [key in Cols]: string } = {
|
||||
0: "md:grid-cols-none",
|
||||
|
@ -104,8 +104,8 @@ const gridColsMd: { [key in Cols]: string } = {
|
|||
9: "md:grid-cols-9",
|
||||
10: "md:grid-cols-10",
|
||||
11: "md:grid-cols-11",
|
||||
12: "md:grid-cols-12"
|
||||
}
|
||||
12: "md:grid-cols-12",
|
||||
};
|
||||
|
||||
const gridColsLg: { [key in Cols]: string } = {
|
||||
0: "lg:grid-cols-none",
|
||||
|
@ -120,8 +120,8 @@ const gridColsLg: { [key in Cols]: string } = {
|
|||
9: "lg:grid-cols-9",
|
||||
10: "lg:grid-cols-10",
|
||||
11: "lg:grid-cols-11",
|
||||
12: "lg:grid-cols-12"
|
||||
}
|
||||
12: "lg:grid-cols-12",
|
||||
};
|
||||
|
||||
const colSpan: { [key in Span]: string } = {
|
||||
1: "col-span-1",
|
||||
|
@ -136,8 +136,8 @@ const colSpan: { [key in Span]: string } = {
|
|||
10: "col-span-10",
|
||||
11: "col-span-11",
|
||||
12: "col-span-12",
|
||||
13: "col-span-13"
|
||||
}
|
||||
13: "col-span-13",
|
||||
};
|
||||
|
||||
const colSpanSm: { [key in Span]: string } = {
|
||||
1: "sm:col-span-1",
|
||||
|
@ -152,8 +152,8 @@ const colSpanSm: { [key in Span]: string } = {
|
|||
10: "sm:col-span-10",
|
||||
11: "sm:col-span-11",
|
||||
12: "sm:col-span-12",
|
||||
13: "sm:col-span-13"
|
||||
}
|
||||
13: "sm:col-span-13",
|
||||
};
|
||||
|
||||
const colSpanMd: { [key in Span]: string } = {
|
||||
1: "md:col-span-1",
|
||||
|
@ -168,8 +168,8 @@ const colSpanMd: { [key in Span]: string } = {
|
|||
10: "md:col-span-10",
|
||||
11: "md:col-span-11",
|
||||
12: "md:col-span-12",
|
||||
13: "md:col-span-13"
|
||||
}
|
||||
13: "md:col-span-13",
|
||||
};
|
||||
|
||||
const colSpanLg: { [key in Span]: string } = {
|
||||
1: "lg:col-span-1",
|
||||
|
@ -184,5 +184,5 @@ const colSpanLg: { [key in Span]: string } = {
|
|||
10: "lg:col-span-10",
|
||||
11: "lg:col-span-11",
|
||||
12: "lg:col-span-12",
|
||||
13: "lg:col-span-13"
|
||||
}
|
||||
13: "lg:col-span-13",
|
||||
};
|
||||
|
|
59
src/db.ts
59
src/db.ts
|
@ -1,12 +1,4 @@
|
|||
import {
|
||||
type Accessor,
|
||||
createEffect,
|
||||
createMemo,
|
||||
createRoot,
|
||||
createSignal,
|
||||
DEV,
|
||||
type Setter,
|
||||
} from "solid-js";
|
||||
import { type Accessor, createEffect, createMemo, createRoot, createSignal, DEV, type Setter } from "solid-js";
|
||||
|
||||
import { Kysely, type NotNull, sql } from "kysely";
|
||||
import type { DB } from "kysely-codegen";
|
||||
|
@ -79,19 +71,13 @@ const allThreadsOverviewQueryRaw = kyselyDb()
|
|||
(eb) =>
|
||||
eb
|
||||
.selectFrom("message")
|
||||
.select((eb) => [
|
||||
"message.thread_id",
|
||||
eb.fn.countAll().as("message_count"),
|
||||
])
|
||||
.select((eb) => ["message.thread_id", eb.fn.countAll().as("message_count")])
|
||||
.where((eb) => {
|
||||
return eb.and([
|
||||
eb("message.body", "is not", null),
|
||||
eb("message.body", "is not", ""),
|
||||
]);
|
||||
return eb.and([eb("message.body", "is not", null), eb("message.body", "is not", "")]);
|
||||
})
|
||||
.groupBy("message.thread_id")
|
||||
.as("message"),
|
||||
(join) => join.onRef("message.thread_id", "=", "thread._id")
|
||||
(join) => join.onRef("message.thread_id", "=", "thread._id"),
|
||||
)
|
||||
.innerJoin("recipient", "thread.recipient_id", "recipient._id")
|
||||
.leftJoin("groups", "recipient._id", "groups.recipient_id")
|
||||
|
@ -114,9 +100,7 @@ const allThreadsOverviewQueryRaw = kyselyDb()
|
|||
}>()
|
||||
.compile();
|
||||
|
||||
export const allThreadsOverviewQuery = cached(() =>
|
||||
kyselyDb().executeQuery(allThreadsOverviewQueryRaw)
|
||||
);
|
||||
export const allThreadsOverviewQuery = cached(() => kyselyDb().executeQuery(allThreadsOverviewQueryRaw));
|
||||
|
||||
const overallSentMessagesQueryRaw = (recipientId: number) =>
|
||||
kyselyDb()
|
||||
|
@ -127,7 +111,7 @@ const overallSentMessagesQueryRaw = (recipientId: number) =>
|
|||
eb("message.from_recipient_id", "=", recipientId),
|
||||
eb("message.body", "is not", null),
|
||||
eb("message.body", "!=", ""),
|
||||
])
|
||||
]),
|
||||
)
|
||||
.executeTakeFirst();
|
||||
|
||||
|
@ -143,9 +127,7 @@ const dmPartnerRecipientQueryRaw = (dmId: number) =>
|
|||
"recipient.nickname_joined_name",
|
||||
])
|
||||
.innerJoin("thread", "recipient._id", "thread.recipient_id")
|
||||
.where((eb) =>
|
||||
eb.and([eb("thread._id", "=", dmId), eb("recipient._id", "!=", SELF_ID)])
|
||||
)
|
||||
.where((eb) => eb.and([eb("thread._id", "=", dmId), eb("recipient._id", "!=", SELF_ID)]))
|
||||
.$narrowType<{
|
||||
_id: number;
|
||||
}>()
|
||||
|
@ -156,25 +138,12 @@ export const dmPartnerRecipientQuery = cached(dmPartnerRecipientQueryRaw);
|
|||
const threadSentMessagesOverviewQueryRaw = (threadId: number) =>
|
||||
kyselyDb()
|
||||
.selectFrom("message")
|
||||
.select([
|
||||
"from_recipient_id",
|
||||
sql<string>`datetime(date_sent / 1000, 'unixepoch')`.as(
|
||||
"message_datetime"
|
||||
),
|
||||
])
|
||||
.select(["from_recipient_id", sql<string>`datetime(date_sent / 1000, 'unixepoch')`.as("message_datetime")])
|
||||
.orderBy(["message_datetime"])
|
||||
.where((eb) =>
|
||||
eb.and([
|
||||
eb("body", "is not", null),
|
||||
eb("body", "!=", ""),
|
||||
eb("thread_id", "=", threadId),
|
||||
])
|
||||
)
|
||||
.where((eb) => eb.and([eb("body", "is not", null), eb("body", "!=", ""), eb("thread_id", "=", threadId)]))
|
||||
.execute();
|
||||
|
||||
export const threadSentMessagesOverviewQuery = cached(
|
||||
threadSentMessagesOverviewQueryRaw
|
||||
);
|
||||
export const threadSentMessagesOverviewQuery = cached(threadSentMessagesOverviewQueryRaw);
|
||||
|
||||
const threadMostUsedWordsQueryRaw = (threadId: number, limit = 10) =>
|
||||
kyselyDb()
|
||||
|
@ -185,16 +154,12 @@ const threadMostUsedWordsQueryRaw = (threadId: number, limit = 10) =>
|
|||
sql`LOWER(substr(body, 1, instr(body || " ", " ") - 1))`.as("word"),
|
||||
sql`(substr(body, instr(body || " ", " ") + 1))`.as("rest"),
|
||||
])
|
||||
.where((eb) =>
|
||||
eb.and([eb("body", "is not", null), eb("thread_id", "=", threadId)])
|
||||
)
|
||||
.where((eb) => eb.and([eb("body", "is not", null), eb("thread_id", "=", threadId)]))
|
||||
.unionAll((ebInner) => {
|
||||
return ebInner
|
||||
.selectFrom("words")
|
||||
.select([
|
||||
sql`LOWER(substr(rest, 1, instr(rest || " ", " ") - 1))`.as(
|
||||
"word"
|
||||
),
|
||||
sql`LOWER(substr(rest, 1, instr(rest || " ", " ") - 1))`.as("word"),
|
||||
sql`(substr(rest, instr(rest || " ", " ") + 1))`.as("rest"),
|
||||
])
|
||||
.where("rest", "<>", "");
|
||||
|
|
|
@ -10,18 +10,14 @@ export const getDistanceBetweenDatesInDays = (a: Date, b: Date) => {
|
|||
};
|
||||
|
||||
// https://dev.to/pretaporter/how-to-get-month-list-in-your-language-4lfb
|
||||
export const getMonthList = (
|
||||
locales?: string | string[],
|
||||
format: "long" | "short" = "long"
|
||||
): string[] => {
|
||||
export const getMonthList = (locales?: string | string[], format: "long" | "short" = "long"): string[] => {
|
||||
const year = new Date().getFullYear(); // 2020
|
||||
const monthList = [...Array(12).keys()]; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
const formatter = new Intl.DateTimeFormat(locales, {
|
||||
month: format,
|
||||
});
|
||||
|
||||
const getMonthName = (monthIndex: number) =>
|
||||
formatter.format(new Date(year, monthIndex));
|
||||
const getMonthName = (monthIndex: number) => formatter.format(new Date(year, monthIndex));
|
||||
|
||||
return monthList.map(getMonthName);
|
||||
};
|
||||
|
@ -48,10 +44,7 @@ export const getDateList = (startDate: Date, endDate: Date): Date[] => {
|
|||
return dateArray;
|
||||
};
|
||||
|
||||
export const getHourList = (
|
||||
locales?: string | string[],
|
||||
format: "numeric" | "2-digit" = "numeric"
|
||||
): string[] => {
|
||||
export const getHourList = (locales?: string | string[], format: "numeric" | "2-digit" = "numeric"): string[] => {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = now.getMonth();
|
||||
|
@ -63,16 +56,12 @@ export const getHourList = (
|
|||
hourCycle: "h11",
|
||||
});
|
||||
|
||||
const getHourName = (hourIndex: number) =>
|
||||
formatter.format(new Date(year, month, day, hourIndex));
|
||||
const getHourName = (hourIndex: number) => formatter.format(new Date(year, month, day, hourIndex));
|
||||
|
||||
return hourList.map(getHourName);
|
||||
};
|
||||
|
||||
export const getWeekdayList = (
|
||||
locales?: string | string[],
|
||||
format: "long" | "short" | "narrow" = "long"
|
||||
): string[] => {
|
||||
export const getWeekdayList = (locales?: string | string[], format: "long" | "short" | "narrow" = "long"): string[] => {
|
||||
const monday = new Date();
|
||||
// set day to monday (w/o +1 it would be sunday)
|
||||
monday.setDate(monday.getDate() - monday.getDay() + 1);
|
||||
|
@ -86,8 +75,7 @@ export const getWeekdayList = (
|
|||
weekday: format,
|
||||
});
|
||||
|
||||
const getWeekDayName = (weekDayIndex: number) =>
|
||||
formatter.format(new Date(year, month, mondayDate + weekDayIndex));
|
||||
const getWeekDayName = (weekDayIndex: number) => formatter.format(new Date(year, month, mondayDate + weekDayIndex));
|
||||
|
||||
return hourList.map(getWeekDayName);
|
||||
};
|
||||
|
|
|
@ -36,9 +36,7 @@ createRoot(() => {
|
|||
createDeferred(
|
||||
on(db, (currentDb) => {
|
||||
if (currentDb) {
|
||||
const newHash = hashString(
|
||||
new TextDecoder().decode(currentDb.export())
|
||||
).toString();
|
||||
const newHash = hashString(new TextDecoder().decode(currentDb.export())).toString();
|
||||
|
||||
const oldHash = localStorage.getItem(HASH_STORE_KEY);
|
||||
|
||||
|
@ -48,15 +46,13 @@ createRoot(() => {
|
|||
localStorage.setItem(HASH_STORE_KEY, newHash);
|
||||
}
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
class LocalStorageCacheAdapter {
|
||||
keys = new Set<string>(
|
||||
Object.keys(localStorage).filter((key) => key.startsWith(this.prefix))
|
||||
);
|
||||
keys = new Set<string>(Object.keys(localStorage).filter((key) => key.startsWith(this.prefix)));
|
||||
prefix = "database";
|
||||
|
||||
#createKey(cacheName: string, key: string): string {
|
||||
|
@ -70,10 +66,7 @@ class LocalStorageCacheAdapter {
|
|||
try {
|
||||
localStorage.setItem(fullKey, JSON.stringify(value));
|
||||
} catch (error: unknown) {
|
||||
if (
|
||||
error instanceof DOMException &&
|
||||
error.name === "QUOTA_EXCEEDED_ERR"
|
||||
) {
|
||||
if (error instanceof DOMException && error.name === "QUOTA_EXCEEDED_ERR") {
|
||||
console.error("Storage quota exceeded, not caching new function calls");
|
||||
}
|
||||
}
|
||||
|
@ -121,10 +114,7 @@ const createHashKey = (...args: unknown[]) => {
|
|||
return hashString(stringToHash);
|
||||
};
|
||||
|
||||
export const cached = <T extends unknown[], R, TT>(
|
||||
fn: (...args: T) => R,
|
||||
self?: ThisType<TT>
|
||||
): ((...args: T) => R) => {
|
||||
export const cached = <T extends unknown[], R, TT>(fn: (...args: T) => R, self?: ThisType<TT>): ((...args: T) => R) => {
|
||||
const cacheName = hashString(fn.toString()).toString();
|
||||
|
||||
// important to return a promise on follow-up calls even if the data is immediately available
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
export const getNameFromRecipient = (
|
||||
joinedNickname: string | null,
|
||||
joinedSystemName: string | null,
|
||||
joinedProfileName: string | null
|
||||
joinedProfileName: string | null,
|
||||
) => {
|
||||
let name = "Could not determine name";
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { createEffect, createMemo, on, type Accessor } from "solid-js";
|
||||
import { createMemo, type Accessor } from "solid-js";
|
||||
import { getDateList, getHourList, getMonthList, getWeekdayList } from "./date";
|
||||
import { cached } from "./db-cache";
|
||||
import type { MessageOverview, MessageStats, Recipients } from "~/types";
|
||||
import { isSameDay } from "date-fns";
|
||||
|
||||
|
@ -18,10 +17,9 @@ const initialWeekdayMap = [...weekdayNames.keys()];
|
|||
|
||||
export const createMessageStatsSources = (
|
||||
messageOverview: Accessor<MessageOverview>,
|
||||
recipients: Accessor<Recipients>
|
||||
recipients: Accessor<Recipients>,
|
||||
) => {
|
||||
const initialRecipientMap = () =>
|
||||
Object.fromEntries(recipients().map(({ recipientId }) => [recipientId, 0]));
|
||||
const initialRecipientMap = () => Object.fromEntries(recipients().map(({ recipientId }) => [recipientId, 0]));
|
||||
|
||||
const dateList = () => {
|
||||
const currentDmMessagesOverview = messageOverview();
|
||||
|
@ -63,9 +61,7 @@ export const createMessageStatsSources = (
|
|||
month[messageDate.getMonth() - 1][message.fromRecipientId] += 1;
|
||||
|
||||
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||
const dateStatsEntry = date.find(({ date }) =>
|
||||
isSameDay(date, messageDate)
|
||||
)!;
|
||||
const dateStatsEntry = date.find(({ date }) => isSameDay(date, messageDate))!;
|
||||
|
||||
// increment the message count of the message's date for this recipient
|
||||
dateStatsEntry[message.fromRecipientId] += 1;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { type Component, createResource, Show } from "solid-js";
|
||||
import { type Component, createResource } from "solid-js";
|
||||
import type { RouteSectionProps } from "@solidjs/router";
|
||||
|
||||
import { dmPartnerRecipientQuery, SELF_ID, threadMostUsedWordsQuery, threadSentMessagesOverviewQuery } from "~/db";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createEffect, Show, type Accessor, type Component } from "solid-js";
|
||||
import { Show, type Accessor, type Component } from "solid-js";
|
||||
import type { ChartData } from "chart.js";
|
||||
import { LineChart } from "~/components/ui/charts";
|
||||
import type { MessageStats, Recipients } from "~/types";
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { type Component, type JSX } from "solid-js";
|
||||
import { createSignal, Show, type Component, type JSX } from "solid-js";
|
||||
import { type RouteSectionProps, useNavigate } from "@solidjs/router";
|
||||
|
||||
import { setDb, SQL } from "~/db";
|
||||
import { Portal } from "solid-js/web";
|
||||
import { Flex } from "~/components/ui/flex";
|
||||
|
||||
export const Home: Component<RouteSectionProps> = () => {
|
||||
const [isLoadingDb, setIsLoadingDb] = createSignal(false);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onFileChange: JSX.ChangeEventHandler<HTMLInputElement, Event> = (event) => {
|
||||
|
@ -12,9 +15,14 @@ export const Home: Component<RouteSectionProps> = () => {
|
|||
const reader = new FileReader();
|
||||
|
||||
reader.addEventListener("load", () => {
|
||||
const Uints = new Uint8Array(reader.result as ArrayBuffer);
|
||||
setDb(new SQL.Database(Uints));
|
||||
navigate("/overview");
|
||||
setIsLoadingDb(true);
|
||||
|
||||
setTimeout(() => {
|
||||
const Uints = new Uint8Array(reader.result as ArrayBuffer);
|
||||
setDb(new SQL.Database(Uints));
|
||||
setIsLoadingDb(false);
|
||||
navigate("/overview");
|
||||
}, 10);
|
||||
});
|
||||
|
||||
reader.readAsArrayBuffer(file);
|
||||
|
@ -22,9 +30,18 @@ export const Home: Component<RouteSectionProps> = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input type="file" accept=".sqlite" onChange={onFileChange}></input>
|
||||
</div>
|
||||
<>
|
||||
<Portal>
|
||||
<Show when={isLoadingDb()}>
|
||||
<Flex alignItems="center" justifyContent="center" class="fixed inset-0 backdrop-blur-lg backdrop-filter">
|
||||
<p class="font-bold text-2xl">Loading database</p>
|
||||
</Flex>
|
||||
</Show>
|
||||
</Portal>
|
||||
<div>
|
||||
<input type="file" accept=".sqlite" onChange={onFileChange}></input>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue