perf(vite): add dynamic imports

This commit is contained in:
Alois 2026-08-31 20:48:32 +02:00
commit 85921a0a08
Signed by: alois
SSH key fingerprint: SHA256:GBzT2DXvAuGV9XIV5W3WrzVpjU54FThmxHXdbz95J24
29 changed files with 470 additions and 326 deletions

View file

@ -5,6 +5,7 @@
"type": "module",
"exports": {
"./store": "./src/store.tsx",
"./state": "./src/state.ts",
"./speakingState": "./src/speakingState.ts",
"./screen": "./src/screen.tsx",
"./utils": "./src/utils.ts",

View file

@ -0,0 +1,93 @@
import type { RefObject } from "react";
import { create } from "zustand";
import type { LocalMediaShareSession } from "./mediaShare/controller";
export type CallView = "preview" | "focused" | "grid";
export type WrappedCallSecret = {
secretId: string;
versionNumber: number;
encryptedSecret: Uint8Array;
kemCiphertext: Uint8Array;
wrappingScheme: string;
};
export type CallRuntime = {
navigate: (options: {
to: string;
search?: Record<string, unknown>;
}) => Promise<void>;
send: (
type: string,
data: Record<string, unknown>,
) => Promise<{ data: unknown }>;
load: (key: string) => Promise<unknown>;
getPublicKey: (userId: number) => Promise<string>;
};
export const useCall = create<{
state: "closed" | "closing" | "connecting" | "open" | "encrypting";
view: CallView;
invitedUserId: number | null;
callId: string | null;
incomingCallInvite: {
callId: string;
callSecret: WrappedCallSecret;
senderId: number;
} | null;
callSecret: string | null;
livekitToken: string | null;
currentCallData: { UserIds: number[]; exists: boolean } | null;
deaf: boolean;
micEnabled: boolean;
cameraEnabled: boolean;
screenShareEnabled: boolean;
screenShareSession: LocalMediaShareSession | null;
cameraSession: LocalMediaShareSession | null;
disabledCameraParticipantIds: number[];
focusedParticipantId: number | null;
focusedParticipantType: "user" | "stream" | null;
usersInFocusedViewHidden: boolean;
watchedStreamParticipantIds: number[];
pendingWatchedParticipantIds: number[];
activeScreenShareParticipantIds: number[];
isEncrypted: boolean;
ownCallSecretInvitePending: boolean;
callIsFullscreen: boolean;
callIsPopout: boolean;
layoutVersion: number;
screenRef: RefObject<HTMLDivElement | null> | null;
runtime: CallRuntime | null;
lastFocusedParticipantId: number | null;
}>(() => ({
state: "closed",
view: "preview",
invitedUserId: null,
callId: null,
incomingCallInvite: null,
callSecret: null,
livekitToken: null,
currentCallData: null,
deaf: false,
micEnabled: false,
cameraEnabled: false,
screenShareEnabled: false,
screenShareSession: null,
cameraSession: null,
disabledCameraParticipantIds: [],
focusedParticipantId: null,
focusedParticipantType: null,
usersInFocusedViewHidden: false,
watchedStreamParticipantIds: [],
pendingWatchedParticipantIds: [],
activeScreenShareParticipantIds: [],
isEncrypted: false,
ownCallSecretInvitePending: false,
callIsFullscreen: false,
callIsPopout: false,
layoutVersion: 0,
screenRef: null,
runtime: null,
lastFocusedParticipantId: null,
}));

View file

@ -1,5 +1,4 @@
import { useCallback, useEffect, useMemo, useRef } from "react";
import { create } from "zustand";
import { useLocation, useNavigate } from "@tanstack/react-router";
import { useMTP } from "@tensamin/mtp";
import { log, toast } from "@tensamin/shared/log";
@ -33,7 +32,6 @@ import {
import z from "zod";
import {
createMediaShareController,
type LocalMediaShareSession,
} from "./mediaShare/controller";
import type { MediaShareRequest } from "./mediaShare";
import {
@ -41,6 +39,14 @@ import {
disposeSpeakingDetector,
} from "./speakingIndicator";
import InvitePopup from "./components/invitePopup";
import {
useCall,
type CallRuntime as Runtime,
type CallView,
type WrappedCallSecret,
} from "./state";
export { useCall } from "./state";
// logging
setLogExtension(
@ -51,19 +57,9 @@ setLogExtension(
getLogger("tensamin"),
);
type CallView = "preview" | "focused" | "grid";
type ProtocolCallSecret = NonNullable<
z.infer<typeof mtp.CallInvite.response>["CallSecret"]
>;
type WrappedCallSecret = {
secretId: string;
versionNumber: number;
encryptedSecret: Uint8Array;
kemCiphertext: Uint8Array;
wrappingScheme: string;
};
type CurrentCallData =
(z.infer<typeof mtp.CallData.response> & { exists: boolean }) | null;
type SendFn = (
type: string,
@ -72,16 +68,6 @@ type SendFn = (
type LoadFn = (key: string) => Promise<unknown>;
type RemoteVideoTrackSelector = Track.Kind | Track.Source;
type Runtime = {
navigate: (options: {
to: string;
search?: Record<string, unknown>;
}) => Promise<void>;
send: SendFn;
load: LoadFn;
getPublicKey: (userId: number) => Promise<string>;
};
let _keyProvider: ExternalE2EEKeyProvider | null = null;
let _e2eeWorker: Worker | null = null;
let _room: Room | null = null;
@ -632,7 +618,7 @@ export function setCallId(callId: string | null) {
// Cache server call metadata used by the preview screen.
export function setCurrentCallData(
currentCallData: CurrentCallData & { exists: boolean },
currentCallData: { UserIds: number[]; exists: boolean },
) {
useCall.setState({ currentCallData });
}
@ -1153,72 +1139,6 @@ async function ensureNoiseFilter(
}
}
export const useCall = create<{
state: "closed" | "closing" | "connecting" | "open" | "encrypting";
view: CallView;
invitedUserId: number | null;
callId: string | null;
incomingCallInvite: {
callId: string;
callSecret: WrappedCallSecret;
senderId: number;
} | null;
callSecret: string | null;
livekitToken: string | null;
currentCallData: CurrentCallData;
deaf: boolean;
micEnabled: boolean;
cameraEnabled: boolean;
screenShareEnabled: boolean;
screenShareSession: LocalMediaShareSession | null;
cameraSession: LocalMediaShareSession | null;
disabledCameraParticipantIds: number[];
focusedParticipantId: number | null;
focusedParticipantType: "user" | "stream" | null;
usersInFocusedViewHidden: boolean;
watchedStreamParticipantIds: number[];
pendingWatchedParticipantIds: number[];
activeScreenShareParticipantIds: number[];
isEncrypted: boolean;
ownCallSecretInvitePending: boolean;
callIsFullscreen: boolean;
callIsPopout: boolean;
layoutVersion: number;
screenRef: React.RefObject<HTMLDivElement | null> | null;
runtime: Runtime | null;
lastFocusedParticipantId: number | null;
}>(() => ({
state: "closed",
view: "preview",
invitedUserId: null,
callId: null,
incomingCallInvite: null,
callSecret: null,
livekitToken: null,
currentCallData: null,
deaf: false,
micEnabled: false,
cameraEnabled: false,
screenShareEnabled: false,
screenShareSession: null,
cameraSession: null,
disabledCameraParticipantIds: [],
focusedParticipantId: null,
focusedParticipantType: null,
usersInFocusedViewHidden: false,
watchedStreamParticipantIds: [],
pendingWatchedParticipantIds: [],
activeScreenShareParticipantIds: [],
isEncrypted: false,
ownCallSecretInvitePending: false,
callIsFullscreen: false,
callIsPopout: false,
layoutVersion: 0,
screenRef: null,
runtime: null,
lastFocusedParticipantId: null,
}));
// Register app-level call listeners and wire React dependencies into the store.
export function useInitializeCall() {
const navigate = useNavigate();

View file

@ -24,6 +24,7 @@
"@tensamin/cache": "workspace:*",
"@tensamin/crypto": "workspace:*",
"@tensamin/hotkeys": "workspace:*",
"@tensamin/markdown": "workspace:*",
"@tensamin/mtp": "workspace:*",
"@tensamin/shared": "workspace:*",
"@tensamin/storage": "workspace:*",

View file

@ -1,5 +1,5 @@
import { Button } from "@methanium/ui";
import { Emoji } from "@methanium/ui/markdown";
import Emoji from "@tensamin/markdown/emoji";
import { getRecentEmojis, useEmojiRanks } from "./emojiRanks";
export default function EmojiPicker({

View file

@ -1,6 +1,6 @@
import { useStorage } from "@tensamin/storage/context";
import { useCallback, useEffect, useState } from "react";
import { normalizeShortcode } from "@methanium/ui/markdown";
import { normalizeShortcode } from "@tensamin/markdown/emoji";
const RANKS_CHANGED_EVENT = "tensamin-reaction-ranks-changed";
let recordQueue = Promise.resolve();

View file

@ -1,4 +1,4 @@
import { Input, type InputController } from "@methanium/ui/markdown";
import Input, { type InputController } from "@tensamin/markdown/input";
import {
Card,
CardHeader,
@ -10,7 +10,14 @@ import {
PopoverTrigger,
} from "@methanium/ui";
import { useStorage } from "@tensamin/storage/context";
import React, { useCallback, useEffect, useState, useRef } from "react";
import React, {
lazy,
Suspense,
useCallback,
useEffect,
useState,
useRef,
} from "react";
import { Button } from "@methanium/ui";
import { Plus, Laugh, FileVideo, SendHorizonal } from "lucide-react";
@ -21,14 +28,15 @@ import { cn, useIsMobile } from "@methanium/ui";
import { encryptChatText } from "@tensamin/crypto/chatSecret";
import { useSession } from "@tensamin/storage/session";
import EmojiPicker from "./emoji/emojiPicker";
import { useEmojiRanks, useRecordEmojiUse } from "./emoji/emojiRanks";
import GifPicker from "./media/gifPicker";
import ReplyBox from "./replyBox";
import { useHotkey } from "@tensamin/hotkeys";
import { editLastMessageHotkey } from "../hotkeys";
import { useUser } from "@tensamin/identity/context";
const EmojiPicker = lazy(() => import("./emoji/emojiPicker"));
const GifPicker = lazy(() => import("./media/gifPicker"));
export default function InputComponent({
value,
setValue,
@ -351,13 +359,15 @@ export default function InputComponent({
)}
/>
<PopoverContent className="w-auto p-0">
<EmojiPicker
onSelect={(shortcode) => {
setValue(`${value}${shortcode} `);
recordUse(shortcode);
setEmojiPopoverOpen(false);
}}
/>
<Suspense fallback={null}>
<EmojiPicker
onSelect={(shortcode) => {
setValue(`${value}${shortcode} `);
recordUse(shortcode);
setEmojiPopoverOpen(false);
}}
/>
</Suspense>
</PopoverContent>
</Popover>
{isMobile ? (
@ -371,12 +381,14 @@ export default function InputComponent({
</DrawerTrigger>
<DrawerContent className="h-[80dvh]">
<div className="min-h-0 flex-1 p-3">
<GifPicker
onSelect={(url) => {
void handleSubmit(url, true);
setGifPopoverOpen(false);
}}
/>
<Suspense fallback={null}>
<GifPicker
onSelect={(url) => {
void handleSubmit(url, true);
setGifPopoverOpen(false);
}}
/>
</Suspense>
</div>
</DrawerContent>
</Drawer>
@ -408,14 +420,16 @@ export default function InputComponent({
className="absolute left-0 top-0 z-10 h-4 w-4 cursor-nwse-resize"
onPointerDown={handleGifPopoverResizeStart}
/>
<GifPicker
resizeHeight={gifPopoverSize?.height}
resizeWidth={gifPopoverSize?.width}
onSelect={(url) => {
void handleSubmit(url, true);
setGifPopoverOpen(false);
}}
/>
<Suspense fallback={null}>
<GifPicker
resizeHeight={gifPopoverSize?.height}
resizeWidth={gifPopoverSize?.width}
onSelect={(url) => {
void handleSubmit(url, true);
setGifPopoverOpen(false);
}}
/>
</Suspense>
</PopoverContent>
</Popover>
)}

View file

@ -1,4 +1,4 @@
import { Text } from "@methanium/ui/markdown";
import Text from "@tensamin/markdown/text";
import { useStorage } from "@tensamin/storage/context";
import {
Avatar,

View file

@ -19,7 +19,9 @@ import { useMTP } from "@tensamin/mtp";
import { getMessage, useChat } from "../context";
import { decryptChatText, encryptChatText } from "@tensamin/crypto/chatSecret";
import { log, toast } from "@tensamin/shared/log";
import { Emoji, Input, normalizeShortcode, Text } from "@methanium/ui/markdown";
import Emoji, { normalizeShortcode } from "@tensamin/markdown/emoji";
import Input from "@tensamin/markdown/input";
import Text from "@tensamin/markdown/text";
import { useRecordEmojiUse } from "./emoji/emojiRanks";
import ReplyBox from "./replyBox";
import { useHotkey } from "@tensamin/hotkeys";

View file

@ -44,7 +44,7 @@ import type {
Ref,
} from "react";
import { useChat } from "../context";
import { Emoji } from "@methanium/ui/markdown";
import Emoji from "@tensamin/markdown/emoji";
import EmojiPicker from "./emoji/emojiPicker";
import { getRecentEmojis, useEmojiRanks } from "./emoji/emojiRanks";

View file

@ -6,7 +6,7 @@ import {
cn,
Skeleton,
} from "@methanium/ui";
import { Text } from "@methanium/ui/markdown";
import Text from "@tensamin/markdown/text";
import type { SelectedUser } from "@tensamin/identity/context";
import Wrapper from "@tensamin/identity/wrapper";
import { Forward, X } from "lucide-react";

View file

@ -9,6 +9,7 @@ import {
export type TextProps = {
value: string;
fontSize?: CSSProperties["fontSize"];
showEditedIndicator?: boolean;
};
/**
@ -25,6 +26,9 @@ export default function Text(props: TextProps) {
return (
<div className="tm-md-root" style={{ fontSize: props.fontSize }}>
{renderedBlocks}
{props.showEditedIndicator && (
<span className="ml-1 text-xs text-muted-foreground">(edited)</span>
)}
</div>
);
}

View file

@ -17,6 +17,7 @@
"@tauri-apps/api": "^2.11.1",
"@tensamin/cache": "workspace:*",
"@tensamin/hotkeys": "workspace:*",
"@tensamin/markdown": "workspace:*",
"@tensamin/mtp": "workspace:*",
"@tensamin/shared": "workspace:*",
"@tensamin/storage": "workspace:*",

View file

@ -1,29 +1,20 @@
import Accessibility from "./pages/accessibility";
import Cache from "./pages/cache";
import Call from "./pages/call";
import Chat from "./pages/chat";
import Index from "./pages/index";
import Licenses from "./pages/licenses";
import Profile from "./pages/profile";
import Security from "./pages/security";
import Theme from "./pages/theme";
import Hotkeys from "./pages/hotkeys";
import { lazy } from "react";
import { settingsNavigation } from "./navigation";
const pageComponents = {
profile: Profile,
security: Security,
chat: Chat,
call: Call,
cache: Cache,
theme: Theme,
accessibility: Accessibility,
hotkeys: Hotkeys,
licenses: Licenses,
profile: lazy(() => import("./pages/profile")),
security: lazy(() => import("./pages/security")),
chat: lazy(() => import("./pages/chat")),
call: lazy(() => import("./pages/call")),
cache: lazy(() => import("./pages/cache")),
theme: lazy(() => import("./pages/theme")),
accessibility: lazy(() => import("./pages/accessibility")),
hotkeys: lazy(() => import("./pages/hotkeys")),
licenses: lazy(() => import("./pages/licenses")),
} as const;
export const settingsPages = [
{ path: "/", component: Index },
{ path: "/", component: lazy(() => import("./pages/index")) },
...settingsNavigation.map((page) => ({
...page,
component: pageComponents[page.path],

View file

@ -1,4 +1,4 @@
import { Input as MDInput } from "@methanium/ui/markdown";
import MDInput from "@tensamin/markdown/input";
import { useMTP } from "@tensamin/mtp";
import { mtp } from "@tensamin/shared/data";
import { useStorage } from "@tensamin/storage/context";