Skip to content

feat: batch UX — Fast on Profile/Likes, date range, reset queue, step lights (v2.4.0)#71

Merged
zendegani merged 22 commits into
mainfrom
feat/batch-ux
Jun 14, 2026
Merged

feat: batch UX — Fast on Profile/Likes, date range, reset queue, step lights (v2.4.0)#71
zendegani merged 22 commits into
mainfrom
feat/batch-ux

Conversation

@zendegani

@zendegani zendegani commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Batch-export UX improvements (v2.4.0), building on the merged Fast Batch (#70). Standard batch behavior is unchanged unless noted.

Fast Batch: more sources

  • Profile and Likes now work in Fast, not just Bookmarks — same ~10× path. The timeline parser was generalized (robust source-agnostic timeline finder + module/self-thread cells). Profile skips reposts by default (detected structurally via retweeted_status_result, since a retweet's top-level author is the retweeter).
  • Selection stays Standard-only — its tab is disabled while Fast is armed (Fast has no feed to paginate).

New sources & controls

  • Timeline tab (Standard) — a 5th batch source exporting the posts loaded in your home feed (x.com/home), through the same worker-tab extractor as Bookmarks/Profile/Likes. Standard-only; the tab is disabled while Fast is armed (the home feed is HomeTimeline/HomeLatestTimelinePOST with cursor in the body, which Fast's GET-with-URL pagination engine doesn't support; deferred).
  • Open page from the tab — when you're not on the right page, the Bookmarks and Timeline tabs show an Open Bookmarks / Open Timeline button that navigates the active x.com tab there (or opens a new tab) instead of a disabled dead-end. Standard still reads the loaded DOM, so you scroll then export. Profile/Likes keep the hint (per-account, no canonical URL without a handle).
  • Date-range filter (Fast) — From/To bounds on the tweet date. Out-of-range posts are skipped before the per-item TweetDetail expansion, so X's ~150/15-min TweetDetail quota is spent only on in-range posts → reach older targets without soft-blocking. (Filters by tweet date; bumps feed page depth since Bookmarks/Likes are ordered by save date.)
  • Reset queue — empties the gathered collection and restarts from the current scroll position, so you can begin a batch at a specific post. (Standard sources; injector XCLIPPER_HARVEST_RESET.)
  • Reset history — renamed from the unclear "Reset dedup".
  • Include reposts toggle — default off (own posts only); honored by both Standard (injector harvest filter) and Fast.
  • Step status lights (Fast) — Page → Tweet → Fetch → Expand. Page/Tweet are red/green readiness lights (reload page / open one tweet) so you know what to do before Export; Fetch/Expand light up the live phase.

Layout & styling

  • Batch Output selector moved above Format.
  • Fast Batch bar flattened: red text (not a red fill), neutral (i) + BETA, and a plain red toggle — less wall-of-red while keeping Fast clearly marked.

Running-job display + reliability fixes

  • A running job's progress now stays visible on every tab/page and is labeled with who/which is running (@handle · 2/6), Standard and Fast.
  • Fast progress survives popup reopen (re-attaches to the background run; was lost because the popup is a fresh page each open).
  • Fast reads the profile handle from the URL, not the injector — so it shows the name and filters reposts even when the page wasn't reloaded after an extension update.
  • Fast captured auth + request templates persist to chrome.storage.session so they survive MV3 service-worker teardown between runs.
  • Reset buttons grey out instead of hiding (stable layout); greyed via color, not opacity, so their tooltips stay readable (issue Tooltip on disabled options is half-transparent and unreadable #38).
  • After an extension reload: URL-based tab focus + clickable "Reload the page" hint (a disabled button can't show its tooltip in Chrome); plain combined Fast precondition hint.
  • Cancel writes only the items actually processed ("stop at 5" → ~5 files); the Fast lock hint shows only on a toggle attempt, not during any export.

Notes

  • Version bumped 2.3.0 → 2.4.0; CHANGELOG updated.
  • New pure logic (timeline finder/module parse, date filter, repost detection) is unit-tested — 194 tests pass; tsc --noEmit + build green.
  • Profile/Likes GraphQL response shapes are schema-modeled (Bookmarks was validated against a real capture); the parser is defensive and was exercised live, but worth a reviewer's eye.

🤖 Generated with Claude Code

zendegani and others added 22 commits June 14, 2026 16:49
Reset queue empties the injector's gathered collection and re-seeds from the
current viewport, so you can scroll to a specific post and start collecting
from there instead of always top-to-bottom (XCLIPPER_HARVEST_RESET → the
injector clears `harvested` then re-harvests the viewport). The control row
now carries two independent buttons: Reset queue (shown when a collection
exists) and Reset history (the dedup ledger, clearer name than "dedup").
Standard batch only — Fast paginates from the top and shows just history.

First of several batch-UX improvements on this branch (date range + step
status lights to follow).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Date the shipped 2.3.0 entry, start a fresh Unreleased section for 2.4.0,
and bump the working version to 2.4.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The control row no longer appears/disappears as a collection grows or a run
finishes — it stays put and the Reset queue / Reset history buttons just grey
out when not applicable, so the popup doesn't change size/layout. Fast mode
shows both with Reset queue always greyed (it paginates from the top).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
opacity on the button cascaded into its [data-tooltip]::after, making the
disabled-button hint half-transparent (issue #38 again). Dim via color/border
instead — the tooltip sets its own color and stays fully legible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…n in Fast

Generalize the Fast engine beyond Bookmarks:
- timeline.ts: robust findTimeline (known keys + generic instructions search)
  and parseTimelinePage now also pulls tweets from TimelineTimelineModule
  items (profile/likes self-thread cells). Unit-tested.
- runFastBatchExport takes a source (bookmarks|profile|likes); picks the
  captured op template per source (Bookmarks/UserTweets/Likes), with one
  combined up-front precondition hint. Profile skips reposts (author ≠ handle),
  matching Standard.
- Popup: Fast routes bookmarks/profile/likes; Selection tab is disabled while
  Fast is armed (and bounces off it), with a reason tooltip. Per-source labels
  + hints. Tab dims via color, not opacity (issue #38).

Reposts include/skip toggle (both modes) is the planned follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…y export

The "An export is running…" hint was appearing whenever a Standard job ran,
even though the user wasn't trying to switch modes. Now the toggle still locks
during a run, but the reason only appears when the user actually clicks the
locked toggle; it clears when the run ends or on switching to Single.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…h who

Progress was gated to the tab the job started from, so navigating to another
profile (or any other page) hid the in-progress bar/handle. Now a running
job's progress shows on every tab while active, and the status line is
prefixed with the job's source/handle (e.g. "@user1 · 2/6", "Bookmarks · …")
so you can see which export is running even when viewing something else.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… reopen

Fast progress didn't survive a popup reopen (popup is a fresh page; fastActive
reset and nothing re-checked the background), so after navigating the bar
vanished, the button looked enabled, and re-clicking hit "already in progress".
Now:
- FastBatchProgress carries source + handle; the progress line is prefixed with
  who/which (e.g. "@vonCodeburg · Expanding 5/200").
- resumeFastIfActive() polls FAST_BATCH_STATUS on popup open; if a run is in
  progress it re-attaches the poller, locks the toggle, and lands on Batch — so
  the running export stays visible and the Export button is correctly disabled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fast doesn't need the page/injector (it replays captured GraphQL), so after an
extension reload without a page refresh it still exported a profile — but the
popup read the handle from the dead injector, so the button showed no name and
no reposts filter was applied (handle was undefined → reposts could slip in).
Derive the profile handle from the page URL instead: the button now shows
@handle and the reposts filter works, with no reload needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…imits

Optional From/To dates (Fast only). Out-of-range posts are skipped during
collection BEFORE the per-item TweetDetail expansion, so the ~150/15min
TweetDetail budget is spent only on in-range posts — you can reach older
targets without soft-blocking. Filters by tweet date; bumps feed page depth
when a range is set (bookmarks/likes are ordered by save date, not tweet
date). Dates persist; swap if entered backwards. Shown only while Fast is
armed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fast profile was exporting retweets: a retweet's top-level author IS the
profile owner (retweeter), so the author≠handle check never caught it. Detect
reposts structurally via legacy.retweeted_status_result.

Add an "Include reposts (profiles)" setting (default off) honored by BOTH
modes — Fast skips reposts unless on; the injector's Standard harvest filter
is now gated by it too. Persisted via shared settings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A compact stepper shown when Fast is armed. Idle: Page/Tweet are readiness
lights (green = the feed/TweetDetail request was captured; red + tooltip =
reload the page / open one tweet) so you know what to do before clicking
Export. During a run: Fetch/Expand light up by phase. Driven by a new
FAST_BATCH_READY query + the existing status poll.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…/toggle

- Date range now sits directly above the Export button; step lights directly
  below it (inside the batch source box).
- Include-reposts moved out of the Export-settings carrot to below the Output
  selector — so it's batch-only and hidden in Single export.
- "Save images locally (only with .md)".
- Fast toggle when on: solid red track + white knob (was a translucent red on
  the red-tinted bar → nearly invisible).
- Refresh the Fast Batch (i) tooltip (was "bookmarks only"; now covers
  bookmarks/profile/likes, step lights, date range, rate-limit behavior).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A failed precondition (status 'error') still rendered the progress bar filled
to 100%, looking like a finished run while the message said to reload. Hide the
bar row on error and show only the hint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ep lights

- Shrink the Export button into a row with the two Reset buttons stacked
  beside it (Reset queue / Reset history), always shown (greyed when N/A).
- Step lights span the full width (space-between) with action/phase labels:
  Reload x.com | Open one tweet | Fetching ... | Expanding ...
- Trim heights: Fast Batch bar + icon tabs (~10%), Export settings header.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…carrot

Less crowded default Batch view: Format, Output and Include-reposts now live
inside the collapsible (collapsed by default in Batch, still hidden in Single),
so they're tucked away until you expand settings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Move Include-reposts above Format in the settings carrot.
- Dial back the Fast red: only the Fast bar, the active source tab, and the
  step lights are red now — the Export button, progress bar, and reset buttons
  stay the normal blue.
- Export button is text-only: drop the leading source icon (both modes) and the
  ⚡ from Fast labels.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…, full-width Export

Fast Batch bar now sits below the icon tabs in a flex row with the stacked
Reset queue / Reset history buttons beside it; the Export button returns to
full width (removed the old .batch-action-row wrapper and its duplicate
reset stack).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ed toggle

Drop the red-tinted bar background (now neutral elevated bg + subtle border);
the red signal moves to the "Fast Batch" label (both states). The (i) icon and
BETA badge stay neutral. The checked toggle becomes a plain red switch
(translucent track + solid red knob) like the other toggles — the heavy
solid-track/white-knob treatment only existed to stay visible on the old red bg.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New Timeline tab harvests x.com/home permalinks through the same worker-tab
extractor as Bookmarks/Profile/Likes. Standard-only — the tab is disabled
while Fast is armed (the home feed is POST-paginated, unlike Fast's GET feeds).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…on it

Instead of a disabled button + "go here" hint, the Bookmarks and Timeline tabs
now show an "Open Bookmarks"/"Open Timeline" action that navigates the active
x.com tab there (or opens a new tab). Standard still reads the loaded DOM, so
the user scrolls then exports. Profile/Likes keep the hint — they're per-account
and have no canonical URL to open without a handle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@zendegani zendegani marked this pull request as ready for review June 14, 2026 19:41
@zendegani zendegani merged commit 6e6a79e into main Jun 14, 2026
4 checks passed
@zendegani zendegani deleted the feat/batch-ux branch June 14, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant