From 21bd46010fdb09fa051bc17649d8896169bdc0c7 Mon Sep 17 00:00:00 2001 From: xCyanGrizzly Date: Thu, 23 Jul 2026 11:05:18 +0200 Subject: [PATCH] feat(stls): flat package list, drop heuristic auto-grouping Render the STL view as a flat per-package list (listDisplayItems no longer collapses packages into group rows) and hide the Ungrouped tab, now that the creator filter organizes the list. Remove the worker's heuristic auto-grouping passes (rule/time/pattern/creator/zip-path/reply-chain/caption); album grouping is kept. Existing groups and manual grouping actions are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/app/(app)/stls/_components/stl-table.tsx | 11 ++---- src/lib/telegram/queries.ts | 24 ++++++------- worker/src/worker.ts | 37 +++++--------------- 3 files changed, 23 insertions(+), 49 deletions(-) diff --git a/src/app/(app)/stls/_components/stl-table.tsx b/src/app/(app)/stls/_components/stl-table.tsx index d914bb0..8814c55 100644 --- a/src/app/(app)/stls/_components/stl-table.tsx +++ b/src/app/(app)/stls/_components/stl-table.tsx @@ -500,14 +500,9 @@ export function StlTable({ )} - - Ungrouped - {ungroupedTotalCount > 0 && ( - - {ungroupedTotalCount} - - )} - + {/* "Ungrouped" tab hidden: the STL list is now flat and grouping is + no longer surfaced here. The tab content below is kept (unreachable) + to avoid churn; remove it and its data fetch if grouping is dropped. */} diff --git a/src/lib/telegram/queries.ts b/src/lib/telegram/queries.ts index b667101..a1262bd 100644 --- a/src/lib/telegram/queries.ts +++ b/src/lib/telegram/queries.ts @@ -135,31 +135,31 @@ export async function listDisplayItems(options: { const sortCol = sortBy === "fileName" ? `"fileName"` : sortBy === "fileSize" ? `"fileSize"` : `"indexedAt"`; const sortDir = order === "asc" ? "ASC" : "DESC"; - // Step 1: Count display items + // NOTE: The STL list is intentionally FLAT — every package is its own display + // row regardless of packageGroupId. Grouping is no longer surfaced in this + // view (the creator column/filter organizes the list instead). PackageGroup + // rows and the manual grouping actions still exist in the DB/UI; they just + // don't drive this list's layout anymore. + + // Step 1: Count display items (one per package) const countResult = await prisma.$queryRawUnsafe<[{ count: bigint }]>( - `SELECT COUNT(*) AS count FROM ( - SELECT DISTINCT COALESCE(p."packageGroupId", p."id") AS display_id - FROM packages p - ${whereClause} - ) AS display_items`, + `SELECT COUNT(*) AS count FROM packages p ${whereClause}`, ...params ); const total = Number(countResult[0].count); - // Step 2: Get display item IDs for this page + // Step 2: Get package IDs for this page const limitParam = paramIdx++; const offsetParam = paramIdx++; const displayRows = await prisma.$queryRawUnsafe< { display_id: string; display_type: string }[] >( `SELECT - COALESCE(p."packageGroupId", p."id") AS display_id, - CASE WHEN p."packageGroupId" IS NOT NULL THEN 'group' ELSE 'package' END AS display_type, - MAX(p.${sortCol}) AS sort_value + p."id" AS display_id, + 'package' AS display_type, + p.${sortCol} AS sort_value FROM packages p ${whereClause} - GROUP BY COALESCE(p."packageGroupId", p."id"), - CASE WHEN p."packageGroupId" IS NOT NULL THEN 'group' ELSE 'package' END ORDER BY sort_value ${sortDir} LIMIT $${limitParam} OFFSET $${offsetParam}`, ...params, limit, (page - 1) * limit diff --git a/worker/src/worker.ts b/worker/src/worker.ts index 793ba0b..3c3971f 100644 --- a/worker/src/worker.ts +++ b/worker/src/worker.ts @@ -65,7 +65,7 @@ import { readRarContents } from "./archive/rar-reader.js"; import { read7zContents } from "./archive/sevenz-reader.js"; import { byteLevelSplit, concatenateFiles } from "./archive/split.js"; import { uploadToChannel, UploadStallError } from "./upload/channel.js"; -import { processAlbumGroups, processRuleBasedGroups, processTimeWindowGroups, processPatternGroups, processCreatorGroups, processZipPathGroups, processReplyChainGroups, processCaptionGroups, detectGroupingConflicts, type IndexedPackageRef } from "./grouping.js"; +import { processAlbumGroups, detectGroupingConflicts, type IndexedPackageRef } from "./grouping.js"; import { db } from "./db/client.js"; import type { TelegramAccount, TelegramChannel } from "@prisma/client"; import type { Client } from "tdl"; @@ -1479,34 +1479,13 @@ async function processArchiveSets( scanResult.photos ); - // Auto-grouping passes (gated by per-channel flag) - const channelRecord = await db.telegramChannel.findUnique({ - where: { id: channel.id }, - select: { autoGroupEnabled: true }, - }); - - if (channelRecord?.autoGroupEnabled !== false) { - // Learned rule-based grouping (from manual overrides) - await processRuleBasedGroups(channel.id, indexedPackageRefs); - - // Time-window grouping for remaining ungrouped packages - await processTimeWindowGroups(channel.id, indexedPackageRefs); - - // Pattern-based grouping (date patterns, project slugs) - await processPatternGroups(channel.id, indexedPackageRefs); - - // Creator-based grouping (3+ files from same creator) - await processCreatorGroups(channel.id, indexedPackageRefs); - - // ZIP path prefix grouping (shared root folder inside archives) - await processZipPathGroups(channel.id, indexedPackageRefs); - - // Reply chain grouping (messages replying to same root) - await processReplyChainGroups(channel.id, indexedPackageRefs); - - // Caption fuzzy match grouping - await processCaptionGroups(channel.id, indexedPackageRefs); - } + // Heuristic auto-grouping passes (rule/time/pattern/creator/zip-path/ + // reply-chain/caption) were removed: the STL view is now a flat list + // organized by the creator filter, so automatically inventing groups at + // ingestion is no longer wanted. Album grouping above is kept because it + // reflects real upload structure (files posted together as one Telegram + // album), not a heuristic guess. Existing groups and the manual grouping + // actions in the UI are unaffected. // Check for potential grouping conflicts await detectGroupingConflicts(channel.id, indexedPackageRefs);