Remove the horizontal flex wrapper so quota badges stack vertically
like all other capacity badges in the column.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Display daily/weekly/total quota utilization as progress bars in the
usage window column for API Key accounts, providing visual feedback
consistent with other account types (OAuth/Gemini).
- Daily quota: "1d" label with reset countdown
- Weekly quota: "7d" label with reset countdown
- Total quota: "total" label (no reset)
Move daily/weekly/total quota progress bars for API Key accounts from
the capacity column (QuotaBadge) to the usage window column
(UsageProgressBar), providing a consistent visual experience with
other usage displays.
- Backend: detect and classify 403 responses (validation/violation/forbidden)
- Backend: extract verification/appeal URLs from 403 response body
- Frontend: display forbidden status badges with color coding
- Frontend: show clickable/copyable verification links
- Also includes: sora SDK client rename, table header style fix, tier badge in accounts list
chore: bump version to 0.1.93.23
- Increase Select dropdown max-width from 320px to 480px for better content display
- Change KeysView group selector from fixed 256px to adaptive 280-480px width
- Make group switch icon always visible (60% opacity, 100% on hover)
- Allow group description to wrap to 2 lines instead of truncating
- Improve user experience for group selection in API keys page
Scrollbar:
- Override scrollbar-width to 'auto' (was 'thin' ~6px, nearly invisible)
- Increase scrollbar-color opacity to 0.7 (was 0.5)
- Add explicit ::-webkit-scrollbar width 10px for older Chrome
Text selection:
- Block selectstart in Phase 1 (onMouseDown) instead of Phase 2
- Clear existing text selection with removeAllRanges() on drag start
Stability:
- Add window blur handler to cleanup drag on tab switch / window leave
- Guard onWheel RAF callback against stale drag state
- Defensive removeMarquee() before createMarquee()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The global CSS makes all scrollbars transparent by default (only visible
on hover). For table containers, scrollbars should always be visible so
users know the content is scrollable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Binary search in findRowIndexAtY (O(n) → O(log n))
- Short-circuit applyRange when row index unchanged
- Cache scrollParent in beginDrag instead of per-frame lookup
- Skip autoScroll recomputation when scrollTop unchanged
- Detect scrollbar clicks on inner containers, not just document
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace document.body.style.userSelect manipulation with selectstart
event listener to prevent text selection (no body style mutation)
- Skip mousedown on scrollbar area (clientX >= documentElement.clientWidth)
- Extract cleanupDrag() for robust state cleanup in all code paths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Allow starting drag from anywhere on the page (not just inside tbody)
- Use 5px drag threshold to prevent accidental selection on click
- Support mouse wheel scrolling during drag to select new rows
- Auto-scroll when dragging near viewport edges with row re-detection
- Find closest row by viewport Y coordinate instead of requiring exact hit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove selectedRowIds/isRowSelected/row-selected CSS from DataTable.
Add semi-transparent marquee rectangle overlay during drag selection,
with dark mode theme support using primary colors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show a semi-transparent blue rectangle overlay while dragging to
select rows, matching the project's primary color theme with dark
mode support. The box spans the full table width from drag start
to current mouse position.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add selectedRowIds prop to DataTable. Selected rows get a blue tint
background (primary-50), including sticky columns. Integrated into
AccountsView and ProxiesView for visual feedback during swipe select.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add useSwipeSelect composable that enables drag-to-select rows in
DataTable. Mousedown on a row and drag up/down to select/deselect
a contiguous range. Integrated into AccountsView and ProxiesView.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
P0 fixes:
- StorageType: UploadFromURL now returns actual storageType, fixing
GDrive tasks being incorrectly recorded as "s3"
- Concurrency: selectAccount returns ReleaseFunc to caller, fixing
premature slot release before task creation
- Race condition: applyRecoveredToken uses copy-on-write for
account.Credentials map to prevent concurrent write panic
- GetCameoStatus: use direct HTTP call to populate missing fields
(StatusMessage, InstructionSetHint, InstructionSet)
- Frontend: progress bar uses reactive now.value instead of
non-reactive Date.now()
P1 fixes:
- EditImage: pass req.Image through to CreateImageRequest
- ListPending: add LIMIT 200 to prevent unbounded queries
- Worker encapsulation: add ListPendingTasks/UpdateTask proxy methods
to SoraTaskService, worker no longer accesses repo directly
- Frontend polling: add retry counter (3 attempts) before giving up
P2-P3 fixes:
- QuotaBar: handle both quota_source and source field names
- i18n: replace hardcoded Chinese labels in SoraPromptBar and
example prompts in SoraGeneratePage with i18n keys
- Fix regenrate → regenerate i18n typo
- SoraMediaPreview: skip Escape handler when not visible
- SoraGeneratePage: void handleGenerate promise in handleRetry
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- QuotaLimitCard: label and input on same row for reduced height
- CreateAccountModal: move AffinityConfigCard into OAuth/SetupToken
quota control section, eliminating duplicate "配额控制" cards
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge the separate "配额限制" and "配额控制" sections into one unified
"配额控制" section per account type. For Anthropic OAuth/SetupToken
accounts, AffinityConfigCard is now inside the quota control section
instead of a separate card.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extend the existing total quota limit with daily and weekly periodic
dimensions. Each dimension is independently configurable and uses lazy
reset — when the period expires, usage is automatically reset to zero on
the next increment. Any dimension exceeding its limit will pause the
account from scheduling.
Backend:
- Add GetQuotaDailyLimit/Used, GetQuotaWeeklyLimit/Used, HasAnyQuotaLimit
- Rewrite IncrementQuotaUsed with atomic CTE SQL for 3-dimension update
- Rewrite ResetQuotaUsed to clear all dimensions and period timestamps
- Update postUsageBilling to use HasAnyQuotaLimit()
- Preserve daily/weekly used values on account edit
Frontend:
- Refactor QuotaLimitCard from single v-model to 3-dimension props
- Add QuotaBadge component for compact D/W/$ display
- Update AccountCapacityCell with per-dimension badges
- Update Create/Edit modals with daily/weekly quota fields
- Update AccountActionMenu hasQuotaLimit to check all dimensions
- Add i18n strings for daily/weekly/total quota labels
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move both cards under a unified "配额限制" section wrapper for Anthropic
platform. Remove independent section wrappers from both components so
they render as plain rounded cards. Non-Anthropic apikey accounts get
their own quota section with just QuotaLimitCard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AffinityConfigCard redesigned to match QuotaLimitCard style (section title + toggle card)
- Moved from standalone section to quota area, visible for all Anthropic account types
- Green zone (base) allows empty = no limit, min=1 when set; yellow zone hidden when base unset
- Deduplicated affinity save logic in EditAccountModal (single block for all Anthropic types)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>