Wrap database in async suspense value (#36)

This commit is contained in:
Mateusz Burzyński 2025-02-20 20:05:57 +01:00 committed by GitHub
parent 12cd21f1d3
commit 6acb94b5af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 51 additions and 28 deletions

View File

@ -4,7 +4,6 @@ import { classNames } from '~/utils/classNames';
import { AssistantMessage, getAnnotationsTokensUsage } from './AssistantMessage'; import { AssistantMessage, getAnnotationsTokensUsage } from './AssistantMessage';
import { UserMessage } from './UserMessage'; import { UserMessage } from './UserMessage';
import { useLocation } from '@remix-run/react'; import { useLocation } from '@remix-run/react';
import { db, chatId } from '~/lib/persistence/useChatHistory';
import { forkChat } from '~/lib/persistence/db'; import { forkChat } from '~/lib/persistence/db';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import WithTooltip from '~/components/ui/Tooltip'; import WithTooltip from '~/components/ui/Tooltip';
@ -29,7 +28,7 @@ export function saveProjectContents(messageId: string, contents: ProjectContents
} }
function hasFileModifications(content: string) { function hasFileModifications(content: string) {
return content.includes("__boltArtifact__"); return content.includes('__boltArtifact__');
} }
export const Messages = React.forwardRef<HTMLDivElement, MessagesProps>((props: MessagesProps, ref) => { export const Messages = React.forwardRef<HTMLDivElement, MessagesProps>((props: MessagesProps, ref) => {

View File

@ -2,7 +2,7 @@ import React, { useState } from 'react';
import { useNavigate } from '@remix-run/react'; import { useNavigate } from '@remix-run/react';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { db, deleteById, getAll, setMessages } from '~/lib/persistence'; import { database, deleteById, getAll, setMessages } from '~/lib/persistence';
import { logStore } from '~/lib/stores/logs'; import { logStore } from '~/lib/stores/logs';
import { classNames } from '~/utils/classNames'; import { classNames } from '~/utils/classNames';
import type { Message } from 'ai'; import type { Message } from 'ai';
@ -31,6 +31,7 @@ interface ApiKeys {
} }
export default function DataTab() { export default function DataTab() {
const db = database?.read();
const navigate = useNavigate(); const navigate = useNavigate();
const [isDeleting, setIsDeleting] = useState(false); const [isDeleting, setIsDeleting] = useState(false);

View File

@ -5,7 +5,7 @@ import { Dialog, DialogButton, DialogDescription, DialogRoot, DialogTitle } from
import { ThemeSwitch } from '~/components/ui/ThemeSwitch'; import { ThemeSwitch } from '~/components/ui/ThemeSwitch';
import { SettingsWindow } from '~/components/settings/SettingsWindow'; import { SettingsWindow } from '~/components/settings/SettingsWindow';
import { SettingsButton } from '~/components/ui/SettingsButton'; import { SettingsButton } from '~/components/ui/SettingsButton';
import { db, deleteById, getAll, chatId, type ChatHistoryItem, useChatHistory } from '~/lib/persistence'; import { database, deleteById, getAll, chatId, type ChatHistoryItem, useChatHistory } from '~/lib/persistence';
import { cubicEasingFn } from '~/utils/easings'; import { cubicEasingFn } from '~/utils/easings';
import { logger } from '~/utils/logger'; import { logger } from '~/utils/logger';
import { HistoryItem } from './HistoryItem'; import { HistoryItem } from './HistoryItem';
@ -39,6 +39,7 @@ const menuVariants = {
type DialogContent = { type: 'delete'; item: ChatHistoryItem } | null; type DialogContent = { type: 'delete'; item: ChatHistoryItem } | null;
export const Menu = () => { export const Menu = () => {
const db = database?.read();
const { duplicateCurrentChat, exportChat } = useChatHistory(); const { duplicateCurrentChat, exportChat } = useChatHistory();
const menuRef = useRef<HTMLDivElement>(null); const menuRef = useRef<HTMLDivElement>(null);
const [list, setList] = useState<ChatHistoryItem[]>([]); const [list, setList] = useState<ChatHistoryItem[]>([]);

View File

@ -32,6 +32,21 @@ export function createAsyncSuspenseValue<T>(getValue: () => Promise<T>) {
}; };
const asyncValue = { const asyncValue = {
load: async () => {
if (!record) {
return load();
}
switch (record.status) {
case 'pending':
return record.promise;
case 'resolved':
return record.value;
case 'rejected':
throw record.error;
}
},
read() { read() {
if (!record) { if (!record) {
throw load(); throw load();

View File

@ -3,7 +3,7 @@ import { useCallback, useEffect, useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { import {
chatId as chatIdStore, chatId as chatIdStore,
db, database,
description as descriptionStore, description as descriptionStore,
getMessages, getMessages,
updateChatDescription, updateChatDescription,
@ -44,6 +44,7 @@ export function useEditChatDescription({
customChatId, customChatId,
syncWithGlobalStore, syncWithGlobalStore,
}: EditChatDescriptionOptions): EditChatDescriptionHook { }: EditChatDescriptionOptions): EditChatDescriptionHook {
const db = database?.read();
const chatIdFromStore = useStore(chatIdStore); const chatIdFromStore = useStore(chatIdStore);
const [editing, setEditing] = useState(false); const [editing, setEditing] = useState(false);
const [currentDescription, setCurrentDescription] = useState(initialDescription); const [currentDescription, setCurrentDescription] = useState(initialDescription);

View File

@ -15,6 +15,7 @@ import {
createChatFromMessages, createChatFromMessages,
} from './db'; } from './db';
import { loadProblem } from '~/components/chat/LoadProblemButton'; import { loadProblem } from '~/components/chat/LoadProblemButton';
import { createAsyncSuspenseValue } from '../asyncSuspenseValue';
export interface ChatHistoryItem { export interface ChatHistoryItem {
id: string; id: string;
@ -26,14 +27,19 @@ export interface ChatHistoryItem {
const persistenceEnabled = !import.meta.env.VITE_DISABLE_PERSISTENCE; const persistenceEnabled = !import.meta.env.VITE_DISABLE_PERSISTENCE;
export const db = persistenceEnabled ? await openDatabase() : undefined; export const database = persistenceEnabled ? createAsyncSuspenseValue(openDatabase) : undefined;
if (typeof document !== 'undefined') {
database?.preload();
}
export const chatId = atom<string | undefined>(undefined); export const chatId = atom<string | undefined>(undefined);
export const description = atom<string | undefined>(undefined); export const description = atom<string | undefined>(undefined);
export function useChatHistory() { export function useChatHistory() {
const db = database?.read();
const navigate = useNavigate(); const navigate = useNavigate();
const { id: mixedId, problemId } = useLoaderData<{ id?: string, problemId?: string }>() ?? {}; const { id: mixedId, problemId } = useLoaderData<{ id?: string; problemId?: string }>() ?? {};
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const [initialMessages, setInitialMessages] = useState<Message[]>([]); const [initialMessages, setInitialMessages] = useState<Message[]>([]);