Compare commits
No commits in common. "5a49648e64fe032e91ea5d20d44cf36df1c6048b" and "a4bf466ba97c685597381c08d8da2251a158ff28" have entirely different histories.
5a49648e64
...
a4bf466ba9
23 changed files with 108 additions and 85 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"quickfix.biome": "explicit",
|
"quickfix.biome": "explicit"
|
||||||
"source.organizeImports.biome": "explicit"
|
|
||||||
},
|
},
|
||||||
"typescript.inlayHints.parameterNames.enabled": "all",
|
"typescript.inlayHints.parameterNames.enabled": "all",
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
|
|
8
bun.lock
8
bun.lock
|
@ -4,11 +4,11 @@
|
||||||
"": {
|
"": {
|
||||||
"name": "signalstats",
|
"name": "signalstats",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@duskflower/signal-decrypt-backup-wasm": "^0.3.0",
|
"@duskflower/signal-decrypt-backup-wasm": "^0.2.1",
|
||||||
"@kobalte/core": "^0.13.7",
|
"@kobalte/core": "^0.13.7",
|
||||||
"@kobalte/tailwindcss": "^0.9.0",
|
"@kobalte/tailwindcss": "^0.9.0",
|
||||||
"@solid-primitives/refs": "^1.1.0",
|
"@solid-primitives/refs": "^1.1.0",
|
||||||
"@solid-primitives/storage": "^4.3.1",
|
"@solid-primitives/storage": "^4.3.0",
|
||||||
"@solid-primitives/upload": "^0.1.0",
|
"@solid-primitives/upload": "^0.1.0",
|
||||||
"@solid-primitives/workers": "^0.4.0",
|
"@solid-primitives/workers": "^0.4.0",
|
||||||
"@solidjs/meta": "^0.29.4",
|
"@solidjs/meta": "^0.29.4",
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
"@commitlint/cli": "^19.6.1",
|
"@commitlint/cli": "^19.6.1",
|
||||||
"@commitlint/config-conventional": "^19.6.0",
|
"@commitlint/config-conventional": "^19.6.0",
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
"@types/node": "^22.10.10",
|
"@types/node": "^22.10.9",
|
||||||
"better-sqlite3": "^11.8.1",
|
"better-sqlite3": "^11.8.1",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"kysely-codegen": "^0.17.0",
|
"kysely-codegen": "^0.17.0",
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
|
|
||||||
"@corvu/utils": ["@corvu/utils@0.4.2", "", { "dependencies": { "@floating-ui/dom": "^1.6.11" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA=="],
|
"@corvu/utils": ["@corvu/utils@0.4.2", "", { "dependencies": { "@floating-ui/dom": "^1.6.11" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA=="],
|
||||||
|
|
||||||
"@duskflower/signal-decrypt-backup-wasm": ["@duskflower/signal-decrypt-backup-wasm@0.3.0", "https://git.duskflower.dev/api/packages/duskflower/npm/%40duskflower%2Fsignal-decrypt-backup-wasm/-/0.3.0/signal-decrypt-backup-wasm-0.3.0.tgz", {}, "sha512-1IMNFGz4bV4o29eXVelNbancqovsljmM0iZRrtau81gSy8bFE1lgwGFN05NAOFWlX/aZYzeUEeZVBrjUYIM0/w=="],
|
"@duskflower/signal-decrypt-backup-wasm": ["@duskflower/signal-decrypt-backup-wasm@0.2.1", "https://git.duskflower.dev/api/packages/duskflower/npm/%40duskflower%2Fsignal-decrypt-backup-wasm/-/0.2.1/signal-decrypt-backup-wasm-0.2.1.tgz", {}, "sha512-lYwtubVOUU4kuJNw28Ns8N9Gh2nZB4j6BJz/vLpxF0Vc7zww3VIGnMCQToFWWSAwCs5+cABadeZMkv87SGfyQg=="],
|
||||||
|
|
||||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="],
|
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="],
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"@commitlint/cli": "^19.6.1",
|
"@commitlint/cli": "^19.6.1",
|
||||||
"@commitlint/config-conventional": "^19.6.0",
|
"@commitlint/config-conventional": "^19.6.0",
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
"@types/node": "^22.10.10",
|
"@types/node": "^22.10.9",
|
||||||
"better-sqlite3": "^11.8.1",
|
"better-sqlite3": "^11.8.1",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"kysely-codegen": "^0.17.0",
|
"kysely-codegen": "^0.17.0",
|
||||||
|
@ -28,11 +28,11 @@
|
||||||
"vite-plugin-wasm": "^3.4.1"
|
"vite-plugin-wasm": "^3.4.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@duskflower/signal-decrypt-backup-wasm": "^0.3.0",
|
"@duskflower/signal-decrypt-backup-wasm": "^0.2.1",
|
||||||
"@kobalte/core": "^0.13.7",
|
"@kobalte/core": "^0.13.7",
|
||||||
"@kobalte/tailwindcss": "^0.9.0",
|
"@kobalte/tailwindcss": "^0.9.0",
|
||||||
"@solid-primitives/refs": "^1.1.0",
|
"@solid-primitives/refs": "^1.1.0",
|
||||||
"@solid-primitives/storage": "^4.3.1",
|
"@solid-primitives/storage": "^4.3.0",
|
||||||
"@solid-primitives/upload": "^0.1.0",
|
"@solid-primitives/upload": "^0.1.0",
|
||||||
"@solid-primitives/workers": "^0.4.0",
|
"@solid-primitives/workers": "^0.4.0",
|
||||||
"@solidjs/meta": "^0.29.4",
|
"@solidjs/meta": "^0.29.4",
|
||||||
|
|
11
src/App.tsx
11
src/App.tsx
|
@ -1,15 +1,16 @@
|
||||||
import { A, Route, Router, useNavigate } from "@solidjs/router";
|
import { A, Route, Router, useNavigate } from "@solidjs/router";
|
||||||
import { type Component, Show, Suspense, createEffect } from "solid-js";
|
import { createEffect, Show, Suspense, type Component } from "solid-js";
|
||||||
import { DmId, GroupId, Home, Overview, Privacy, preloadDmId } from "./pages";
|
import { DmId, GroupId, Home, Overview, preloadDmId, Privacy } from "./pages";
|
||||||
|
|
||||||
import "./app.css";
|
import "./app.css";
|
||||||
import { ColorModeProvider, ColorModeScript, createLocalStorageManager } from "@kobalte/core";
|
|
||||||
import { MetaProvider } from "@solidjs/meta";
|
import { MetaProvider } from "@solidjs/meta";
|
||||||
import { Portal } from "solid-js/web";
|
import { Portal } from "solid-js/web";
|
||||||
import { Callout, CalloutContent, CalloutTitle } from "./components/ui/callout";
|
import { Callout, CalloutTitle, CalloutContent } from "./components/ui/callout";
|
||||||
import { ModeToggle } from "./components/ui/mode-toggle";
|
|
||||||
import { dbLoaded } from "./db";
|
import { dbLoaded } from "./db";
|
||||||
import { hasCashedData } from "./lib/db-cache";
|
import { hasCashedData } from "./lib/db-cache";
|
||||||
import { isWasmSupported } from "./lib/utils";
|
import { isWasmSupported } from "./lib/utils";
|
||||||
|
import { ColorModeProvider, ColorModeScript, createLocalStorageManager } from "@kobalte/core";
|
||||||
|
import { ModeToggle } from "./components/ui/mode-toggle";
|
||||||
|
|
||||||
const NO_DATA_NEEDED_PAGES = ["/", "/privacy"];
|
const NO_DATA_NEEDED_PAGES = ["/", "/privacy"];
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { type NotNull, sql } from "kysely";
|
import { sql, type NotNull } from "kysely";
|
||||||
import type { MainToWorkerMsg, WorkerToMainMsg } from "~/lib/kysely-official-wasm-worker/type";
|
import { worker, kyselyDb, SELF_ID, DB_FILENAME, setDbLoaded } from "./db";
|
||||||
import { cached, clearDbCache } from "../lib/db-cache";
|
import { cached, clearDbCache } from "../lib/db-cache";
|
||||||
import { DB_FILENAME, SELF_ID, kyselyDb, setDbLoaded, worker } from "./db";
|
import type { MainToWorkerMsg, WorkerToMainMsg } from "~/lib/kysely-official-wasm-worker/type";
|
||||||
|
|
||||||
export const loadDb = async (statements: string[], progressCallback?: (percentage: number) => void): Promise<void> => {
|
export const loadDb = async (statements: string[], progressCallback?: (percentage: number) => void): Promise<void> => {
|
||||||
// try to persist storage, https://web.dev/articles/persistent-storage#request_persistent_storage
|
// try to persist storage, https://web.dev/articles/persistent-storage#request_persistent_storage
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Kysely } from "kysely";
|
import { Kysely } from "kysely";
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { OfficialWasmWorkerDialect } from "~/lib/kysely-official-wasm-worker";
|
|
||||||
import type { DB } from "./db-schema";
|
import type { DB } from "./db-schema";
|
||||||
|
import { OfficialWasmWorkerDialect } from "~/lib/kysely-official-wasm-worker";
|
||||||
import WasmWorker from "./db-worker?worker";
|
import WasmWorker from "./db-worker?worker";
|
||||||
|
import { createSignal } from "solid-js";
|
||||||
|
|
||||||
export const SELF_ID = 2;
|
export const SELF_ID = 2;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { BackupDecryptor } from "@duskflower/signal-decrypt-backup-wasm";
|
import {
|
||||||
|
BackupDecryptor,
|
||||||
|
type DecryptionResult,
|
||||||
|
} from "@duskflower/signal-decrypt-backup-wasm";
|
||||||
|
|
||||||
const CHUNK_SIZE = 1024 * 1024 * 40; // 40MB chunks
|
const CHUNK_SIZE = 1024 * 1024 * 40; // 40MB chunks
|
||||||
|
|
||||||
|
@ -6,8 +9,7 @@ export async function decryptBackup(
|
||||||
file: File,
|
file: File,
|
||||||
passphrase: string,
|
passphrase: string,
|
||||||
progressCallback: (progress: number) => void,
|
progressCallback: (progress: number) => void,
|
||||||
statementsCallback?: (statements: string[]) => void | Promise<void>,
|
): Promise<DecryptionResult> {
|
||||||
): Promise<string[]> {
|
|
||||||
const fileSize = file.size;
|
const fileSize = file.size;
|
||||||
const decryptor = new BackupDecryptor();
|
const decryptor = new BackupDecryptor();
|
||||||
decryptor.set_progress_callback(fileSize, progressCallback);
|
decryptor.set_progress_callback(fileSize, progressCallback);
|
||||||
|
@ -32,8 +34,6 @@ export async function decryptBackup(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await statementsCallback?.(decryptor.get_new_decrypted_statements());
|
|
||||||
|
|
||||||
offset += CHUNK_SIZE;
|
offset += CHUNK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
import type { DatabaseIntrospector, Dialect, DialectAdapter, Driver, Kysely, QueryCompiler } from "kysely";
|
import type {
|
||||||
|
DatabaseIntrospector,
|
||||||
|
Dialect,
|
||||||
|
DialectAdapter,
|
||||||
|
Driver,
|
||||||
|
Kysely,
|
||||||
|
QueryCompiler,
|
||||||
|
} from "kysely";
|
||||||
import { SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler } from "kysely";
|
import { SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler } from "kysely";
|
||||||
import { OfficialWasmWorkerDriver } from "./driver";
|
import { OfficialWasmWorkerDriver } from "./driver";
|
||||||
import type { OfficialWasmWorkerDialectConfig } from "./type";
|
import type { OfficialWasmWorkerDialectConfig } from "./type";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { MessageOverview, MessageStats, Recipients } from "~/types";
|
|
||||||
import { getHourList, getMonthList, getWeekdayList } from "./date";
|
import { getHourList, getMonthList, getWeekdayList } from "./date";
|
||||||
|
import type { MessageOverview, MessageStats, Recipients } from "~/types";
|
||||||
|
|
||||||
const hourNames = getHourList();
|
const hourNames = getHourList();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { MessageOverview, MessageStats, Recipients } from "~/types";
|
import type { MessageOverview, MessageStats, Recipients } from "~/types";
|
||||||
import { getHourList, getMonthList, getWeekdayList } from "./date";
|
|
||||||
import { cached } from "./db-cache";
|
import { cached } from "./db-cache";
|
||||||
|
import { getHourList, getMonthList, getWeekdayList } from "./date";
|
||||||
import MessageStatsWorker from "./messages-worker?worker";
|
import MessageStatsWorker from "./messages-worker?worker";
|
||||||
|
|
||||||
export const hourNames = getHourList();
|
export const hourNames = getHourList();
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
import { Title } from "@solidjs/meta";
|
import { Suspense, type Component } from "solid-js";
|
||||||
import { type RoutePreloadFunc, type RouteSectionProps, createAsync } from "@solidjs/router";
|
import { createAsync, type RoutePreloadFunc, type RouteSectionProps } from "@solidjs/router";
|
||||||
import { type Component, Suspense } from "solid-js";
|
|
||||||
import { Flex } from "~/components/ui/flex";
|
import { dmPartnerRecipientQuery, threadMostUsedWordsQuery, threadSentMessagesOverviewQuery, SELF_ID } from "~/db";
|
||||||
import { Grid } from "~/components/ui/grid";
|
|
||||||
import { Heading } from "~/components/ui/heading";
|
|
||||||
import { SELF_ID, dmPartnerRecipientQuery, threadMostUsedWordsQuery, threadSentMessagesOverviewQuery } from "~/db";
|
|
||||||
import { getNameFromRecipient } from "~/lib/get-name-from-recipient";
|
import { getNameFromRecipient } from "~/lib/get-name-from-recipient";
|
||||||
import { createMessageStatsSources } from "~/lib/messages";
|
import { Heading } from "~/components/ui/heading";
|
||||||
import type { MessageOverview } from "~/types";
|
import { Grid } from "~/components/ui/grid";
|
||||||
|
import { Title } from "@solidjs/meta";
|
||||||
import { DmMessagesPerDate } from "./dm-messages-per-date";
|
import { DmMessagesPerDate } from "./dm-messages-per-date";
|
||||||
import { DmMessagesPerDaytime } from "./dm-messages-per-daytime";
|
|
||||||
import { DmMessagesPerMonth } from "./dm-messages-per-month";
|
|
||||||
import { DmMessagesPerRecipient } from "./dm-messages-per-recipients";
|
|
||||||
import { DmMessagesPerWeekday } from "./dm-messages-per-weekday";
|
|
||||||
import { DmOverview } from "./dm-overview";
|
import { DmOverview } from "./dm-overview";
|
||||||
import { DmWordCloud } from "./dm-wordcloud";
|
import { DmWordCloud } from "./dm-wordcloud";
|
||||||
|
import { DmMessagesPerMonth } from "./dm-messages-per-month";
|
||||||
|
import { DmMessagesPerDaytime } from "./dm-messages-per-daytime";
|
||||||
|
import { DmMessagesPerRecipient } from "./dm-messages-per-recipients";
|
||||||
|
import { DmMessagesPerWeekday } from "./dm-messages-per-weekday";
|
||||||
|
import type { MessageOverview } from "~/types";
|
||||||
|
import { createMessageStatsSources } from "~/lib/messages";
|
||||||
|
import { Flex } from "~/components/ui/flex";
|
||||||
|
|
||||||
const getDmIdData = (dmId: number) => {
|
const getDmIdData = (dmId: number) => {
|
||||||
// the other person in the chat with name and id
|
// the other person in the chat with name and id
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { Show, type Accessor, type Component } from "solid-js";
|
||||||
import type { ChartData } from "chart.js";
|
import type { ChartData } from "chart.js";
|
||||||
import { type Accessor, type Component, Show } from "solid-js";
|
|
||||||
import { LineChart } from "~/components/ui/charts";
|
import { LineChart } from "~/components/ui/charts";
|
||||||
import type { MessageStats, Recipients } from "~/types";
|
import type { MessageStats, Recipients } from "~/types";
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
import { Show, type Accessor, type Component } from "solid-js";
|
||||||
import type { ChartData } from "chart.js";
|
import type { ChartData } from "chart.js";
|
||||||
import { type Accessor, type Component, Show } from "solid-js";
|
|
||||||
import { BarChart } from "~/components/ui/charts";
|
import { BarChart } from "~/components/ui/charts";
|
||||||
import { hourNames } from "~/lib/messages";
|
|
||||||
import type { MessageStats, Recipients } from "~/types";
|
import type { MessageStats, Recipients } from "~/types";
|
||||||
|
import { hourNames } from "~/lib/messages";
|
||||||
|
|
||||||
export const DmMessagesPerDaytime: Component<{
|
export const DmMessagesPerDaytime: Component<{
|
||||||
daytimeStats: MessageStats["daytime"] | undefined;
|
daytimeStats: MessageStats["daytime"] | undefined;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { Show, type Accessor, type Component } from "solid-js";
|
||||||
import type { ChartData } from "chart.js";
|
import type { ChartData } from "chart.js";
|
||||||
import { type Accessor, type Component, Show } from "solid-js";
|
|
||||||
import { RadarChart } from "~/components/ui/charts";
|
import { RadarChart } from "~/components/ui/charts";
|
||||||
import { monthNames } from "~/lib/messages";
|
import { monthNames } from "~/lib/messages";
|
||||||
import type { MessageStats, Recipients } from "~/types";
|
import type { MessageStats, Recipients } from "~/types";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { Show, type Accessor, type Component } from "solid-js";
|
||||||
import type { ChartData } from "chart.js";
|
import type { ChartData } from "chart.js";
|
||||||
import { type Accessor, type Component, Show } from "solid-js";
|
|
||||||
import { PieChart } from "~/components/ui/charts";
|
import { PieChart } from "~/components/ui/charts";
|
||||||
import type { MessageStats, Recipients } from "~/types";
|
import type { MessageStats, Recipients } from "~/types";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { Show, type Accessor, type Component } from "solid-js";
|
||||||
import type { ChartData } from "chart.js";
|
import type { ChartData } from "chart.js";
|
||||||
import { type Accessor, type Component, Show } from "solid-js";
|
|
||||||
import { RadarChart } from "~/components/ui/charts";
|
import { RadarChart } from "~/components/ui/charts";
|
||||||
import { weekdayNames } from "~/lib/messages";
|
import { weekdayNames } from "~/lib/messages";
|
||||||
import type { MessageStats, Recipients } from "~/types";
|
import type { MessageStats, Recipients } from "~/types";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { CalendarArrowDown, CalendarArrowUp, CalendarClock, MessagesSquare } from "lucide-solid";
|
import { Show, type Component } from "solid-js";
|
||||||
import { type Component, Show } from "solid-js";
|
|
||||||
import { Flex } from "~/components/ui/flex";
|
import { Flex } from "~/components/ui/flex";
|
||||||
import { Grid } from "~/components/ui/grid";
|
import { Grid } from "~/components/ui/grid";
|
||||||
|
import { CalendarArrowDown, CalendarArrowUp, CalendarClock, MessagesSquare } from "lucide-solid";
|
||||||
import { getDistanceBetweenDatesInDays } from "~/lib/date";
|
import { getDistanceBetweenDatesInDays } from "~/lib/date";
|
||||||
import type { MessageOverview } from "~/types";
|
import type { MessageOverview } from "~/types";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { ChartData } from "chart.js";
|
import type { ChartData } from "chart.js";
|
||||||
import { type Accessor, type Component, Show } from "solid-js";
|
import { Show, type Accessor, type Component } from "solid-js";
|
||||||
import { WordCloudChart } from "~/components/ui/charts";
|
import { WordCloudChart } from "~/components/ui/charts";
|
||||||
import type { threadMostUsedWordsQuery } from "~/db";
|
import type { threadMostUsedWordsQuery } from "~/db";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { RouteSectionProps } from "@solidjs/router";
|
|
||||||
import type { Component } from "solid-js";
|
import type { Component } from "solid-js";
|
||||||
|
import type { RouteSectionProps } from "@solidjs/router";
|
||||||
|
|
||||||
export const GroupId: Component<RouteSectionProps> = (props) => {
|
export const GroupId: Component<RouteSectionProps> = (props) => {
|
||||||
const groupId = () => Number(props.params.groupid);
|
const groupId = () => Number(props.params.groupid);
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import { createDropzone, createFileUploader } from "@solid-primitives/upload";
|
import { useNavigate, type RouteSectionProps } from "@solidjs/router";
|
||||||
|
import { createSignal, type JSX, Show, type Component } from "solid-js";
|
||||||
|
|
||||||
import { Title } from "@solidjs/meta";
|
import { Title } from "@solidjs/meta";
|
||||||
import { type RouteSectionProps, useNavigate } from "@solidjs/router";
|
|
||||||
import { type Component, type JSX, Show, createSignal } from "solid-js";
|
|
||||||
import { Portal } from "solid-js/web";
|
import { Portal } from "solid-js/web";
|
||||||
import { Button } from "~/components/ui/button";
|
|
||||||
import { Flex } from "~/components/ui/flex";
|
import { Flex } from "~/components/ui/flex";
|
||||||
|
|
||||||
import { Progress, ProgressLabel, ProgressValueLabel } from "~/components/ui/progress";
|
import { Progress, ProgressLabel, ProgressValueLabel } from "~/components/ui/progress";
|
||||||
import { TextField, TextFieldInput, TextFieldLabel } from "~/components/ui/text-field";
|
|
||||||
import { loadDb } from "~/db";
|
import { loadDb } from "~/db";
|
||||||
import { decryptBackup } from "~/lib/backup-decryptor";
|
import { decryptBackup } from "~/lib/decryptor";
|
||||||
|
import { createDropzone, createFileUploader } from "@solid-primitives/upload";
|
||||||
|
import { Button } from "~/components/ui/button";
|
||||||
|
import { TextField, TextFieldInput, TextFieldLabel } from "~/components/ui/text-field";
|
||||||
|
|
||||||
export const Home: Component<RouteSectionProps> = () => {
|
export const Home: Component<RouteSectionProps> = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
@ -32,8 +34,8 @@ export const Home: Component<RouteSectionProps> = () => {
|
||||||
const [backupFile, setBackupFile] = createSignal<File>();
|
const [backupFile, setBackupFile] = createSignal<File>();
|
||||||
|
|
||||||
const [decryptionProgress, setDecryptionProgress] = createSignal<number>();
|
const [decryptionProgress, setDecryptionProgress] = createSignal<number>();
|
||||||
const [totalStatements, setTotalStatements] = createSignal(0);
|
const [loadingProgress, setLoadingProgress] = createSignal<number>();
|
||||||
const [executedStatements, setExecutedStatements] = createSignal(0);
|
// const [isLoadingDatabase, setIsLoadingDatabase] = createSignal(false);
|
||||||
|
|
||||||
const onSubmit: JSX.EventHandler<HTMLFormElement, SubmitEvent> = (event) => {
|
const onSubmit: JSX.EventHandler<HTMLFormElement, SubmitEvent> = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -42,22 +44,28 @@ export const Home: Component<RouteSectionProps> = () => {
|
||||||
const currentPassphrase = passphrase();
|
const currentPassphrase = passphrase();
|
||||||
|
|
||||||
if (currentBackupFile && currentPassphrase) {
|
if (currentBackupFile && currentPassphrase) {
|
||||||
console.time();
|
// const hashChunk = await currentBackupFile.slice(-1000).text();
|
||||||
decryptBackup(currentBackupFile, currentPassphrase, setDecryptionProgress, async (statements) => {
|
// const hash = hashString(hashChunk);
|
||||||
const length = statements.length;
|
|
||||||
setTotalStatements((oldValue) => oldValue + length);
|
|
||||||
|
|
||||||
await loadDb(statements, (progress) => {
|
// if (hash === dbHash()) {
|
||||||
setExecutedStatements((oldValue) => Math.round(oldValue + (progress / 100) * length));
|
// return;
|
||||||
});
|
// }
|
||||||
|
|
||||||
setExecutedStatements((oldValue) => oldValue + length);
|
// setDbHash(hash);
|
||||||
})
|
|
||||||
.then(() => {
|
decryptBackup(currentBackupFile, currentPassphrase, setDecryptionProgress)
|
||||||
|
.then(async (decrypted) => {
|
||||||
umami.track("Decrypt backup");
|
umami.track("Decrypt backup");
|
||||||
|
setDecryptionProgress(undefined);
|
||||||
|
// setIsLoadingDatabase(true);
|
||||||
|
setLoadingProgress(0);
|
||||||
|
|
||||||
|
await loadDb(decrypted.database_statements, setLoadingProgress);
|
||||||
umami.track("Load database");
|
umami.track("Load database");
|
||||||
|
|
||||||
console.timeEnd();
|
// setIsLoadingDatabase(false);
|
||||||
|
setLoadingProgress(undefined);
|
||||||
|
|
||||||
navigate("/overview");
|
navigate("/overview");
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
@ -76,7 +84,7 @@ export const Home: Component<RouteSectionProps> = () => {
|
||||||
class="fixed inset-0 gap-y-8 backdrop-blur-lg backdrop-filter"
|
class="fixed inset-0 gap-y-8 backdrop-blur-lg backdrop-filter"
|
||||||
classList={{
|
classList={{
|
||||||
// hidden: decryptionProgress() === undefined && !isLoadingDatabase(),
|
// hidden: decryptionProgress() === undefined && !isLoadingDatabase(),
|
||||||
hidden: decryptionProgress() === undefined && totalStatements() === 0,
|
hidden: decryptionProgress() === undefined && loadingProgress() === undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Show when={decryptionProgress() !== undefined}>
|
<Show when={decryptionProgress() !== undefined}>
|
||||||
|
@ -89,18 +97,20 @@ export const Home: Component<RouteSectionProps> = () => {
|
||||||
class="w-[300px] space-y-1"
|
class="w-[300px] space-y-1"
|
||||||
>
|
>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<ProgressLabel>Decrypting...</ProgressLabel>
|
<ProgressLabel>Processing...</ProgressLabel>
|
||||||
<ProgressValueLabel />
|
<ProgressValueLabel />
|
||||||
</div>
|
</div>
|
||||||
</Progress>
|
</Progress>
|
||||||
</Show>
|
</Show>
|
||||||
<Show when={totalStatements() !== 0}>
|
<Show when={loadingProgress() !== undefined}>
|
||||||
|
{/* <p class="font-bold text-2xl">Loading database</p>
|
||||||
|
<p class="text-muted-foreground">This can take some time</p> */}
|
||||||
<p class="font-bold text-2xl">Loading database</p>
|
<p class="font-bold text-2xl">Loading database</p>
|
||||||
<Progress
|
<Progress
|
||||||
value={executedStatements()}
|
value={loadingProgress()}
|
||||||
minValue={0}
|
minValue={0}
|
||||||
maxValue={totalStatements()}
|
maxValue={100}
|
||||||
getValueLabel={({ value, max }) => `${value} of ${max}`}
|
getValueLabel={({ value }) => `${value}%`}
|
||||||
class="w-[300px] space-y-1"
|
class="w-[300px] space-y-1"
|
||||||
>
|
>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import { Title } from "@solidjs/meta";
|
|
||||||
import type { RouteSectionProps } from "@solidjs/router";
|
import type { RouteSectionProps } from "@solidjs/router";
|
||||||
import { type Component, Show, createResource } from "solid-js";
|
import { type Component, createResource, Show } from "solid-js";
|
||||||
import { SELF_ID, allThreadsOverviewQuery, overallSentMessagesQuery } from "~/db";
|
|
||||||
|
import { allThreadsOverviewQuery, overallSentMessagesQuery, SELF_ID } from "~/db";
|
||||||
|
|
||||||
|
import { Title } from "@solidjs/meta";
|
||||||
import { getNameFromRecipient } from "~/lib/get-name-from-recipient";
|
import { getNameFromRecipient } from "~/lib/get-name-from-recipient";
|
||||||
import { OverviewTable, type RoomOverview } from "./overview-table";
|
import { OverviewTable, type RoomOverview } from "./overview-table";
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,32 @@
|
||||||
|
import { type Component, createSignal, For, Match, Show, Switch } from "solid-js";
|
||||||
import { useNavigate, usePreloadRoute } from "@solidjs/router";
|
import { useNavigate, usePreloadRoute } from "@solidjs/router";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type ColumnFiltersState,
|
type ColumnFiltersState,
|
||||||
type FilterFn,
|
|
||||||
type SortDirection,
|
|
||||||
type SortingState,
|
|
||||||
createColumnHelper,
|
createColumnHelper,
|
||||||
createSolidTable,
|
createSolidTable,
|
||||||
|
type FilterFn,
|
||||||
flexRender,
|
flexRender,
|
||||||
getCoreRowModel,
|
getCoreRowModel,
|
||||||
getFilteredRowModel,
|
getFilteredRowModel,
|
||||||
getPaginationRowModel,
|
getPaginationRowModel,
|
||||||
getSortedRowModel,
|
getSortedRowModel,
|
||||||
|
type SortDirection,
|
||||||
|
type SortingState,
|
||||||
} from "@tanstack/solid-table";
|
} from "@tanstack/solid-table";
|
||||||
import { intlFormatDistance } from "date-fns";
|
import { intlFormatDistance } from "date-fns";
|
||||||
import { ArrowDown, ArrowUp, ArrowUpDown } from "lucide-solid";
|
import { ArrowDown, ArrowUp, ArrowUpDown } from "lucide-solid";
|
||||||
import { type Component, For, Match, Show, Switch, createSignal } from "solid-js";
|
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Checkbox } from "~/components/ui/checkbox";
|
import { Checkbox } from "~/components/ui/checkbox";
|
||||||
import { Flex } from "~/components/ui/flex";
|
|
||||||
import { Label } from "~/components/ui/label";
|
import { Label } from "~/components/ui/label";
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table";
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table";
|
||||||
import { TextField, TextFieldInput } from "~/components/ui/text-field";
|
import { TextField, TextFieldInput } from "~/components/ui/text-field";
|
||||||
import { dbLoaded, threadSentMessagesOverviewQuery } from "~/db";
|
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
|
import { Flex } from "~/components/ui/flex";
|
||||||
|
import { dbLoaded, threadSentMessagesOverviewQuery } from "~/db";
|
||||||
|
|
||||||
export interface RoomOverview {
|
export interface RoomOverview {
|
||||||
threadId: number;
|
threadId: number;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import tailwind from "@tailwindcss/vite";
|
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import solidPlugin from "vite-plugin-solid";
|
import solidPlugin from "vite-plugin-solid";
|
||||||
import wasm from "vite-plugin-wasm";
|
import wasm from "vite-plugin-wasm";
|
||||||
|
import tailwind from "@tailwindcss/vite";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [solidPlugin(), wasm(), tailwind()],
|
plugins: [solidPlugin(), wasm(), tailwind()],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue