Enable button moved from /image-host to /settings/ihost, so e2e
tests now navigate to settings to enable the feature first.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
better-auth defers `user.create.after` hooks until after the transaction
commits, but the session cookie cache is written inside the transaction.
This caused `activeOrganizationId` to be null on first load after sign-up,
breaking features that depend on an active organization (e.g. Image Host).
Solution: create the personal org in `session.create.before` (which runs
inside the transaction, after user INSERT) and set `activeOrganizationId`
on the session before it's cached. Also keep idempotent org creation in
`user.create.after` so orgs are created even without auto sign-in (e.g.
when email verification is required).
Additionally fix an ambiguous Playwright locator in image-host.spec.ts
that matched multiple elements.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: v2.4.0 T7 — Image Host gallery page with FileManager reuse
- Add ImageHostView component that wires FileManager with image-host-specific
config: upload via /api/ihost/images presigned flow, delete with 5s undo toast,
copy URL in raw/Markdown/HTML/BBCode formats, and thumbnail rendering
- Extend FileManager with new capabilities (copyUrl, delete), getThumbnailUrl
prop, onDeleteItems/onCopyUrl callbacks, and viewModeStorageKey for isolated
view-mode persistence per page
- Extend FilesGrid with optional getThumbnailUrl prop: renders lazy-loaded image
thumbnails with FileIcon fallback on error; backward-compatible with Files page
- Extend FileRowActions with Copy URL submenu (raw/Markdown/HTML/BBCode) and a
Delete action separate from Move to Trash; fully backward-compatible
- Extend UploadDropzone with optional uploadFn prop to bypass the default
object-upload flow; Files page behavior unchanged
- Parameterize useViewMode hook with optional storageKey argument
- Add API wrappers: listIhostImages, createIhostImagePresign, confirmIhostImage,
deleteIhostImage with matching tests in api.test.ts
- Add useClipboard hook; refactor navigator.clipboard.writeText usage in
share-dialog.tsx and shares/index.tsx to use the hook
- Add IhostRoute to rpc.ts
- Add ihost.copy.*, ihost.delete.*, ihost.upload.*, ihost.table.* i18n keys
to en.json and zh.json; add common.copied key
Agent-Profile: https://agent-kanban.dev/agents/b724a773425e397c
* fix: use Hono RPC client for ihost API, add presign endpoint, expand test coverage
- Rewrite server/routes/ihost.ts to use method chaining, fixing Hono RPC type
inference (imperative app.post() calls prevented the schema from being typed)
- Extract POST /images/presign as a dedicated typed endpoint (zValidator) for the
browser client; POST /images becomes multipart-only for API-key/PicGo compat
- Frontend: replace raw ihostFetch() with ihostApi RPC calls for all four
wrappers (listIhostImages, createIhostImagePresign, confirmIhostImage,
deleteIhostImage); mime parameter typed as AllowedImageMime
- Update integration tests to use /images/presign for JSON presign cases; adjust
status expectations to 400 (Zod) vs 413/415 (manual checks no longer needed)
- Add unit tests: use-clipboard, image-host-data-source, image-host-view,
file-row-actions, upload-dropzone, use-view-mode custom-key
- Add e2e/image-host.spec.ts: enable feature gate, upload (mocked S3 PUT),
grid→table view switching, copy Markdown URL, delete with Undo, delete permanently
Agent-Profile: https://agent-kanban.dev/agents/b724a773425e397c
* test: improve patch coverage for ihost routes and file-row-actions
Add missing 503/401 integration tests for multipart endpoint and API key
error paths. Extract testable pure functions from file-row-actions.tsx and
image-host-view.tsx and update tests to import from source files.
Agent-Profile: https://agent-kanban.dev/agents/b724a773425e397c
* test: fix coverage cascade, add component rendering tests and branch tests
Revert buildCopyText export which caused file-manager/files-grid/upload-dropzone
to appear in coverage at 0% via transitive imports. Restore inline switch logic
in handleCopyUrl and define buildCopyText locally in the test.
Install @testing-library/react + jsdom, add React plugin to vitest unit project,
and write FileRowActions rendering tests (file-row-actions.render.test.tsx) to
cover JSX branches including Copy URL sub-menu and delete item.
Add missing DELETE 403 (no config) and storage-null branch tests to
ihost.integration.test.ts to cover uncovered branches in ihost.ts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: update ihost.cf-test.ts for multipart-only POST /images endpoint
POST /api/ihost/images now returns 415 for JSON (multipart only).
Add separate test for POST /api/ihost/images/presign returning 403
when image hosting is not enabled.
Agent-Profile: https://agent-kanban.dev/agents/b724a773425e397c
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace verb-based URLs with proper HTTP methods and resource nouns:
- Objects: merge PATCH /:id/done, /trash, /restore into PATCH /:id
with discriminated union (action: update|confirm|trash|restore)
- Objects: POST /:id/copy → POST /copy with copyFrom in body
- Objects: POST /batch/move, /batch/trash → PATCH /batch;
POST /batch/delete → DELETE /batch
- Notifications: POST /:id/read → PATCH /:id,
POST /read-all → PATCH /, GET /unread-count → GET /stats
- Users: PUT /:id/status → PATCH /:id
- Teams: POST /join → POST /:teamId/members
- Email-config: POST /test → POST /test-messages
- Invite-codes: POST /validate → POST /validations
- Fix path hierarchy: move admin auth-providers from
/api/auth-providers/admin/* to /api/admin/auth-providers/*
- Rename recycle-bin to trash across API, frontend, and e2e tests
- Update all integration tests, CF tests, unit tests, and schemas
BREAKING CHANGE: all listed API endpoints have changed paths or methods
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Duplicate folder/file names silently created duplicates under the same
parent. Add DB-level partial unique index on (org_id, parent, LOWER(name))
for active rows, plus a centralized plan/commit helper threaded through
create, rename, move, copy, upload-confirm, and restore. 409 responses
open a Keep Both / Replace / Cancel dialog with sticky "apply to all"
for batch operations; case-insensitive match matches OS conventions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: remove Name field from registration form
- Remove name from signUpSchema; send empty string to satisfy DB NOT NULL
- Reorder sign-up form: Email → Username → Password → Invite Code
- createPersonalOrg falls back to username when name is empty
- Add username to UserWithOrg type (server and frontend), typed as string
- Sidebar and admin users table show username when name is empty
- Update all e2e helpers and specs to remove Name field interactions
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
* fix: update signUpSchema tests to match new schema (email, username, password)
Remove name field tests; add username validation tests.
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
---------
Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
* feat(auth): overhaul sign-in/sign-up UI with username login, OAuth buttons, and invite codes
- Sign-in: accept email or username (auto-detected via regex), show OAuth provider buttons
- Sign-up: add username field, conditional invite code field (invite_only mode), closed mode message
- New shared OAuthButtons component fetching enabled providers via Hono RPC
- Extend useSiteOptions hook with authSignupMode
- Add AuthProvider type to shared/types, listAuthProviders API via Hono RPC client
- Add i18n keys for new UI elements (en + zh)
- Hide sign-up link on sign-in page when registration is closed
- Add try/finally to form submissions to prevent stuck loading state
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
* fix(e2e): update E2E tests for new sign-in/sign-up form fields
- Sign-up: fill new Username field, use exact match for Name label
- Sign-in: update label selector from "Email" to "Email or Username"
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
* fix(e2e): update responsive-auth test for new form field labels
The /name/i regex matched both "Username" and "Name" fields, causing
strict mode violations. Use exact label matchers instead.
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
---------
Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
- Replace globalSetup function with a setup project that runs after
webServer starts, fixing the timing issue where seed API calls
failed because the server wasn't ready yet
- Admin tests sign in with known credentials (fallback chain for
CI vs local dev) instead of registering new users that may not
get admin role
- Remove storage column tests that required seeded data — the
overflow test covers the same responsive behavior
- Remove settings form test that couldn't navigate via page.goto
due to SPA session loss
Result: 51 tests, 51 passed, 0 skipped, 0 failed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use @desktop/@tablet/@mobile/@all tags in test titles and project-level
grep patterns instead of runtime test.skip(). This eliminates ~90
spurious skipped tests — each project now only loads tests tagged for
its device.
Before: 144 total (43 pass, 101 skip)
After: 55 total (43 pass, 12 skip — admin-only skips)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use Playwright page.route() to mock the file list API, getObject API,
and S3 download URLs. This allows testing text, markdown, and code
preview rendering without a real S3 backend. Verifies:
- Mobile: preview opens as full-screen drawer with content rendered
- Desktop: preview opens as centered dialog with content rendered
- File header shows name and size correctly
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
better-auth rejects requests without an Origin header (403).
Add Origin: baseURL to sign-up, sign-in, and storage seed requests
in the global setup script.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add e2e/global-setup.ts that registers the first user (admin) and
creates a storage backend via API before any tests run. This replaces
the per-test seedStorage calls that failed when the test user wasn't
admin. All folder-dependent tests now work reliably in CI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests that create folders need a storage record in the database.
Instead of silently skipping when storage is missing, seed a dummy
storage backend via the admin API before folder creation. This
ensures tests actually run and fail loudly if something is wrong.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract shared signUpAndGoToFiles and createFolder helpers into
e2e/helpers.ts. createFolder listens for the API response and skips
the test if the server returns an error (e.g. no S3 storage configured
in CI). This prevents folder-dependent tests from timing out.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use --env-file=.dev.vars only locally (CI injects env vars directly)
- Increase dialog close timeouts from 5s to 10s for CF Workers runtime
- Replace fragile class-based action button selectors with row-scoped
role queries
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the centered Dialog with a bottom Sheet (Drawer) on mobile
for file previews. Audio gets a half-height drawer so the file list
stays visible; video uses auto-height; PDF/text/code go full-screen
for immersive reading. Images keep the existing lightbox on all
devices. Desktop behavior is unchanged.
Also fixes useIsMobile to initialize synchronously from window.innerWidth,
preventing a flash of desktop layout on mobile first render.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Toolbar buttons collapse to icon-only on mobile with sr-only text.
Table columns (size, modified, email, quota, etc.) progressively hide
at sm/md/lg breakpoints. Admin and trash pages get matching treatment.
Playwright config gains tablet (768×1024) and mobile (390×844) projects
with 38 E2E tests covering overflow, column visibility, and sidebar
behavior across all three viewports.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Separate admin backend from main frontend sidebar:
- Remove admin nav items from main sidebar
- Add user profile dropdown with "Admin Panel" entry (admin only)
- Create admin layout at /admin with role guard and separate sidebar
- Implement storage management page with CRUD table and form dialog
- Add delete confirmation dialog following existing patterns
- Add en/zh translations for all admin storage keys
- Update E2E tests to verify sidebar separation
Agent-Profile: https://agent-kanban.dev/agents/b724a773425e397c
The 'shows sidebar after login' and 'navigate all placeholder pages'
tests were tied to the original v1 sidebar layout (with admin items)
and the placeholder page text. They block every legitimate frontend
PR that replaces placeholder content or moves admin items to a
separate layout per the frontend/backend separation design.
Real E2E coverage will be added by individual feature PRs going
forward (file manager, trash, admin pages, etc.).