Tags: SysAdminDoc/Discrub
Tags
v2.9.0 - Multi-select + Auto-apply views + Pinned strip + Sweep + Con… …text menu Five features. No new permissions. Multi-select everywhere - New common-components/multi-select/use-multi-select.ts hook owns selectionMode + toggle/selectAll/clear state; lazy-prunes ids that drop out of the visible set. - Bookmarks, Receipts, Schedules tabs gain Select mode with checkbox overlays and bulk actions (bookmarks: pin/unpin/delete; receipts: delete; schedules: enable/disable/delete). Auto-apply saved views - SavedView gains autoApplyOnTarget flag + findAutoApplyView service helper. Channel Messages runs an effect keyed on (guildId,channelId) that applies the matching view once per selection change. - FlashOn/FlashOff toggle in the Manage Views list; disabled when the view has no target. Pinned bookmarks strip - New src/containers/bookmarks/pinned-bookmarks-strip.tsx: collapsible Accordion above the message table showing bookmarks where pinned=true && channelId === selected. Live-refreshes via chrome.storage.onChanged. - Plugged into Channel Messages and Direct Messages. View Sweep - New src/common-components/saved-views/view-sweep-dialog.tsx: channel picker + format selector. Instantiates a local ExportUtils + hands off to exportChannels (non-HTML formats only to avoid useReactToPrint contentRef requirements). Applies the view's export preset before running so artist-mode/media-download/etc. are honored. Right-click context menu - New src/components/message-context-menu.tsx: anchorPosition-based Menu wired to table-message via onContextMenu. Actions: Open in Discord, Pin to channel top (auto-bookmarks + pins), Bookmark, Copy content / Markdown / Discord quote, Copy ID, Copy raw JSON.
v2.8.0 - Saved Views, Live Text Search, Receipt Re-delete, Bookmark N… …otes+Pin, Link Tree Export Five features. No new permissions. Saved Views — views-service.ts CRUD (bounded to 50, by-ID references to filter/export presets so edits propagate), a SavedViewsBar with chip list / create dialog / manage dialog on Channel Messages. Apply re-uses the existing selection, filter, setSetting, and searchCriteria paths. Live channel text search — LiveSearchPanel scans the loaded messages with regex or plain text (debounced 180ms, virtualized list via react-window, capped at 500 hits with truncation chip, deep-link button per row). New toolbar icon toggles it. Receipt-driven re-delete — receipts.tsx now cross-references a receipt's sampled message IDs against the currently-loaded set and exposes a 'Re-delete survivors' action in the detail dialog with its own confirmation. Routes through the existing deleteMessages thunk so the normal rate-limit and permission handling stays. Bookmark notes + local pin — BookmarkedMessage gets optional note (1000 chars) and pinned fields, with new setBookmarkNote / toggleBookmarkPin helpers. Bookmarks tab gains inline note editing (Cmd/Ctrl+Enter commits, Esc cancels) and a pin icon; pinned bookmarks float to the top with a mauve accent border. Link Tree export — new ExportType.LINK_TREE emits one Discord deep-link per message as plain text. Reuses the _addToZip plumbing, skips _processMessages like URL_LIST does. Registered in the extension picker + tooltip description.
v2.7.0 - Command palette, preset sharing, schedule history, streamer 2.0
Five features. No new permissions.
1) Preset import/export + pin-to-toolbar
- PresetShareEnvelope { magic, version, kind, name, payload } with
version guard so newer shares don't silently load on old clients.
- Per-preset Copy-to-Clipboard icon in the manager, plus an
Import-from-text button that validates the paste.
- New favorite flag; FavoritePresetChips surfaces pinned filter
presets as one-click chips in the message-table toolbar.
2) Schedule run history
- Schedule.runHistory[] bounded to 20, newest-first.
- Background SW alarm handler now appends a Pending record with
delivery-status note (no Discord tab vs. banner delivered).
- Schedules tab: per-row History icon that expands the history
panel; Pending rows expose an inline Retry button.
- recordScheduleRun() used by both the SW and the dialog's
handleRunSchedule so lastRun + history stay consistent.
3) Streamer mode 2.0
- New APP_STREAMER_NAME_SCRUBBER setting: when on (together with
streamer mode), replaces every author name with User A/B/C...
via the session-scoped NameScrubber utility (labels shuffle on
reload so you can't correlate across clips).
- New APP_STREAMER_AUTO_CHANNELS setting stores channel/DM IDs
where streamer mode auto-enables. New useStreamerMode hook is
the single source of truth for manual + auto logic.
- Channel Messages gets a Visibility chip to toggle the current
channel in the auto list.
- Header status shows "Streamer · Auto" when triggered by the
channel rule so users know why streamer is on.
4) Command palette (Ctrl/Cmd + K)
- Lightweight fuzzy matcher, arrow/Enter nav, builds entries on
demand from: dialog tabs, presets (filter + export), schedules,
core actions. Allows typing into other inputs.
- Palette's "apply filter preset" entry dispatches a
discrub:apply-filter-preset CustomEvent the message-table
toolbar listens for, so preset application always flows through
the same code path.
v2.6.0 - Deep-link, shortcuts, Me analytics, quick-range chips, copy-as Five focused power-user features. All local; no new permissions. 1) Open in Discord Wired into every place Discrub shows a message: table rows, attachment-gallery lightbox, GDPR search results, bookmarks, receipt detail dialog. New src/utils/open-in-discord.ts builds canonical URLs (/@me/<channel>/<message> for DMs, /channels/<guild>/<channel>/<message> for servers) and navigates window.top. New src/common-components/open-in-discord-button shared icon button. BookmarkedMessage now stores optional guildId so server bookmarks deep-link correctly — older bookmarks still work via the @me fallback. Receipts for deleted/purged messages drop the messageId (the anchor is gone from Discord) but still link to the channel for context. 2) Keyboard shortcuts New src/common-components/keyboard-shortcuts: useKeyboardShortcuts hook + ShortcutCheatsheet dialog. Shift+? opens the cheatsheet, Esc closes the Discrub dialog, 1..9 + 0 jump between tabs. Scoped to the extension iframe via a window-level keydown listener; inputs/textareas are ignored unless shortcut.allowInInputs. Help-icon button added to the dialog header. 3) "Me" analytics sub-view Analytics tab gets an Everyone/Just-me toggle (ToggleButtonGroup). "Just me" filters scopedMessages by currentUser.id before the memo'd compute — zero net new stats, everything automatically rescopes: per-user list, hourly/daily heatmap, top words, emoji, attachments, reactions, pinned, edited. Disabled gracefully when no current user is available. 4) Quick range chips New src/containers/channel-messages/quick-range-chips.tsx: Last 24h / 7d / 30d / 90d / 1y. One click sets searchAfterDate, clears searchBeforeDate, and fires getMessageData immediately. Collapses a ~6-click archive flow to 1 click. 5) Copy as... New src/containers/message-table-toolbar/components/copy-as-menu.tsx. Four formats: plain text, Markdown (bold author, blockquoted body), Discord quote (paste back into any channel), JSON. Operates on selection if any, otherwise on the visible filtered dataset.
v2.5.0 - Scheduled auto-export Set up recurring exports for a server, channel, or DM. Schedules fire via chrome.alarms (the only new permission) even when Chrome is idle. When a schedule is due Discrub banners it at the top of the dialog with a one-click Run now — the export dialog always shows before the download starts, nothing runs without the user's confirmation. This is "alarm-triggered + dialog-assisted" automation: the truly zero-touch path isn't reliable in MV3 (service-worker lifetime, token capture requiring a live Discord tab), so we opted for the variant that degrades gracefully. A fired alarm with no live Discord tab stages a pending-run flag; next Discrub open surfaces it. New surfaces - src/services/schedules-service.ts — CRUD, cadence modelling (daily/weekly/monthly), computeNextRun helper, pending-run queue, bounded to 25 schedules. - src/containers/schedules/schedules.tsx — new tab: list with inline enable toggle, Run now button, editor dialog for create/edit with target / format / cadence pickers. - Manifest: adds "alarms". No new host or download permissions. - public/resources/js/background.js — chrome.alarms lifecycle: syncScheduleAlarms() reconciles stored schedules against Chrome's alarm list at boot, onInstalled, and on storage change. onAlarm handler writes a pending-run flag and attempts live delivery into any open Discord tab. - src/chrome/content.js — new SCHEDULE_FIRED message forwarded into the dialog iframe via postMessage. - src/containers/discrub-dialog/discrub-dialog.tsx — listens for schedule-fired postMessages + checks pending-run queue on mount, shows a top-of-dialog info banner with Run now / Dismiss. - Menu bar gets a Schedules slot at index 8 (About=9, Settings=10).
v2.4.0 - Full-text search across imported GDPR data The Data Import tab now has a Browse / Search toggle. In Search mode, you can query every message in every imported channel at once — this is the feature GDPR imports were always missing. Discord's own search famously breaks on large servers and can't search DMs reliably; this one just works because everything runs locally against the already- imported data. Highlights - Regex or plain text (case-insensitive). - Optional channel filter; before/after date filters. - Debounced (180 ms) so typing is smooth on 500k-message packages. - Virtualized results (react-window), capped at 500 hits with an explicit warning chip when the cap is hit. - Each result shows the channel, timestamp, match-count (if >1), and a snippet with the match highlighted in the Catppuccin accent colour. "Open in channel" jumps straight into browse mode for that channel. - Invalid regex surfaces an inline error rather than throwing. New files - src/containers/data-import/import-search.ts: pure, side-effect-free search logic with string-match and global-regex paths. - SearchPane + SearchResultRow components inside data-import.tsx.
v2.3.0 - Saved presets + Gallery bulk actions + Receipts tab Three new features. None require new permissions; all extend existing patterns and reuse already-bundled deps. Saved filter & export presets - New src/services/presets-service.ts: CRUD for named presets in chrome.storage.local (50/kind, upsert-by-name semantics, bounded). - New src/common-components/preset-bar: shared dropdown + save/manage affordance, wired into filter-modal and default-content. - Filter presets round-trip Date values via ISO strings. - Export presets persist via setSetting so the Config tab stays in sync after applying a preset. - New setFilters action in message-slice for single-shot replace. Attachment Gallery bulk actions - Selection mode with checkbox overlays per tile, Select All Visible / Deselect All, outline highlight on selected tiles. - Download as ZIP streams via @transcend-io/conflux + streamSaver (already bundled); filename collisions deduped with _N suffix; progress bar; partial-failure surface in a Snackbar. - Delete selected routes through the existing deleteMessages thunk behind an explicit "deletes source messages, not just attachments" warning dialog. Receipts tab (local audit log) - New src/services/receipts-service.ts: bounded ring buffer (500 receipts) in chrome.storage.local with sample message refs capped at 200 per receipt and content truncation at 2KB. - Emit sites: purge-slice (per entity at completion), message-slice deleteMessages (delete/edit/unreact breakdown), editMessages, editMessagesWithContents. Receipts include before/after content for edits. - New src/containers/receipts/receipts.tsx tab: virtualized list (react-window), action filter + text search, detail dialog with diff view, CSV/JSON export of the visible set, clear-all behind a confirmation. - Wired into menu-bar (Receipts slot) and discrub-dialog menuIndex switch (Receipts=7, About=8, Settings=9). Type decls for streamsaver and @transcend-io/conflux added to src/global-types.d.ts so the TS gallery-zip helper compiles without ambient any.
v2.2.3 - Real bugs from a focused code-review pass Find & Replace correctness - String.prototype.replace(string, replacement) only replaces the FIRST match. The match counter counts all matches. So plain-text replace of "foo" with "bar" in "foo foo foo" would count 3 matches but only produce "bar foo foo". Switched the plain-text branch to replaceAll() so the count and the replacement agree. Data Import perf - Browsing a GDPR data package channel rendered every message as a DOM node inside a 400px overflow box. A channel with 50k+ messages would freeze the tab for seconds. Now uses react-window FixedSizeList; overscan=8 for smooth scroll. Purge preview perf - The top-user breakdown sorted Object.entries of messagesByUser on every render. Memoized with useMemo keyed on preview. - Hoisted the Intl.DateTimeFormat instance from per-render to module scope.
v2.2.2 - Export cancellation correctness + full slice audit Bulk exports (exportChannels) were advancing the "since last export" timestamp for channels that were cancelled mid-compress, causing the next incremental export to silently skip those channels. Fixed by moving the exportedChannelIds.push after the isAppStopped check and re-verifying cancellation state right before each timestamp write. Same guard added for single-channel exports so cancelling during generateZip() no longer marks the channel as "fully exported." generateZip() is now wrapped in try/catch so a finalize failure surfaces in the console and the app state still resets cleanly instead of leaving the dialog stuck in the "Generating" state. Completed a deep audit pass across message/purge/export Redux slices and all container components — confirmed no remaining side-effect bugs, timer leaks, or orphaned promise chains from the earlier QA pass. No container changes needed.
PreviousNext