diff --git a/src/modules/duckdb/build.rs b/src/modules/duckdb/build.rs index 3e6869b..eb97d78 100644 --- a/src/modules/duckdb/build.rs +++ b/src/modules/duckdb/build.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use arrow::array::{BooleanArray, Int32Array, Int64Array, ListBuilder, StringBuilder, UInt64Array}; +use arrow::array::{Int32Array, Int64Array, ListBuilder, StringBuilder, UInt64Array}; use arrow::datatypes::{DataType, Field, Schema}; use arrow::record_batch::RecordBatch; use std::sync::Arc; @@ -57,7 +57,6 @@ pub fn build_record_batch(items: &[Envelope]) -> RecordBatch { Field::new("size_bytes", DataType::UInt64, true), Field::new("thread_id", DataType::Utf8, true), Field::new("message_id", DataType::Utf8, true), - Field::new("has_attachment", DataType::Boolean, false), Field::new("attachment_count", DataType::Int32, false), Field::new("regular_attachment_count", DataType::Int32, false), Field::new( @@ -87,7 +86,6 @@ pub fn build_record_batch(items: &[Envelope]) -> RecordBatch { let mut size_b = UInt64Array::builder(capacity); let mut thread_id_b = StringBuilder::with_capacity(capacity, capacity * 20); let mut msg_id_b = StringBuilder::with_capacity(capacity, capacity * 30); - let mut has_att_b = BooleanArray::builder(capacity); let mut att_count_b = Int32Array::builder(capacity); let mut regular_att_count_b = Int32Array::builder(capacity); let mut tags_b = ListBuilder::new(StringBuilder::new()); @@ -119,7 +117,6 @@ pub fn build_record_batch(items: &[Envelope]) -> RecordBatch { size_b.append_value(e.size as u64); thread_id_b.append_value(&e.thread_id); msg_id_b.append_value(&e.message_id); - has_att_b.append_value(e.regular_attachment_count > 0); att_count_b.append_value(e.attachment_count as i32); regular_att_count_b.append_value(e.regular_attachment_count as i32); tags_b.append(true); @@ -145,7 +142,6 @@ pub fn build_record_batch(items: &[Envelope]) -> RecordBatch { Arc::new(size_b.finish()), Arc::new(thread_id_b.finish()), Arc::new(msg_id_b.finish()), - Arc::new(has_att_b.finish()), Arc::new(att_count_b.finish()), Arc::new(regular_att_count_b.finish()), Arc::new(tags_b.finish()), diff --git a/src/modules/duckdb/init.rs b/src/modules/duckdb/init.rs index fba254e..12b0383 100644 --- a/src/modules/duckdb/init.rs +++ b/src/modules/duckdb/init.rs @@ -1212,7 +1212,7 @@ impl DuckDBManager { { let sql = format!( r#" - SELECT has_attachment, COUNT(*) AS cnt + SELECT (regular_attachment_count > 0) AS has_attachment, COUNT(*) AS cnt FROM envelopes {account_filter} GROUP BY has_attachment @@ -1559,8 +1559,11 @@ impl DuckDBManager { } if let Some(has) = filter.has_attachment { - base_sql.push_str(" AND e.has_attachment = ? "); - args.push(has.into()); + if has { + base_sql.push_str(" AND e.regular_attachment_count > 0 "); + } else { + base_sql.push_str(" AND e.regular_attachment_count = 0 "); + } } if let Some(tags) = filter.tags { diff --git a/src/modules/duckdb/migrations/V1__initial.sql b/src/modules/duckdb/migrations/V1__initial.sql index 9d98706..4dcd397 100644 --- a/src/modules/duckdb/migrations/V1__initial.sql +++ b/src/modules/duckdb/migrations/V1__initial.sql @@ -34,7 +34,6 @@ CREATE TABLE IF NOT EXISTS envelopes ( message_id TEXT, -- attachment summary - has_attachment BOOLEAN NOT NULL, attachment_count INTEGER NOT NULL CHECK (attachment_count >= 0), regular_attachment_count INTEGER NOT NULL CHECK (regular_attachment_count >= 0), tags VARCHAR[], diff --git a/src/modules/envelope/extractor.rs b/src/modules/envelope/extractor.rs index 5b8c789..ef9a2a5 100644 --- a/src/modules/envelope/extractor.rs +++ b/src/modules/envelope/extractor.rs @@ -390,7 +390,7 @@ pub async fn reattach_eml_content( ) })?; - if !envelope.has_attachments() { + if !envelope.has_any_attachments() { return Ok((envelope, restored_eml)); } diff --git a/src/modules/indexer/envelope.rs b/src/modules/indexer/envelope.rs index d5b8d24..8b05f3b 100644 --- a/src/modules/indexer/envelope.rs +++ b/src/modules/indexer/envelope.rs @@ -49,7 +49,7 @@ pub struct Envelope { } impl Envelope { - pub fn has_attachments(&self) -> bool { + pub fn has_any_attachments(&self) -> bool { self.attachment_count > 0 } diff --git a/web/src/features/auth/user-auth-form.tsx b/web/src/features/auth/user-auth-form.tsx index 79dc441..60f1cb2 100644 --- a/web/src/features/auth/user-auth-form.tsx +++ b/web/src/features/auth/user-auth-form.tsx @@ -21,7 +21,7 @@ import { HTMLAttributes, useState } from 'react' import { z } from 'zod' import { useForm } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' -import { cn } from '@/lib/utils' +import { cn, toSearchParams } from '@/lib/utils' import { Form, FormControl, @@ -65,7 +65,7 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) { const { t } = useTranslation() const { search } = useLocation(); - const redirect = new URLSearchParams(search).get('redirect') || '/'; + const redirect = toSearchParams(search).get('redirect') || '/'; const formSchema = getFormSchema(t) const form = useForm>({ @@ -92,11 +92,11 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) { if (result.theme) { setTheme(result.theme); } - + if (result.language) { i18n.changeLanguage(result.language); } - + navigate({ to: redirect }); } else { toast({ diff --git a/web/src/features/oauth2-result/index.tsx b/web/src/features/oauth2-result/index.tsx index f749801..ea77488 100644 --- a/web/src/features/oauth2-result/index.tsx +++ b/web/src/features/oauth2-result/index.tsx @@ -23,11 +23,12 @@ import { useLocation } from "@tanstack/react-router"; import { AlertCircle, CheckCircle2, Info } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useTranslation } from "react-i18next"; +import { toSearchParams } from "@/lib/utils"; export default function OAuth2Result() { const { t } = useTranslation(); const { search } = useLocation(); - const params = new URLSearchParams(search); + const params = toSearchParams(search); const error = params.get("error"); const message = params.get("message"); const success = params.get("success"); diff --git a/web/src/features/settings/configurations/index.tsx b/web/src/features/settings/configurations/index.tsx index a76c760..d5d05dc 100644 --- a/web/src/features/settings/configurations/index.tsx +++ b/web/src/features/settings/configurations/index.tsx @@ -25,13 +25,10 @@ import { ShieldCheck, Server, Database, - Globe, - Lock, Activity, InfoIcon, Mail, - Zap, - Cpu + Zap } from "lucide-react" import { get_system_configurations } from "@/api/system/api" import { useQuery } from "@tanstack/react-query" diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts index 18142d8..0549520 100644 --- a/web/src/lib/utils.ts +++ b/web/src/lib/utils.ts @@ -187,4 +187,15 @@ export function showNumbers(current: number, total: number) { } } return result +} + + +export function toSearchParams(obj: Record): URLSearchParams { + const params = new URLSearchParams(); + Object.entries(obj).forEach(([key, value]) => { + if (value !== undefined && value !== null) { + params.append(key, String(value)); + } + }); + return params; } \ No newline at end of file