import React, { Fragment, useCallback, useMemo, useState } from 'react' import { Button, Modal, Badge } from '@janhq/joi' import { atom, useAtom, useSetAtom } from 'jotai' import { AlertTriangleIcon } from 'lucide-react' import { twMerge } from 'tailwind-merge' import Spinner from '@/containers/Loader/Spinner' import useMigratingData from '@/hooks/useMigratingData' import { didShowMigrationWarningAtom } from '@/helpers/atoms/AppConfig.atom' export const showMigrationModalAtom = atom(false) const MigrationStates = ['idle', 'in_progress', 'failed', 'success'] as const type MigrationState = (typeof MigrationStates)[number] const ModalMigrations = () => { const setDidShowMigrationModal = useSetAtom(didShowMigrationWarningAtom) const [showMigrationModal, setShowMigrationModal] = useAtom( showMigrationModalAtom ) const [step, setStep] = React.useState(1) const { migrateModels, migrateThreadsAndMessages } = useMigratingData() const [threadAndMessageMigrationState, setThreadAndMessageMigrationState] = useState('idle') const [modelMigrationState, setModelMigrationState] = useState('idle') const getStepTitle = () => { switch (step) { case 1: return 'Important Update: Data Migration Needed' default: return threadAndMessageMigrationState === 'in_progress' || modelMigrationState === 'in_progress' ? 'Migrating' : 'Migration Completed' } } const migrationThreadsAndMessages = useCallback(async () => { setThreadAndMessageMigrationState('in_progress') try { await migrateThreadsAndMessages() setThreadAndMessageMigrationState('success') console.debug('Migrating threads and messages successfully!') } catch (err) { console.error('Migrating threads and messages error', err) setThreadAndMessageMigrationState('failed') } }, [setThreadAndMessageMigrationState, migrateThreadsAndMessages]) const migratingModels = useCallback(async () => { setModelMigrationState('in_progress') try { await migrateModels() setModelMigrationState('success') console.debug('Migrating models successfully!') } catch (err) { console.error('Migrating models error', err) setModelMigrationState('failed') } }, [migrateModels, setModelMigrationState]) const onStartMigrationClick = useCallback(async () => { setStep(2) await migratingModels() await migrationThreadsAndMessages() }, [migratingModels, migrationThreadsAndMessages]) const onDismiss = useCallback(() => { setStep(1) setShowMigrationModal(false) setDidShowMigrationModal(true) }, [setDidShowMigrationModal, setShowMigrationModal]) const disableDismissButton = useMemo( () => threadAndMessageMigrationState === 'in_progress' || modelMigrationState === 'in_progress', [threadAndMessageMigrationState, modelMigrationState] ) return ( {step === 1 && (

{`We've made some exciting improvements to the app, but we need your help to update your data.`}

What to expect:

  • Some threads or models{' '} might be missing after the migration.
  • This will take a few seconds and reload the app.
)} {step === 2 && (
{threadAndMessageMigrationState !== 'in_progress' && ( <> {threadAndMessageMigrationState === 'success' ? ( Success ) : ( Failed )} )}

Threads

{threadAndMessageMigrationState === 'in_progress' ? ( ) : ( threadAndMessageMigrationState !== 'success' && ( ) )}
{modelMigrationState !== 'in_progress' && ( <> {modelMigrationState === 'success' ? ( Success ) : ( Failed )} )}

Models

{modelMigrationState === 'in_progress' ? ( ) : ( modelMigrationState === 'failed' && ( ) )}
)} } /> ) } export default ModalMigrations