refactor!: replace Tantivy search engine with DuckDB

This commit is contained in:
rustmailer
2026-03-03 12:30:26 +08:00
parent ef4ab3496e
commit d2936ed4a7
52 changed files with 3594 additions and 1821 deletions
@@ -23,7 +23,7 @@ import {
CardHeader,
CardTitle,
} from '@/components/ui/card'
import { UserAuthForm } from './components/user-auth-form'
import { UserAuthForm } from './user-auth-form'
import { useTranslation } from 'react-i18next'
import { AuthLayout } from './auth-layout'
@@ -1,63 +0,0 @@
//
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
//
// This file is part of the Bichon Email Archiving Project
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { IconLogout } from '@tabler/icons-react'
import { ConfirmDialog } from '@/components/confirm-dialog'
import { useTranslation } from 'react-i18next'
interface Props {
open: boolean
onOpenChange: (open: boolean) => void
handleConfirm: () => void
}
export function LogoutConfirmDialog({ open, onOpenChange, handleConfirm }: Props) {
const { t } = useTranslation()
const handleLogout = () => {
handleConfirm();
onOpenChange(false);
};
return (
<ConfirmDialog
open={open}
onOpenChange={onOpenChange}
handleConfirm={handleLogout}
className="max-w-md"
title={
<span className='text-destructive'>
<IconLogout
className='mr-1 inline-block stroke-destructive'
size={18}
/>{' '}
{t('auth.logout')}
</span>
}
desc={
<p>
{t('auth.areYouSureYouWantToLogOut')}
<br />
{t('auth.youWillNeedToLogInAgain')}
</p>
}
confirmText={t('auth.logout')}
cancelBtnText={t('common.cancel')}
/>
)
}
+3
View File
@@ -29,6 +29,7 @@ import { get_dashboard_stats, TimeBucket } from '@/api/system/api';
import { Main } from '@/components/layout/main';
import { FixedHeader } from '@/components/layout/fixed-header';
import { useTranslation } from 'react-i18next';
import { getToken } from '@/stores/authStore';
interface DailyActivity {
date: string;
@@ -102,8 +103,10 @@ const EmptyTable = ({ title }: { title: string }) => (
);
export default function MailArchiveDashboard() {
const token = getToken();
const { data: stats, isLoading } = useQuery({
queryKey: ['dashboard-stats'],
enabled: !!token,
queryFn: get_dashboard_stats,
});
@@ -118,7 +118,7 @@ export function MailList({
)}
{items.map((item, index) => {
const hasAttachments = item.attachments && item.attachments.length > 0
const hasAttachments = item.attachment_count > 0
const isSelected = currentEnvelope?.id === item.id
const isChecked = hasSelected(item.id)
return (
@@ -171,7 +171,7 @@ export function MailList({
{hasAttachments && (
<div className="flex items-center gap-1">
<Paperclip className="h-3 w-3" />
<span>{item.attachments?.length}</span>
<span>{item.attachment_count}</span>
</div>
)}
<span className="hidden md:inline">{formatBytes(item.size)}</span>
+1 -1
View File
@@ -207,7 +207,7 @@ export function MailListTable({
{
id: "attachment_count",
header: () => <Paperclip size={16} />,
cell: ({ row }) => <span className='text-xs'>{(row.original.attachments ?? []).length}</span>,
cell: ({ row }) => <span className='text-xs'>{row.original.attachment_count}</span>,
meta: { className: 'text-left text-xs' },
minSize: 40,
maxSize: 40
+2 -2
View File
@@ -154,7 +154,7 @@ export function MailList({
)}
{items.map((item, index) => {
const hasAttachments = item.attachments && item.attachments.length > 0
const hasAttachments = item.attachment_count > 0
const isSelectedRow = currentEnvelope?.id === item.id
const isChecked = hasSelected(item.account_id, item.id)
@@ -209,7 +209,7 @@ export function MailList({
{hasAttachments && (
<div className="flex items-center gap-1">
<Paperclip className="h-3 w-3" />
<span>{item.attachments?.length}</span>
<span>{item.attachment_count}</span>
</div>
)}