feat(app): unify composer attachments with pill + lightbox redesign

Images and GitHub issues/PRs now live in one draft-store list (ComposerAttachment union) with cwd persisted on the draft. Paperclip becomes a + drop-up menu; queue button removed. Each pill uses a shared AttachmentPill wrapper with a corner-X that mirrors the auto-update toast spec. Pill body opens the attachment: GitHub via openExternalUrl, images via a new fullscreen AttachmentLightbox. GitHub picker auto-closes on select.
This commit is contained in:
Mohamed Boudra
2026-04-17 11:36:08 +07:00
parent 11524dc349
commit 3838a8b969
25 changed files with 2994 additions and 735 deletions
@@ -3,8 +3,8 @@ import { describe, expect, it } from "vitest";
import { __draftStoreTestUtils } from "./draft-store";
describe("draft-store migration", () => {
it("normalizes attachment metadata and strips persisted preview URLs", () => {
const migrated = __draftStoreTestUtils.migratePersistedState({
it("normalizes legacy image metadata into image attachments and strips persisted preview URLs", async () => {
const migrated = await __draftStoreTestUtils.migratePersistedState({
drafts: {
"agent:server:agent": {
input: {
@@ -28,32 +28,43 @@ describe("draft-store migration", () => {
createModalDraft: null,
});
expect(migrated.drafts["agent:server:agent"]?.input.images).toEqual([
{
id: "att-1",
mimeType: "image/png",
storageType: "desktop-file",
storageKey: "/tmp/att-1.png",
createdAt: 1700000000000,
},
]);
expect(migrated.drafts["agent:server:agent"]?.input).toEqual({
text: "hello",
attachments: [
{
kind: "image",
metadata: {
id: "att-1",
mimeType: "image/png",
storageType: "desktop-file",
storageKey: "/tmp/att-1.png",
createdAt: 1700000000000,
},
},
],
cwd: "",
});
});
it("is idempotent for already-migrated shapes", () => {
it("is idempotent for already-migrated shapes", async () => {
const original = {
drafts: {
"agent:server:agent": {
input: {
text: "hello",
images: [
attachments: [
{
id: "att-1",
mimeType: "image/jpeg",
storageType: "web-indexeddb",
storageKey: "att-1",
createdAt: 1700000000000,
kind: "image",
metadata: {
id: "att-1",
mimeType: "image/jpeg",
storageType: "web-indexeddb",
storageKey: "att-1",
createdAt: 1700000000000,
},
},
],
cwd: "/repo",
},
lifecycle: "active",
updatedAt: 1700000000001,
@@ -63,8 +74,8 @@ describe("draft-store migration", () => {
createModalDraft: null,
};
const once = __draftStoreTestUtils.migratePersistedState(original);
const twice = __draftStoreTestUtils.migratePersistedState(once);
const once = await __draftStoreTestUtils.migratePersistedState(original);
const twice = await __draftStoreTestUtils.migratePersistedState(once);
expect(twice).toEqual(once);
});