From 443afab7bd57a0cdd0fac739a9f84109204c13fd Mon Sep 17 00:00:00 2001 From: HouYunFei <1844025705@qq.com> Date: Fri, 26 Jun 2026 17:24:48 +0800 Subject: [PATCH] refactor: remove "use client" directive from multiple files and update project structure to align with Vite and React Router --- AGENTS.md | 7 +- docs/content/docs/progress/pending-test.mdx | 2 +- web/src/app/(user)/canvas/[id]/page.tsx | 5 -- web/src/app/favicon.ico | Bin 38078 -> 0 bytes web/src/components/audio-settings-panel.tsx | 2 - .../canvas}/asset-picker-modal.tsx | 2 - .../canvas}/canvas-agent-chat-ui.tsx | 2 - .../canvas}/canvas-assistant-panel.tsx | 10 ++- .../canvas}/canvas-audio-settings-popover.tsx | 2 - .../canvas}/canvas-config-composer.tsx | 2 - .../canvas}/canvas-config-node-panel.tsx | 4 +- .../canvas}/canvas-connections.tsx | 2 +- .../canvas}/canvas-context-menu.tsx | 4 +- .../canvas}/canvas-delete-projects-dialog.tsx | 6 +- .../canvas}/canvas-image-settings-popover.tsx | 2 - .../canvas-image-toolbar-settings-modal.tsx | 2 - .../canvas}/canvas-image-toolbar-tools.tsx | 4 +- .../canvas}/canvas-local-agent-panel.tsx | 6 +- .../canvas}/canvas-mini-map.tsx | 4 +- .../canvas}/canvas-node-angle-dialog.tsx | 2 - .../canvas}/canvas-node-crop-dialog.tsx | 2 - .../canvas}/canvas-node-generation.ts | 4 +- .../canvas}/canvas-node-hover-toolbar.tsx | 4 +- .../canvas}/canvas-node-mask-edit-dialog.tsx | 2 - .../canvas}/canvas-node-prompt-panel.tsx | 6 +- .../canvas}/canvas-node-split-dialog.tsx | 4 +- .../canvas}/canvas-node-upscale-dialog.tsx | 4 +- .../canvas}/canvas-node.tsx | 6 +- .../canvas}/canvas-project-card.tsx | 8 +-- .../canvas}/canvas-prompt-library.tsx | 2 - .../canvas-resource-mention-textarea.tsx | 4 +- .../canvas}/canvas-size-picker.tsx | 2 - .../canvas}/canvas-toolbar.tsx | 0 .../canvas}/canvas-video-settings-popover.tsx | 2 - .../canvas}/canvas-zoom-controls.tsx | 0 .../canvas}/infinite-canvas.tsx | 4 +- .../components/image-generation-pending.tsx | 2 - web/src/components/image-settings-panel.tsx | 2 - .../components/layout/app-config-modal.tsx | 2 - web/src/components/layout/app-providers.tsx | 2 - web/src/components/layout/app-top-nav.tsx | 2 - .../components/layout/client-root-init.tsx | 2 - web/src/components/layout/github-link.tsx | 2 - .../components/layout/mobile-nav-drawer.tsx | 2 - .../components/layout/user-status-actions.tsx | 2 - .../layout/version-release-modal.tsx | 2 - web/src/components/model-picker.tsx | 2 - web/src/components/prompts/prompt-card.tsx | 2 - .../prompts/prompt-select-dialog.tsx | 2 - web/src/components/prompts/use-prompt-list.ts | 2 - .../components/ui/animated-theme-toggler.tsx | 2 - web/src/components/ui/dia-text-reveal.tsx | 2 - web/src/components/ui/select.tsx | 2 - web/src/components/video-settings-panel.tsx | 2 - .../constants.ts => constant/canvas.ts} | 4 +- web/src/hooks/use-copy-text.ts | 2 - .../layout.tsx => layouts/user-layout.tsx} | 2 - .../utils => lib/canvas}/canvas-agent-ops.ts | 4 +- .../utils => lib/canvas}/canvas-export.ts | 4 +- .../utils => lib/canvas}/canvas-image-data.ts | 2 - .../utils => lib/canvas}/canvas-node-size.ts | 2 - .../canvas}/canvas-resource-references.ts | 2 +- web/src/main.tsx | 2 +- .../(user) => pages}/assets/asset-transfer.ts | 0 .../page.tsx => pages/assets/index.tsx} | 2 - .../page.tsx => pages/canvas/index.tsx} | 14 ++-- .../canvas/project.tsx} | 60 +++++++++--------- .../(user)/page.tsx => pages/home/index.tsx} | 2 - .../image/page.tsx => pages/image/index.tsx} | 4 +- .../not-found/index.tsx} | 0 .../components}/prompt-detail-dialog.tsx | 2 - .../page.tsx => pages/prompts/index.tsx} | 4 +- .../video/page.tsx => pages/video/index.tsx} | 4 +- web/src/router.tsx | 20 +++--- web/src/services/api/prompts.ts | 2 - web/src/services/app-sync.ts | 6 +- web/src/services/file-storage.ts | 2 - web/src/services/image-storage.ts | 2 - web/src/services/webdav-sync.ts | 2 - .../canvas}/use-canvas-agent-store.ts | 2 +- .../canvas}/use-canvas-store.ts | 2 +- .../canvas}/use-canvas-ui-store.ts | 0 web/src/stores/use-asset-store.ts | 4 +- web/src/stores/use-config-store.ts | 2 - web/src/stores/use-user-store.ts | 2 - web/src/{app => styles}/globals.css | 0 .../canvas-export.ts} | 2 +- .../canvas/types.ts => types/canvas.ts} | 0 88 files changed, 94 insertions(+), 230 deletions(-) delete mode 100644 web/src/app/(user)/canvas/[id]/page.tsx delete mode 100644 web/src/app/favicon.ico rename web/src/{app/(user)/canvas/components => components/canvas}/asset-picker-modal.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-agent-chat-ui.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-assistant-panel.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-audio-settings-popover.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-config-composer.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-config-node-panel.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-connections.tsx (98%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-context-menu.tsx (96%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-delete-projects-dialog.tsx (90%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-image-settings-popover.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-image-toolbar-settings-modal.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-image-toolbar-tools.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-local-agent-panel.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-mini-map.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-node-angle-dialog.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-node-crop-dialog.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-node-generation.ts (98%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-node-hover-toolbar.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-node-mask-edit-dialog.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-node-prompt-panel.tsx (98%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-node-split-dialog.tsx (98%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-node-upscale-dialog.tsx (98%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-node.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-project-card.tsx (95%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-prompt-library.tsx (98%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-resource-mention-textarea.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-size-picker.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-toolbar.tsx (100%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-video-settings-popover.tsx (99%) rename web/src/{app/(user)/canvas/components => components/canvas}/canvas-zoom-controls.tsx (100%) rename web/src/{app/(user)/canvas/components => components/canvas}/infinite-canvas.tsx (99%) rename web/src/{app/(user)/canvas/constants.ts => constant/canvas.ts} (93%) rename web/src/{app/(user)/layout.tsx => layouts/user-layout.tsx} (96%) rename web/src/{app/(user)/canvas/utils => lib/canvas}/canvas-agent-ops.ts (97%) rename web/src/{app/(user)/canvas/utils => lib/canvas}/canvas-export.ts (94%) rename web/src/{app/(user)/canvas/utils => lib/canvas}/canvas-image-data.ts (99%) rename web/src/{app/(user)/canvas/utils => lib/canvas}/canvas-node-size.ts (98%) rename web/src/{app/(user)/canvas/utils => lib/canvas}/canvas-resource-references.ts (99%) rename web/src/{app/(user) => pages}/assets/asset-transfer.ts (100%) rename web/src/{app/(user)/assets/page.tsx => pages/assets/index.tsx} (99%) rename web/src/{app/(user)/canvas/page.tsx => pages/canvas/index.tsx} (93%) rename web/src/{app/(user)/canvas/[id]/canvas-client-page.tsx => pages/canvas/project.tsx} (98%) rename web/src/{app/(user)/page.tsx => pages/home/index.tsx} (99%) rename web/src/{app/(user)/image/page.tsx => pages/image/index.tsx} (99%) rename web/src/{app/not-found.tsx => pages/not-found/index.tsx} (100%) rename web/src/{components/prompts => pages/prompts/components}/prompt-detail-dialog.tsx (99%) rename web/src/{app/(user)/prompts/page.tsx => pages/prompts/index.tsx} (98%) rename web/src/{app/(user)/video/page.tsx => pages/video/index.tsx} (99%) rename web/src/{app/(user)/canvas/stores => stores/canvas}/use-canvas-agent-store.ts (97%) rename web/src/{app/(user)/canvas/stores => stores/canvas}/use-canvas-store.ts (99%) rename web/src/{app/(user)/canvas/stores => stores/canvas}/use-canvas-ui-store.ts (100%) rename web/src/{app => styles}/globals.css (100%) rename web/src/{app/(user)/canvas/export-types.ts => types/canvas-export.ts} (83%) rename web/src/{app/(user)/canvas/types.ts => types/canvas.ts} (100%) diff --git a/AGENTS.md b/AGENTS.md index 803bca0..a5ce89d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,15 +32,16 @@ ## 前端规范 -- 前端使用 Next.js App Router、React、TypeScript、Ant Design、Tailwind、Zustand。 +- 前端使用 Vite、React、React Router、TypeScript、Ant Design、Tailwind、Zustand。 - 编写 Ant Design 相关代码时,参考 https://ant.design/llms-full.txt 理解组件 API、示例和设计规范,并优先结合项目当前 antd 版本与既有写法。 - API 请求统一放在 `web/src/services/api/`。 - 全局或跨页面状态优先放在 `web/src/stores/`。 - 已经放在全局 store 或全局 hook 中的状态/动作,组件需要时直接使用对应 store/hook,不要为了“纯组件”层层透传 props;避免一个组件传递过多参数。 - 全局组件、全局常量、全局配置等全局性质的内容不要作为 props 或参数层层传递;哪里需要就在哪里直接从对应全局入口获取。 - 多个页面重复出现的 UI 副作用动作,例如复制文本并提示、下载并提示、统一确认弹窗,优先抽成 `web/src/hooks/` 下的全局 hook;不要放进 store,除非它确实是需要共享/订阅的状态。 -- 画布相关状态和组件放在 `web/src/app/(user)/canvas/` 内部。 -- 页面里只有一个主业务组件时直接写在 `page.tsx`,不要单独拆 `Manager` 组件再传一堆 props。 +- 路由页面放在 `web/src/pages/`,页面布局放在 `web/src/layouts/`,路由配置放在 `web/src/router.tsx`。 +- 画布页面放在 `web/src/pages/canvas/`,画布组件放在 `web/src/components/canvas/`,画布状态放在 `web/src/stores/canvas/`,画布工具函数放在 `web/src/lib/canvas/`。 +- 页面按目录组织,例如 `web/src/pages/image/index.tsx`;页面里只有一个主业务组件时直接写在对应页面入口中,不要单独拆 `Manager` 组件再传一堆 props。 - 不要新增只做简单转发的组件,例如只 `return {children}` 或只换个名字透传 props;直接在使用处使用真实组件或把逻辑写进当前文件。 - 页面私有 hook 放在对应页面目录下,例如 `admin/assets/use-admin-assets.ts`;只有多个页面真实复用的 hook 才放到外层 `hooks/`。 - 管理后台页面私有组件放到各自页面目录的 `components/` 下,例如 `admin/assets/components/`、`admin/prompts/components/`;不要为了单页面使用放到 `admin/components/` 共享目录。 diff --git a/docs/content/docs/progress/pending-test.mdx b/docs/content/docs/progress/pending-test.mdx index 3e6225a..69b9206 100644 --- a/docs/content/docs/progress/pending-test.mdx +++ b/docs/content/docs/progress/pending-test.mdx @@ -11,4 +11,4 @@ description: 当前版本已实现但仍需人工验证的变更项 - 音频和视频生成:选择 Gemini 调用格式时先给出不支持提示,仍需使用 OpenAI 兼容渠道。 - WebDAV 同步:移除 Next.js 转发代理和连接方式选择,改为浏览器前端直接连接 WebDAV 服务。 - 提示词库:移除 Next.js route 抓取和服务端内存缓存,改为浏览器前端直连 GitHub 原始文件并缓存到 IndexedDB。 -- 前端构建:移除 Next.js,改为 Vite + React Router,需验证首页、图片/视频工作台、素材、提示词库和画布路由跳转。 +- 前端构建:移除 Next.js,改为 Vite + React Router,并将前端目录调整为 `pages` / `components` / `stores` / `lib` / `layouts` / `styles`,需验证首页、图片/视频工作台、素材、提示词库和画布路由跳转。 diff --git a/web/src/app/(user)/canvas/[id]/page.tsx b/web/src/app/(user)/canvas/[id]/page.tsx deleted file mode 100644 index 948e1e2..0000000 --- a/web/src/app/(user)/canvas/[id]/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import CanvasClientPage from "./canvas-client-page"; - -export default function CanvasPage() { - return ; -} diff --git a/web/src/app/favicon.ico b/web/src/app/favicon.ico deleted file mode 100644 index 35695fff6acbe4a281ab812aee82cedddec31203..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38078 zcmeI4dyHIF9mi+eLMx;Xpn+njTPs*&K}j%*Nl7aPC2IVm5-}udQ4?chN|b2gBiW4+ zHBk&zAtV@VjEE%SBZv}wWD^beNEERU1d9`@EvW*ffZ(GYKcCsTx_h~2=H7E>W*>8Y zmi8~9{z%mG# zwN8gRwL(3b)7;hwnZ4Pgz1njqSFd?%sadyLESEBSo`9dgeI54lScM1i|1n$w>mX#V zeGKk^*jo9%vOMNAcdz>PXs`C1&(-Vqtd?4-ncCI0Q%G<*`~q4vc!t<-z=aSpYrO~V zf;zQ|V$Er8YlO_+?9pC}a+IA@D>ds@i{(9ibQmcMxPpYjZm@8!VU@!J$Z&_^BM>SC!H5!!p-r>XWE2!GvO#cJKe-6%r zka_*Q0`7*Hu~o*#n!{Wnvj=;zrz*MgzG|X2-QHiZT+2LGUIEv`vykth?C-|@7TycT zLy;|K^5w7_s=n@f92;Y-Im}gL*0u+Gskb+8FS z&jCw~%fREf$~8}4V~h=%HLYzAbzXDTKrPfnZH8f9!tYuAW+e4XNi+tR>8mL967E1%MGst=k?1Q4-%FaDP{7x8$kY)Ek z?!}>3UVSE@+h>1kS<~9R@^xEx?`ohH!#1DqEpRh*>#^6`Q^b3}0lx)A&tmg4b@HmLQ4jm=-G58Fe0m~q7OPH|MF1Qbh zUiY1IO&@)Y$(y;YVJ&M~yPLkDHTUYC-Fv7OOG7a~yW9wWhfu#|=IQaA}h=5g)$ z{wU;gI_H``Av3o%td)<#&kiD3NYoQ5QykqBF3z<31 zZH+80=FvUw0rxy#EIY4%NJFvLRJHKDz5%vD$X2oN7Pu9>4vS;wTnpJY7R+sp7~PF= zZ|)Hw^vN0yr`6KX92glC2R%GTfr@5^WqrZD{ zZ|>2(y65?3Z>6Ez;RwX+(U@c4HTnYR_8#&Ltbe(KYL z!k-{^pT^w}pM@7e$gK7H4vs@+4s)5aPEYR1y>+X_@|@ebbWryk@EUO!Y=PsU$edr< zp_`96%oTgx@j1(mefKus?PMDKAlwagj<T!hFA3&MUKKkfuOl&=SwP$;G4-47+ z?EfKXLY?mjdVTiye!yC&dk@4On_$nOdmt<=DDybF4*mvpj!BQ}OJEJ;%{kZfsdKK` zqrKYmVlm&3Y=?UxR)6FE0$+tQA#cvPrca$3_Gqss!(y_HZ076mDAdvCe&W5xuY$}R zJLg)R-1cUV_PW^2?@86@HmIY~A>yxx3m`Mc&bd}6x4qe;y)HKM^>H0cfS<`??}z=9 z*gwK9Sk=L?bFRhcZ!h*_Z}w=fi`CxD#=ZwnLX1{f%pT&mb#R=`$2=Y;{<~mri``CR zgYSetLyT5g%oG_yn=d4j#W%<1_!qi1qtp zdm0s6%SOFN@N>v?n5##7uort874v@9ID8SFg}Kt++V)^C3-ulwtw-4sqAmlEzu4~x z>O61Ow6;Ci%P87rHvI{B1nOuR6KhRt+ry~ZGB*BN@HmXUHy5M5wXA7vdl+T&^Ufsf zg%~YkVytCNYmd5lfBk&e1F@f9t2_tRu$DC!`n`R&P}|1H@B-Kc55gdy19Mx$TGq67 zvS|f89{qblKMz$oo~!tp+ZxtNHd}#}{Q4&FzCsmEtN5DR8rDkod<9;@)V1(1RMEAJ zuQ|t_AG%oTrhq=sY?os`$%hpSo z`dkb*!{bn-X_Yy1n9H0=dqgNwab0H4SaX;wSv3W`AHNa40Dix96v}9>kG{qjYmQO7x6hXQX73=A_bQ); zvij?5jIqh;Dd6#Y1?-2i`s-_qvB~Nw;I-p5a3_>G2lUa`m~`Digg)3ha(o=h+#AwI zUt^N>M}g&}@!vAu0Nq}PUDHQjW0Lhxffb~BKl~nw{$|2C*YwdhS^pJyH7T!#gOGnM zcFr|@k_|?I6G(dz6uk~O=bApr2B*L{sdvLZ$j$-B&bgLsunMds{Tt!i;JsyW?3`=K z2CKjl(ys>pcIvMk96RS)vf(J;{d~Vq6vxSitH657ZRy}R*>Dx`-ol9;94AW(Bn6TJ zNr9w5QXnai6i5mr1(E_ufuulEASsX(C{Um^kL?)$K5L5q7tAF8Ul_&>$2@c$v#zy$ zriZh~eqqzGR&YF(xh!q9a%29n>IT|qwVIjF^4a6(vib2=D>U{Si?(fTwL;_nHRltA z^BTX>&W|VCSsG)`H@O4PpZw9z^Ttc3I`gcL5wlvK(74mkR((QapABq6pU}89sY|=H z)~xZA^C+l=#{TW%beru)3&(AB$J=S9l`a^!o12*SX)D?p2FEniX|3H{;kemR(_Eo3 u&5dWZW{y#GYc?Mm(_H4_Q(ruu>?rGMXxwZc4Ab$U@!|Ht@c$Y^9{m@OhdAQ^ diff --git a/web/src/components/audio-settings-panel.tsx b/web/src/components/audio-settings-panel.tsx index 55a092c..d88e626 100644 --- a/web/src/components/audio-settings-panel.tsx +++ b/web/src/components/audio-settings-panel.tsx @@ -1,5 +1,3 @@ -"use client"; - import { type ReactNode } from "react"; import { ImageSettingsTheme } from "@/components/image-settings-panel"; diff --git a/web/src/app/(user)/canvas/components/asset-picker-modal.tsx b/web/src/components/canvas/asset-picker-modal.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/asset-picker-modal.tsx rename to web/src/components/canvas/asset-picker-modal.tsx index 46a290f..e12462b 100644 --- a/web/src/app/(user)/canvas/components/asset-picker-modal.tsx +++ b/web/src/components/canvas/asset-picker-modal.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useMemo, useState } from "react"; import { Empty, Input, Modal, Pagination, Tag } from "antd"; import { Search } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-agent-chat-ui.tsx b/web/src/components/canvas/canvas-agent-chat-ui.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-agent-chat-ui.tsx rename to web/src/components/canvas/canvas-agent-chat-ui.tsx index b227931..b8f622e 100644 --- a/web/src/app/(user)/canvas/components/canvas-agent-chat-ui.tsx +++ b/web/src/components/canvas/canvas-agent-chat-ui.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useRef, useState, type ReactNode } from "react"; import { Button, Tooltip } from "antd"; import { ArrowUp, CheckCircle2, CircleAlert, ImagePlus, LoaderCircle, UserRound, Wrench, X, XCircle } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-assistant-panel.tsx b/web/src/components/canvas/canvas-assistant-panel.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-assistant-panel.tsx rename to web/src/components/canvas/canvas-assistant-panel.tsx index e30b5f6..41b1652 100644 --- a/web/src/app/(user)/canvas/components/canvas-assistant-panel.tsx +++ b/web/src/components/canvas/canvas-assistant-panel.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useMemo, useRef, useState } from "react"; import copyToClipboard from "copy-to-clipboard"; import { Bot, Copy, Cpu, History, PanelRightClose, Plus, Settings2, Trash2, X } from "lucide-react"; @@ -20,10 +18,10 @@ import { Select, SelectContent, SelectItem, SelectTrigger } from "@/components/u import { CanvasPromptLibrary } from "./canvas-prompt-library"; import { AgentChatComposer, AgentChatMessage, AgentModeSwitch, AgentPanelTabs, AgentWorkingMessage, type CanvasAgentChatMessage, type CanvasAgentMode } from "./canvas-agent-chat-ui"; import { CanvasLocalAgentPanel } from "./canvas-local-agent-panel"; -import { NODE_DEFAULT_SIZE } from "../constants"; -import { CanvasNodeType, type CanvasAssistantMessage, type CanvasAssistantReference, type CanvasAssistantSession, type CanvasNodeData } from "../types"; -import { useCanvasAgentStore } from "../stores/use-canvas-agent-store"; -import { summarizeCanvasAgentOps, type CanvasAgentOp, type CanvasAgentSnapshot } from "../utils/canvas-agent-ops"; +import { NODE_DEFAULT_SIZE } from "@/constant/canvas"; +import { CanvasNodeType, type CanvasAssistantMessage, type CanvasAssistantReference, type CanvasAssistantSession, type CanvasNodeData } from "@/types/canvas"; +import { useCanvasAgentStore } from "@/stores/canvas/use-canvas-agent-store"; +import { summarizeCanvasAgentOps, type CanvasAgentOp, type CanvasAgentSnapshot } from "@/lib/canvas/canvas-agent-ops"; export const CANVAS_AGENT_PANEL_MOTION_MS = 500; const PANEL_MOTION_SECONDS = CANVAS_AGENT_PANEL_MOTION_MS / 1000; diff --git a/web/src/app/(user)/canvas/components/canvas-audio-settings-popover.tsx b/web/src/components/canvas/canvas-audio-settings-popover.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-audio-settings-popover.tsx rename to web/src/components/canvas/canvas-audio-settings-popover.tsx index 6bdc7fa..2f20434 100644 --- a/web/src/app/(user)/canvas/components/canvas-audio-settings-popover.tsx +++ b/web/src/components/canvas/canvas-audio-settings-popover.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useRef, useState, type RefObject } from "react"; import { createPortal } from "react-dom"; import { Settings2 } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-config-composer.tsx b/web/src/components/canvas/canvas-config-composer.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-config-composer.tsx rename to web/src/components/canvas/canvas-config-composer.tsx index 1fbde49..679fd20 100644 --- a/web/src/app/(user)/canvas/components/canvas-config-composer.tsx +++ b/web/src/components/canvas/canvas-config-composer.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useMemo, useRef, useState } from "react"; import type { CSSProperties, KeyboardEvent, MouseEvent, PointerEvent } from "react"; import { Button, Image } from "antd"; diff --git a/web/src/app/(user)/canvas/components/canvas-config-node-panel.tsx b/web/src/components/canvas/canvas-config-node-panel.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-config-node-panel.tsx rename to web/src/components/canvas/canvas-config-node-panel.tsx index 8ac921e..54b4023 100644 --- a/web/src/app/(user)/canvas/components/canvas-config-node-panel.tsx +++ b/web/src/components/canvas/canvas-config-node-panel.tsx @@ -1,5 +1,3 @@ -"use client"; - import type { CSSProperties } from "react"; import { Image as ImageIcon, LoaderCircle, MessageSquare, Music2, Play, Settings2, Square, Video } from "lucide-react"; import { Button, Segmented } from "antd"; @@ -12,7 +10,7 @@ import { useThemeStore } from "@/stores/use-theme-store"; import { CanvasImageSettingsPopover } from "./canvas-image-settings-popover"; import { CanvasAudioSettingsPopover, type CanvasAudioSettingKey } from "./canvas-audio-settings-popover"; import { CanvasVideoSettingsPopover } from "./canvas-video-settings-popover"; -import type { CanvasGenerationMode, CanvasNodeData, CanvasNodeMetadata } from "../types"; +import type { CanvasGenerationMode, CanvasNodeData, CanvasNodeMetadata } from "@/types/canvas"; type CanvasConfigNodePanelProps = { node: CanvasNodeData; diff --git a/web/src/app/(user)/canvas/components/canvas-connections.tsx b/web/src/components/canvas/canvas-connections.tsx similarity index 98% rename from web/src/app/(user)/canvas/components/canvas-connections.tsx rename to web/src/components/canvas/canvas-connections.tsx index 499f3a6..95cbb7a 100644 --- a/web/src/app/(user)/canvas/components/canvas-connections.tsx +++ b/web/src/components/canvas/canvas-connections.tsx @@ -2,7 +2,7 @@ import type { MouseEvent as ReactMouseEvent } from "react"; import { canvasThemes } from "@/lib/canvas-theme"; import { useThemeStore } from "@/stores/use-theme-store"; -import type { CanvasConnection, CanvasNodeData, ConnectionHandle, Position } from "../types"; +import type { CanvasConnection, CanvasNodeData, ConnectionHandle, Position } from "@/types/canvas"; export function ConnectionPath({ connection, diff --git a/web/src/app/(user)/canvas/components/canvas-context-menu.tsx b/web/src/components/canvas/canvas-context-menu.tsx similarity index 96% rename from web/src/app/(user)/canvas/components/canvas-context-menu.tsx rename to web/src/components/canvas/canvas-context-menu.tsx index 5a1a034..18ac9ce 100644 --- a/web/src/app/(user)/canvas/components/canvas-context-menu.tsx +++ b/web/src/components/canvas/canvas-context-menu.tsx @@ -1,12 +1,10 @@ -"use client"; - import { useEffect } from "react"; import type { ReactNode } from "react"; import { Plus, Trash2 } from "lucide-react"; import { canvasThemes } from "@/lib/canvas-theme"; import { useThemeStore } from "@/stores/use-theme-store"; -import type { ContextMenuState } from "../types"; +import type { ContextMenuState } from "@/types/canvas"; export function CanvasNodeContextMenu({ menu, onClose, onDuplicate, onDelete }: { menu: ContextMenuState; onClose: () => void; onDuplicate: () => void; onDelete: () => void }) { const theme = canvasThemes[useThemeStore((state) => state.theme)]; diff --git a/web/src/app/(user)/canvas/components/canvas-delete-projects-dialog.tsx b/web/src/components/canvas/canvas-delete-projects-dialog.tsx similarity index 90% rename from web/src/app/(user)/canvas/components/canvas-delete-projects-dialog.tsx rename to web/src/components/canvas/canvas-delete-projects-dialog.tsx index 6fc42c0..9b0f5f0 100644 --- a/web/src/app/(user)/canvas/components/canvas-delete-projects-dialog.tsx +++ b/web/src/components/canvas/canvas-delete-projects-dialog.tsx @@ -1,10 +1,8 @@ -"use client"; - import { Button, Modal } from "antd"; import { useAssetStore } from "@/stores/use-asset-store"; -import { useCanvasStore } from "../stores/use-canvas-store"; -import { useCanvasUiStore } from "../stores/use-canvas-ui-store"; +import { useCanvasStore } from "@/stores/canvas/use-canvas-store"; +import { useCanvasUiStore } from "@/stores/canvas/use-canvas-ui-store"; export function CanvasDeleteProjectsDialog() { const ids = useCanvasUiStore((state) => state.deleteProjectIds); diff --git a/web/src/app/(user)/canvas/components/canvas-image-settings-popover.tsx b/web/src/components/canvas/canvas-image-settings-popover.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-image-settings-popover.tsx rename to web/src/components/canvas/canvas-image-settings-popover.tsx index d636856..622f46d 100644 --- a/web/src/app/(user)/canvas/components/canvas-image-settings-popover.tsx +++ b/web/src/components/canvas/canvas-image-settings-popover.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useRef, useState, type RefObject } from "react"; import { createPortal } from "react-dom"; import { Settings2 } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-image-toolbar-settings-modal.tsx b/web/src/components/canvas/canvas-image-toolbar-settings-modal.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-image-toolbar-settings-modal.tsx rename to web/src/components/canvas/canvas-image-toolbar-settings-modal.tsx index 8fb1026..ded4517 100644 --- a/web/src/app/(user)/canvas/components/canvas-image-toolbar-settings-modal.tsx +++ b/web/src/components/canvas/canvas-image-toolbar-settings-modal.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useCallback, useEffect, useMemo, useRef, useState, type CSSProperties, type ReactNode } from "react"; import { Button, Card, Checkbox, Form, Modal, Space, Switch, Tag, Tooltip, Typography, theme as antdTheme } from "antd"; import { Ellipsis, Image as ImageIcon, Settings2 } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-image-toolbar-tools.tsx b/web/src/components/canvas/canvas-image-toolbar-tools.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-image-toolbar-tools.tsx rename to web/src/components/canvas/canvas-image-toolbar-tools.tsx index a41cd1d..e8e0164 100644 --- a/web/src/app/(user)/canvas/components/canvas-image-toolbar-tools.tsx +++ b/web/src/components/canvas/canvas-image-toolbar-tools.tsx @@ -1,9 +1,7 @@ -"use client"; - import type { ReactNode } from "react"; import { Brush, Camera, Copy, FileText, Grid2x2, Lock, LockOpen, Maximize2, Scissors, Sparkles, Upload, ZoomIn } from "lucide-react"; -import type { CanvasNodeData } from "../types"; +import type { CanvasNodeData } from "@/types/canvas"; export type ImageNodeActionToolId = "copyPrompt" | "reversePrompt" | "replace" | "resize" | "maskEdit" | "crop" | "split" | "upscale" | "superResolve" | "angle" | "view"; export type ImageQuickToolId = "info" | "delete" | "saveAsset" | "download" | "edit" | ImageNodeActionToolId; diff --git a/web/src/app/(user)/canvas/components/canvas-local-agent-panel.tsx b/web/src/components/canvas/canvas-local-agent-panel.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-local-agent-panel.tsx rename to web/src/components/canvas/canvas-local-agent-panel.tsx index 99992ac..508c505 100644 --- a/web/src/app/(user)/canvas/components/canvas-local-agent-panel.tsx +++ b/web/src/components/canvas/canvas-local-agent-panel.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useCallback, useEffect, useMemo, useRef, useState, type PointerEvent as ReactPointerEvent } from "react"; import { useSearchParams } from "react-router-dom"; import { App, Button, Input, Segmented, Tooltip } from "antd"; @@ -10,8 +8,8 @@ import { motion } from "motion/react"; import { canvasThemes } from "@/lib/canvas-theme"; import { useThemeStore } from "@/stores/use-theme-store"; import { useUserStore } from "@/stores/use-user-store"; -import { useCanvasAgentStore, type AgentAttachment, type AgentChatItem, type AgentEventLog, type AgentPanelTab, type AgentPendingToolCall, type AgentThreadSummary } from "../stores/use-canvas-agent-store"; -import { summarizeCanvasAgentOps, type CanvasAgentOp, type CanvasAgentSnapshot } from "../utils/canvas-agent-ops"; +import { useCanvasAgentStore, type AgentAttachment, type AgentChatItem, type AgentEventLog, type AgentPanelTab, type AgentPendingToolCall, type AgentThreadSummary } from "@/stores/canvas/use-canvas-agent-store"; +import { summarizeCanvasAgentOps, type CanvasAgentOp, type CanvasAgentSnapshot } from "@/lib/canvas/canvas-agent-ops"; import { AgentChatComposer, AgentChatMessage, AgentPanelTabs, AgentPendingToolCard, AgentWorkingMessage, type CanvasAgentChatAttachment } from "./canvas-agent-chat-ui"; const PANEL_MOTION_SECONDS = 0.5; diff --git a/web/src/app/(user)/canvas/components/canvas-mini-map.tsx b/web/src/components/canvas/canvas-mini-map.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-mini-map.tsx rename to web/src/components/canvas/canvas-mini-map.tsx index 1bf04f1..9433105 100644 --- a/web/src/app/(user)/canvas/components/canvas-mini-map.tsx +++ b/web/src/components/canvas/canvas-mini-map.tsx @@ -1,10 +1,8 @@ -"use client"; - import { useCallback, useMemo, useRef, useState } from "react"; import { canvasThemes } from "@/lib/canvas-theme"; import { useThemeStore } from "@/stores/use-theme-store"; -import { CanvasNodeType, type CanvasNodeData, type ViewportTransform } from "../types"; +import { CanvasNodeType, type CanvasNodeData, type ViewportTransform } from "@/types/canvas"; export function Minimap({ nodes, viewport, viewportSize, onViewportChange }: { nodes: CanvasNodeData[]; viewport: ViewportTransform; viewportSize: { width: number; height: number }; onViewportChange: (viewport: ViewportTransform) => void }) { const theme = canvasThemes[useThemeStore((state) => state.theme)]; diff --git a/web/src/app/(user)/canvas/components/canvas-node-angle-dialog.tsx b/web/src/components/canvas/canvas-node-angle-dialog.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-node-angle-dialog.tsx rename to web/src/components/canvas/canvas-node-angle-dialog.tsx index c4514a3..2116c61 100644 --- a/web/src/app/(user)/canvas/components/canvas-node-angle-dialog.tsx +++ b/web/src/components/canvas/canvas-node-angle-dialog.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useState } from "react"; import { Button, Modal, Segmented, Slider } from "antd"; import { RotateCcw, WandSparkles } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-node-crop-dialog.tsx b/web/src/components/canvas/canvas-node-crop-dialog.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-node-crop-dialog.tsx rename to web/src/components/canvas/canvas-node-crop-dialog.tsx index fafbdbc..8f42834 100644 --- a/web/src/app/(user)/canvas/components/canvas-node-crop-dialog.tsx +++ b/web/src/components/canvas/canvas-node-crop-dialog.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useRef, useState, type PointerEvent as ReactPointerEvent } from "react"; import { Button, Modal } from "antd"; import { Check, Lock, LockOpen, X } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-node-generation.ts b/web/src/components/canvas/canvas-node-generation.ts similarity index 98% rename from web/src/app/(user)/canvas/components/canvas-node-generation.ts rename to web/src/components/canvas/canvas-node-generation.ts index 3fd8ecf..5dd158f 100644 --- a/web/src/app/(user)/canvas/components/canvas-node-generation.ts +++ b/web/src/components/canvas/canvas-node-generation.ts @@ -3,8 +3,8 @@ import { imageReferenceLabel } from "@/lib/image-reference-prompt"; import { seedanceReferenceLabel } from "@/lib/seedance-video"; import type { ReferenceImage } from "@/types/image"; import type { ReferenceAudio, ReferenceVideo } from "@/types/media"; -import { CanvasNodeType, type CanvasConnection, type CanvasNodeData } from "../types"; -import { getGenerationResourceNodes } from "../utils/canvas-resource-references"; +import { CanvasNodeType, type CanvasConnection, type CanvasNodeData } from "@/types/canvas"; +import { getGenerationResourceNodes } from "@/lib/canvas/canvas-resource-references"; export type NodeGenerationContext = { prompt: string; diff --git a/web/src/app/(user)/canvas/components/canvas-node-hover-toolbar.tsx b/web/src/components/canvas/canvas-node-hover-toolbar.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-node-hover-toolbar.tsx rename to web/src/components/canvas/canvas-node-hover-toolbar.tsx index 338423a..6a79801 100644 --- a/web/src/app/(user)/canvas/components/canvas-node-hover-toolbar.tsx +++ b/web/src/components/canvas/canvas-node-hover-toolbar.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useMemo, useState, type ReactNode } from "react"; import { App, Modal, Segmented, Tooltip } from "antd"; import { Download, Ellipsis, FolderPlus, Image as ImageIcon, Info, MessageSquare, Minus, Music2, Pencil, Plus, RefreshCw, Settings2, Trash2, Upload, Video } from "lucide-react"; @@ -8,7 +6,7 @@ import { canvasThemes } from "@/lib/canvas-theme"; import { formatBytes, getDataUrlByteSize } from "@/lib/image-utils"; import { useCopyText } from "@/hooks/use-copy-text"; import { useThemeStore } from "@/stores/use-theme-store"; -import { CanvasNodeType, type CanvasNodeData, type ViewportTransform } from "../types"; +import { CanvasNodeType, type CanvasNodeData, type ViewportTransform } from "@/types/canvas"; import { ImageToolSettingsModal, type ImageToolbarSettingsTool } from "./canvas-image-toolbar-settings-modal"; import { IMAGE_QUICK_TOOLS_STORAGE_KEY, buildImageToolbarTools, defaultImageQuickToolIds, readImageQuickToolsConfig, type ImageQuickToolId } from "./canvas-image-toolbar-tools"; diff --git a/web/src/app/(user)/canvas/components/canvas-node-mask-edit-dialog.tsx b/web/src/components/canvas/canvas-node-mask-edit-dialog.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-node-mask-edit-dialog.tsx rename to web/src/components/canvas/canvas-node-mask-edit-dialog.tsx index 7367d93..6d413ce 100644 --- a/web/src/app/(user)/canvas/components/canvas-node-mask-edit-dialog.tsx +++ b/web/src/components/canvas/canvas-node-mask-edit-dialog.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useRef, useState, type PointerEvent as ReactPointerEvent } from "react"; import { Button, Input, Modal, Slider } from "antd"; import { Brush, Eraser, RotateCcw, WandSparkles, X } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-node-prompt-panel.tsx b/web/src/components/canvas/canvas-node-prompt-panel.tsx similarity index 98% rename from web/src/app/(user)/canvas/components/canvas-node-prompt-panel.tsx rename to web/src/components/canvas/canvas-node-prompt-panel.tsx index 592e547..7ce22ca 100644 --- a/web/src/app/(user)/canvas/components/canvas-node-prompt-panel.tsx +++ b/web/src/components/canvas/canvas-node-prompt-panel.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useState } from "react"; import { ArrowUp, LoaderCircle, Square } from "lucide-react"; import { Button } from "antd"; @@ -14,8 +12,8 @@ import { CanvasPromptLibrary } from "./canvas-prompt-library"; import { CanvasAudioSettingsPopover, type CanvasAudioSettingKey } from "./canvas-audio-settings-popover"; import { CanvasResourceMentionTextarea } from "./canvas-resource-mention-textarea"; import { CanvasVideoSettingsPopover } from "./canvas-video-settings-popover"; -import { CanvasNodeType, type CanvasGenerationMode, type CanvasNodeData } from "../types"; -import type { CanvasResourceReference } from "../utils/canvas-resource-references"; +import { CanvasNodeType, type CanvasGenerationMode, type CanvasNodeData } from "@/types/canvas"; +import type { CanvasResourceReference } from "@/lib/canvas/canvas-resource-references"; export type CanvasNodeGenerationMode = CanvasGenerationMode; diff --git a/web/src/app/(user)/canvas/components/canvas-node-split-dialog.tsx b/web/src/components/canvas/canvas-node-split-dialog.tsx similarity index 98% rename from web/src/app/(user)/canvas/components/canvas-node-split-dialog.tsx rename to web/src/components/canvas/canvas-node-split-dialog.tsx index ff05a55..a2f5a16 100644 --- a/web/src/app/(user)/canvas/components/canvas-node-split-dialog.tsx +++ b/web/src/components/canvas/canvas-node-split-dialog.tsx @@ -1,11 +1,9 @@ -"use client"; - import { useEffect, useState } from "react"; import { Button, InputNumber, Modal } from "antd"; import { Grid2x2 } from "lucide-react"; import { readImageMeta } from "@/lib/image-utils"; -import type { ImageSplitParams } from "../utils/canvas-image-data"; +import type { ImageSplitParams } from "@/lib/canvas/canvas-image-data"; export type CanvasImageSplitParams = ImageSplitParams; diff --git a/web/src/app/(user)/canvas/components/canvas-node-upscale-dialog.tsx b/web/src/components/canvas/canvas-node-upscale-dialog.tsx similarity index 98% rename from web/src/app/(user)/canvas/components/canvas-node-upscale-dialog.tsx rename to web/src/components/canvas/canvas-node-upscale-dialog.tsx index cc00a5e..99f3e72 100644 --- a/web/src/app/(user)/canvas/components/canvas-node-upscale-dialog.tsx +++ b/web/src/components/canvas/canvas-node-upscale-dialog.tsx @@ -1,11 +1,9 @@ -"use client"; - import { useEffect, useMemo, useState } from "react"; import { Button, Modal, Segmented } from "antd"; import { ImagePlus } from "lucide-react"; import { readImageMeta } from "@/lib/image-utils"; -import { MAX_UPSCALE_LONG_EDGE, resolveUpscaleSize, type ImageUpscaleAlgorithm, type ImageUpscaleParams } from "../utils/canvas-image-data"; +import { MAX_UPSCALE_LONG_EDGE, resolveUpscaleSize, type ImageUpscaleAlgorithm, type ImageUpscaleParams } from "@/lib/canvas/canvas-image-data"; export type CanvasImageUpscaleParams = ImageUpscaleParams; diff --git a/web/src/app/(user)/canvas/components/canvas-node.tsx b/web/src/components/canvas/canvas-node.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-node.tsx rename to web/src/components/canvas/canvas-node.tsx index 0fd9cd8..281390f 100644 --- a/web/src/app/(user)/canvas/components/canvas-node.tsx +++ b/web/src/components/canvas/canvas-node.tsx @@ -1,5 +1,3 @@ -"use client"; - import React, { useCallback, useEffect, useRef, useState } from "react"; import type { ReactNode } from "react"; import { ChevronRight, Image as ImageIcon, Music2, RefreshCw, Star, Video } from "lucide-react"; @@ -8,8 +6,8 @@ import { canvasThemes } from "@/lib/canvas-theme"; import { formatBytes } from "@/lib/image-utils"; import { useThemeStore } from "@/stores/use-theme-store"; import { CanvasResourceMentionTextarea } from "./canvas-resource-mention-textarea"; -import { CanvasNodeType, type CanvasNodeData, type Position } from "../types"; -import type { CanvasResourceReference } from "../utils/canvas-resource-references"; +import { CanvasNodeType, type CanvasNodeData, type Position } from "@/types/canvas"; +import type { CanvasResourceReference } from "@/lib/canvas/canvas-resource-references"; type ResizeCorner = "top-left" | "top-right" | "bottom-left" | "bottom-right"; const selectionBlue = "#2f80ff"; diff --git a/web/src/app/(user)/canvas/components/canvas-project-card.tsx b/web/src/components/canvas/canvas-project-card.tsx similarity index 95% rename from web/src/app/(user)/canvas/components/canvas-project-card.tsx rename to web/src/components/canvas/canvas-project-card.tsx index d90381e..ca306cc 100644 --- a/web/src/app/(user)/canvas/components/canvas-project-card.tsx +++ b/web/src/components/canvas/canvas-project-card.tsx @@ -1,12 +1,10 @@ -"use client"; - import { Check, Download, Pencil, Trash2, X } from "lucide-react"; import { useNavigate, useSearchParams } from "react-router-dom"; import { Button, Input } from "antd"; -import { useCanvasStore, type CanvasProject } from "../stores/use-canvas-store"; -import { useCanvasUiStore } from "../stores/use-canvas-ui-store"; -import { exportCanvasProjects } from "../utils/canvas-export"; +import { useCanvasStore, type CanvasProject } from "@/stores/canvas/use-canvas-store"; +import { useCanvasUiStore } from "@/stores/canvas/use-canvas-ui-store"; +import { exportCanvasProjects } from "@/lib/canvas/canvas-export"; export function CanvasProjectCard({ project }: { project: CanvasProject }) { const navigate = useNavigate(); diff --git a/web/src/app/(user)/canvas/components/canvas-prompt-library.tsx b/web/src/components/canvas/canvas-prompt-library.tsx similarity index 98% rename from web/src/app/(user)/canvas/components/canvas-prompt-library.tsx rename to web/src/components/canvas/canvas-prompt-library.tsx index a29730d..ec73084 100644 --- a/web/src/app/(user)/canvas/components/canvas-prompt-library.tsx +++ b/web/src/components/canvas/canvas-prompt-library.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useState } from "react"; import { Button, Tooltip } from "antd"; import { BookOpen } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-resource-mention-textarea.tsx b/web/src/components/canvas/canvas-resource-mention-textarea.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-resource-mention-textarea.tsx rename to web/src/components/canvas/canvas-resource-mention-textarea.tsx index 3b13088..4e4d801 100644 --- a/web/src/app/(user)/canvas/components/canvas-resource-mention-textarea.tsx +++ b/web/src/components/canvas/canvas-resource-mention-textarea.tsx @@ -1,5 +1,3 @@ -"use client"; - import { forwardRef, useMemo, useRef, useState } from "react"; import type { CSSProperties, MouseEvent, PointerEvent, TextareaHTMLAttributes } from "react"; import { createPortal } from "react-dom"; @@ -7,7 +5,7 @@ import { FileText, Image as ImageIcon, Music2, Video } from "lucide-react"; import { canvasThemes } from "@/lib/canvas-theme"; import { useThemeStore } from "@/stores/use-theme-store"; -import type { CanvasResourceReference } from "../utils/canvas-resource-references"; +import type { CanvasResourceReference } from "@/lib/canvas/canvas-resource-references"; type MentionState = { start: number; diff --git a/web/src/app/(user)/canvas/components/canvas-size-picker.tsx b/web/src/components/canvas/canvas-size-picker.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-size-picker.tsx rename to web/src/components/canvas/canvas-size-picker.tsx index 349a3aa..ba84dfa 100644 --- a/web/src/app/(user)/canvas/components/canvas-size-picker.tsx +++ b/web/src/components/canvas/canvas-size-picker.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useRef, useState } from "react"; import { Select } from "antd"; diff --git a/web/src/app/(user)/canvas/components/canvas-toolbar.tsx b/web/src/components/canvas/canvas-toolbar.tsx similarity index 100% rename from web/src/app/(user)/canvas/components/canvas-toolbar.tsx rename to web/src/components/canvas/canvas-toolbar.tsx diff --git a/web/src/app/(user)/canvas/components/canvas-video-settings-popover.tsx b/web/src/components/canvas/canvas-video-settings-popover.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/canvas-video-settings-popover.tsx rename to web/src/components/canvas/canvas-video-settings-popover.tsx index 4e4c613..d9301a3 100644 --- a/web/src/app/(user)/canvas/components/canvas-video-settings-popover.tsx +++ b/web/src/components/canvas/canvas-video-settings-popover.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useRef, useState, type RefObject } from "react"; import { createPortal } from "react-dom"; import { Settings2 } from "lucide-react"; diff --git a/web/src/app/(user)/canvas/components/canvas-zoom-controls.tsx b/web/src/components/canvas/canvas-zoom-controls.tsx similarity index 100% rename from web/src/app/(user)/canvas/components/canvas-zoom-controls.tsx rename to web/src/components/canvas/canvas-zoom-controls.tsx diff --git a/web/src/app/(user)/canvas/components/infinite-canvas.tsx b/web/src/components/canvas/infinite-canvas.tsx similarity index 99% rename from web/src/app/(user)/canvas/components/infinite-canvas.tsx rename to web/src/components/canvas/infinite-canvas.tsx index f9293da..2d9550e 100644 --- a/web/src/app/(user)/canvas/components/infinite-canvas.tsx +++ b/web/src/components/canvas/infinite-canvas.tsx @@ -1,10 +1,8 @@ -"use client"; - import React, { useEffect, useRef, useState } from "react"; import { canvasThemes, type CanvasBackgroundMode } from "@/lib/canvas-theme"; import { useThemeStore } from "@/stores/use-theme-store"; -import type { ViewportTransform } from "../types"; +import type { ViewportTransform } from "@/types/canvas"; type InfiniteCanvasProps = { containerRef: React.RefObject; diff --git a/web/src/components/image-generation-pending.tsx b/web/src/components/image-generation-pending.tsx index ecaf660..544d954 100644 --- a/web/src/components/image-generation-pending.tsx +++ b/web/src/components/image-generation-pending.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useState } from "react"; import { LoaderCircle } from "lucide-react"; diff --git a/web/src/components/image-settings-panel.tsx b/web/src/components/image-settings-panel.tsx index 386bde3..3a1f2ed 100644 --- a/web/src/components/image-settings-panel.tsx +++ b/web/src/components/image-settings-panel.tsx @@ -1,5 +1,3 @@ -"use client"; - import { type ReactNode, useState } from "react"; import { ConfigProvider, Switch } from "antd"; diff --git a/web/src/components/layout/app-config-modal.tsx b/web/src/components/layout/app-config-modal.tsx index 19b581e..04b26b9 100644 --- a/web/src/components/layout/app-config-modal.tsx +++ b/web/src/components/layout/app-config-modal.tsx @@ -1,5 +1,3 @@ -"use client"; - import { App, Button, Form, Input, Modal, Progress, Select, Tabs } from "antd"; import { CircleAlert, Cloud, Plus, RefreshCw, Trash2, Wifi } from "lucide-react"; import { useState } from "react"; diff --git a/web/src/components/layout/app-providers.tsx b/web/src/components/layout/app-providers.tsx index 5d6e99e..1eaccdd 100644 --- a/web/src/components/layout/app-providers.tsx +++ b/web/src/components/layout/app-providers.tsx @@ -1,5 +1,3 @@ -"use client"; - import type { ReactNode } from "react"; import { useEffect } from "react"; import { ProConfigProvider } from "@ant-design/pro-components"; diff --git a/web/src/components/layout/app-top-nav.tsx b/web/src/components/layout/app-top-nav.tsx index b421b62..326bf41 100644 --- a/web/src/components/layout/app-top-nav.tsx +++ b/web/src/components/layout/app-top-nav.tsx @@ -1,5 +1,3 @@ -"use client"; - import { Menu } from "lucide-react"; import { Link, useLocation } from "react-router-dom"; diff --git a/web/src/components/layout/client-root-init.tsx b/web/src/components/layout/client-root-init.tsx index 1b00c9b..139af77 100644 --- a/web/src/components/layout/client-root-init.tsx +++ b/web/src/components/layout/client-root-init.tsx @@ -1,5 +1,3 @@ -"use client"; - import type { ReactNode } from "react"; import { useEffect, useRef } from "react"; import { App } from "antd"; diff --git a/web/src/components/layout/github-link.tsx b/web/src/components/layout/github-link.tsx index eee8208..ca695b2 100644 --- a/web/src/components/layout/github-link.tsx +++ b/web/src/components/layout/github-link.tsx @@ -1,5 +1,3 @@ -"use client"; - import { GithubOutlined } from "@ant-design/icons"; import { cn } from "@/lib/utils"; diff --git a/web/src/components/layout/mobile-nav-drawer.tsx b/web/src/components/layout/mobile-nav-drawer.tsx index 4ec1ca9..c600916 100644 --- a/web/src/components/layout/mobile-nav-drawer.tsx +++ b/web/src/components/layout/mobile-nav-drawer.tsx @@ -1,5 +1,3 @@ -"use client"; - import { Drawer } from "antd"; import { Link } from "react-router-dom"; diff --git a/web/src/components/layout/user-status-actions.tsx b/web/src/components/layout/user-status-actions.tsx index abd2e73..44bbe50 100644 --- a/web/src/components/layout/user-status-actions.tsx +++ b/web/src/components/layout/user-status-actions.tsx @@ -1,5 +1,3 @@ -"use client"; - import type { CSSProperties } from "react"; import { BookOpen, Keyboard, Settings2 } from "lucide-react"; diff --git a/web/src/components/layout/version-release-modal.tsx b/web/src/components/layout/version-release-modal.tsx index af58172..7f4bf19 100644 --- a/web/src/components/layout/version-release-modal.tsx +++ b/web/src/components/layout/version-release-modal.tsx @@ -1,5 +1,3 @@ -"use client"; - import type { CSSProperties } from "react"; import { Modal, Tag, Timeline } from "antd"; import { useVersionCheck } from "@/hooks/use-version-check"; diff --git a/web/src/components/model-picker.tsx b/web/src/components/model-picker.tsx index bb2f7ab..1ebf373 100644 --- a/web/src/components/model-picker.tsx +++ b/web/src/components/model-picker.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useId, useMemo, useState } from "react"; import { Cpu } from "lucide-react"; diff --git a/web/src/components/prompts/prompt-card.tsx b/web/src/components/prompts/prompt-card.tsx index 31d4ec4..ce8c011 100644 --- a/web/src/components/prompts/prompt-card.tsx +++ b/web/src/components/prompts/prompt-card.tsx @@ -1,5 +1,3 @@ -"use client"; - import { Copy } from "lucide-react"; import type { ReactNode } from "react"; import { Button, Card, Tag } from "antd"; diff --git a/web/src/components/prompts/prompt-select-dialog.tsx b/web/src/components/prompts/prompt-select-dialog.tsx index 8c58586..6f7b4fc 100644 --- a/web/src/components/prompts/prompt-select-dialog.tsx +++ b/web/src/components/prompts/prompt-select-dialog.tsx @@ -1,5 +1,3 @@ -"use client"; - import { Check, Search } from "lucide-react"; import { type UIEvent, useEffect, useState } from "react"; import { App, Empty, Input, Modal, Spin, Tag } from "antd"; diff --git a/web/src/components/prompts/use-prompt-list.ts b/web/src/components/prompts/use-prompt-list.ts index c09f117..b5b8f20 100644 --- a/web/src/components/prompts/use-prompt-list.ts +++ b/web/src/components/prompts/use-prompt-list.ts @@ -1,5 +1,3 @@ -"use client"; - import { useMemo } from "react"; import { useInfiniteQuery } from "@tanstack/react-query"; diff --git a/web/src/components/ui/animated-theme-toggler.tsx b/web/src/components/ui/animated-theme-toggler.tsx index 717db7b..56c0908 100644 --- a/web/src/components/ui/animated-theme-toggler.tsx +++ b/web/src/components/ui/animated-theme-toggler.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useCallback, useEffect, useRef, useState } from "react"; import { Moon, Sun } from "lucide-react"; import { flushSync } from "react-dom"; diff --git a/web/src/components/ui/dia-text-reveal.tsx b/web/src/components/ui/dia-text-reveal.tsx index 45ebf8d..373cf02 100644 --- a/web/src/components/ui/dia-text-reveal.tsx +++ b/web/src/components/ui/dia-text-reveal.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useRef, useState } from "react"; import { animate, motion, useInView, useMotionValue, useReducedMotion, useTransform, type HTMLMotionProps } from "motion/react"; diff --git a/web/src/components/ui/select.tsx b/web/src/components/ui/select.tsx index 414714f..c9bb249 100644 --- a/web/src/components/ui/select.tsx +++ b/web/src/components/ui/select.tsx @@ -1,5 +1,3 @@ -"use client" - import * as React from "react" import { Select as SelectPrimitive } from "radix-ui" diff --git a/web/src/components/video-settings-panel.tsx b/web/src/components/video-settings-panel.tsx index ab7bce2..9fb977d 100644 --- a/web/src/components/video-settings-panel.tsx +++ b/web/src/components/video-settings-panel.tsx @@ -1,5 +1,3 @@ -"use client"; - import { type ReactNode } from "react"; import { Switch } from "antd"; diff --git a/web/src/app/(user)/canvas/constants.ts b/web/src/constant/canvas.ts similarity index 93% rename from web/src/app/(user)/canvas/constants.ts rename to web/src/constant/canvas.ts index 3029ec7..d1f02b6 100644 --- a/web/src/app/(user)/canvas/constants.ts +++ b/web/src/constant/canvas.ts @@ -1,5 +1,5 @@ -import { CanvasNodeType } from "./types"; -import type { CanvasNodeMetadata } from "./types"; +import { CanvasNodeType } from "@/types/canvas"; +import type { CanvasNodeMetadata } from "@/types/canvas"; type CanvasNodeSpec = { width: number; diff --git a/web/src/hooks/use-copy-text.ts b/web/src/hooks/use-copy-text.ts index 80f1eea..9d2c6ff 100644 --- a/web/src/hooks/use-copy-text.ts +++ b/web/src/hooks/use-copy-text.ts @@ -1,5 +1,3 @@ -"use client"; - import { App } from "antd"; import copy from "copy-to-clipboard"; diff --git a/web/src/app/(user)/layout.tsx b/web/src/layouts/user-layout.tsx similarity index 96% rename from web/src/app/(user)/layout.tsx rename to web/src/layouts/user-layout.tsx index 9fa65bf..752d71a 100644 --- a/web/src/app/(user)/layout.tsx +++ b/web/src/layouts/user-layout.tsx @@ -1,5 +1,3 @@ -"use client"; - import type { ReactNode } from "react"; import { AppTopNav } from "@/components/layout/app-top-nav"; diff --git a/web/src/app/(user)/canvas/utils/canvas-agent-ops.ts b/web/src/lib/canvas/canvas-agent-ops.ts similarity index 97% rename from web/src/app/(user)/canvas/utils/canvas-agent-ops.ts rename to web/src/lib/canvas/canvas-agent-ops.ts index 335d0f0..5c2a2e9 100644 --- a/web/src/app/(user)/canvas/utils/canvas-agent-ops.ts +++ b/web/src/lib/canvas/canvas-agent-ops.ts @@ -1,7 +1,7 @@ import { nanoid } from "nanoid"; -import { getNodeSpec } from "../constants"; -import { CanvasNodeType, type CanvasConnection, type CanvasNodeData, type CanvasNodeMetadata, type ViewportTransform } from "../types"; +import { getNodeSpec } from "@/constant/canvas"; +import { CanvasNodeType, type CanvasConnection, type CanvasNodeData, type CanvasNodeMetadata, type ViewportTransform } from "@/types/canvas"; export type CanvasAgentOp = | { type: "add_node"; id?: string; nodeType?: CanvasNodeType; title?: string; position?: { x: number; y: number }; x?: number; y?: number; width?: number; height?: number; metadata?: CanvasNodeMetadata } diff --git a/web/src/app/(user)/canvas/utils/canvas-export.ts b/web/src/lib/canvas/canvas-export.ts similarity index 94% rename from web/src/app/(user)/canvas/utils/canvas-export.ts rename to web/src/lib/canvas/canvas-export.ts index 5e91aba..f4c41a5 100644 --- a/web/src/app/(user)/canvas/utils/canvas-export.ts +++ b/web/src/lib/canvas/canvas-export.ts @@ -3,8 +3,8 @@ import { saveAs } from "file-saver"; import { createZip } from "@/lib/zip"; import { getMediaBlob } from "@/services/file-storage"; import { getImageBlob } from "@/services/image-storage"; -import type { CanvasExportAsset, CanvasExportFile } from "../export-types"; -import type { CanvasProject } from "../stores/use-canvas-store"; +import type { CanvasExportAsset, CanvasExportFile } from "@/types/canvas-export"; +import type { CanvasProject } from "@/stores/canvas/use-canvas-store"; export async function exportCanvasProjects(projects: CanvasProject[], fileName = "无限画布") { const zipFiles: { name: string; data: BlobPart }[] = []; diff --git a/web/src/app/(user)/canvas/utils/canvas-image-data.ts b/web/src/lib/canvas/canvas-image-data.ts similarity index 99% rename from web/src/app/(user)/canvas/utils/canvas-image-data.ts rename to web/src/lib/canvas/canvas-image-data.ts index a91f34d..c9fd8e4 100644 --- a/web/src/app/(user)/canvas/utils/canvas-image-data.ts +++ b/web/src/lib/canvas/canvas-image-data.ts @@ -1,5 +1,3 @@ -"use client"; - export type ImageCropRect = { x: number; y: number; diff --git a/web/src/app/(user)/canvas/utils/canvas-node-size.ts b/web/src/lib/canvas/canvas-node-size.ts similarity index 98% rename from web/src/app/(user)/canvas/utils/canvas-node-size.ts rename to web/src/lib/canvas/canvas-node-size.ts index fdce716..b43bb8e 100644 --- a/web/src/app/(user)/canvas/utils/canvas-node-size.ts +++ b/web/src/lib/canvas/canvas-node-size.ts @@ -1,5 +1,3 @@ -"use client"; - export function fitNodeSize(width: number, height: number, maxWidth = 640, maxHeight = 640) { const w = Math.max(1, width); const h = Math.max(1, height); diff --git a/web/src/app/(user)/canvas/utils/canvas-resource-references.ts b/web/src/lib/canvas/canvas-resource-references.ts similarity index 99% rename from web/src/app/(user)/canvas/utils/canvas-resource-references.ts rename to web/src/lib/canvas/canvas-resource-references.ts index 3e77499..cf4b23d 100644 --- a/web/src/app/(user)/canvas/utils/canvas-resource-references.ts +++ b/web/src/lib/canvas/canvas-resource-references.ts @@ -1,6 +1,6 @@ import { imageReferenceLabel } from "@/lib/image-reference-prompt"; import { seedanceReferenceLabel } from "@/lib/seedance-video"; -import { CanvasNodeType, type CanvasConnection, type CanvasNodeData } from "../types"; +import { CanvasNodeType, type CanvasConnection, type CanvasNodeData } from "@/types/canvas"; export type CanvasResourceKind = "image" | "video" | "audio" | "text"; diff --git a/web/src/main.tsx b/web/src/main.tsx index 3c06649..ffde538 100644 --- a/web/src/main.tsx +++ b/web/src/main.tsx @@ -1,7 +1,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import "antd/dist/reset.css"; -import "./app/globals.css"; +import "./styles/globals.css"; import { RouterProvider } from "react-router-dom"; import { AppProviders } from "@/components/layout/app-providers"; diff --git a/web/src/app/(user)/assets/asset-transfer.ts b/web/src/pages/assets/asset-transfer.ts similarity index 100% rename from web/src/app/(user)/assets/asset-transfer.ts rename to web/src/pages/assets/asset-transfer.ts diff --git a/web/src/app/(user)/assets/page.tsx b/web/src/pages/assets/index.tsx similarity index 99% rename from web/src/app/(user)/assets/page.tsx rename to web/src/pages/assets/index.tsx index 38c4f49..56ef703 100644 --- a/web/src/app/(user)/assets/page.tsx +++ b/web/src/pages/assets/index.tsx @@ -1,5 +1,3 @@ -"use client"; - import { Copy, Download, PencilLine, Search, Trash2, Upload } from "lucide-react"; import { useEffect, useMemo, useRef, useState } from "react"; import { App, Button, Card, Drawer, Empty, Form, Image, Input, Modal, Pagination, Select, Space, Tag, Typography } from "antd"; diff --git a/web/src/app/(user)/canvas/page.tsx b/web/src/pages/canvas/index.tsx similarity index 93% rename from web/src/app/(user)/canvas/page.tsx rename to web/src/pages/canvas/index.tsx index 0942600..8fd37ca 100644 --- a/web/src/app/(user)/canvas/page.tsx +++ b/web/src/pages/canvas/index.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useEffect, useRef } from "react"; import { useNavigate, useSearchParams } from "react-router-dom"; import { App, Button } from "antd"; @@ -8,12 +6,12 @@ import { Download, FileUp, Plus } from "lucide-react"; import { readZip } from "@/lib/zip"; import { setMediaBlob } from "@/services/file-storage"; import { setImageBlob } from "@/services/image-storage"; -import { CanvasDeleteProjectsDialog } from "./components/canvas-delete-projects-dialog"; -import { CanvasProjectCard } from "./components/canvas-project-card"; -import type { CanvasExportFile } from "./export-types"; -import { useCanvasStore } from "./stores/use-canvas-store"; -import { useCanvasUiStore } from "./stores/use-canvas-ui-store"; -import { exportCanvasProjects } from "./utils/canvas-export"; +import { CanvasDeleteProjectsDialog } from "@/components/canvas/canvas-delete-projects-dialog"; +import { CanvasProjectCard } from "@/components/canvas/canvas-project-card"; +import type { CanvasExportFile } from "@/types/canvas-export"; +import { useCanvasStore } from "@/stores/canvas/use-canvas-store"; +import { useCanvasUiStore } from "@/stores/canvas/use-canvas-ui-store"; +import { exportCanvasProjects } from "@/lib/canvas/canvas-export"; export default function CanvasPage() { const { message } = App.useApp(); diff --git a/web/src/app/(user)/canvas/[id]/canvas-client-page.tsx b/web/src/pages/canvas/project.tsx similarity index 98% rename from web/src/app/(user)/canvas/[id]/canvas-client-page.tsx rename to web/src/pages/canvas/project.tsx index a5dd125..c757b4f 100644 --- a/web/src/app/(user)/canvas/[id]/canvas-client-page.tsx +++ b/web/src/pages/canvas/project.tsx @@ -1,5 +1,3 @@ -"use client"; - import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"; import type { ChangeEvent as ReactChangeEvent, DragEvent as ReactDragEvent, MouseEvent as ReactMouseEvent, PointerEvent as ReactPointerEvent } from "react"; import { useNavigate, useParams, useSearchParams } from "react-router-dom"; @@ -19,35 +17,35 @@ import { canvasThemes, type CanvasBackgroundMode } from "@/lib/canvas-theme"; import { UserStatusActions } from "@/components/layout/user-status-actions"; import { useAssetStore } from "@/stores/use-asset-store"; import { useThemeStore } from "@/stores/use-theme-store"; -import { cropDataUrl, splitDataUrl, upscaleDataUrl } from "../utils/canvas-image-data"; -import { fitNodeSize, nodeSizeFromRatio } from "../utils/canvas-node-size"; +import { cropDataUrl, splitDataUrl, upscaleDataUrl } from "@/lib/canvas/canvas-image-data"; +import { fitNodeSize, nodeSizeFromRatio } from "@/lib/canvas/canvas-node-size"; import { App, Button, Dropdown, Modal } from "antd"; -import { NODE_DEFAULT_SIZE, getNodeSpec } from "../constants"; -import { ActiveConnectionPath, ConnectionPath } from "../components/canvas-connections"; -import { CanvasConfigComposer } from "../components/canvas-config-composer"; -import { CanvasConfigNodePanel } from "../components/canvas-config-node-panel"; -import { CANVAS_AGENT_PANEL_MOTION_MS, CanvasAssistantPanel } from "../components/canvas-assistant-panel"; -import { CanvasNodeContextMenu } from "../components/canvas-context-menu"; -import { CanvasNodeAngleDialog, type CanvasImageAngleParams } from "../components/canvas-node-angle-dialog"; -import { CanvasNodeCropDialog, type CanvasImageCropRect } from "../components/canvas-node-crop-dialog"; -import { CanvasNodeMaskEditDialog, type CanvasImageMaskEditPayload } from "../components/canvas-node-mask-edit-dialog"; -import { CanvasNodeSplitDialog, type CanvasImageSplitParams } from "../components/canvas-node-split-dialog"; -import { CanvasNodeUpscaleDialog, type CanvasImageUpscaleParams } from "../components/canvas-node-upscale-dialog"; -import { buildNodeGenerationContext, buildNodeGenerationInputs, buildNodeResponseMessages, hydrateNodeGenerationContext, type NodeGenerationInput } from "../components/canvas-node-generation"; -import { CanvasNodeHoverToolbar, CanvasNodeInfoModal } from "../components/canvas-node-hover-toolbar"; -import { InfiniteCanvas } from "../components/infinite-canvas"; -import { Minimap } from "../components/canvas-mini-map"; -import { CanvasNode } from "../components/canvas-node"; -import { CanvasNodePromptPanel, type CanvasNodeGenerationMode } from "../components/canvas-node-prompt-panel"; -import { CanvasToolbar } from "../components/canvas-toolbar"; -import { AssetPickerModal, type InsertAssetPayload } from "../components/asset-picker-modal"; -import { CanvasZoomControls } from "../components/canvas-zoom-controls"; -import { CanvasLocalAgentPanel } from "../components/canvas-local-agent-panel"; -import { useCanvasAgentStore } from "../stores/use-canvas-agent-store"; -import { useCanvasStore } from "../stores/use-canvas-store"; -import { applyCanvasAgentOps, type CanvasAgentOp, type CanvasAgentSnapshot } from "../utils/canvas-agent-ops"; -import { buildCanvasResourceReferences, buildNodeMentionReferences } from "../utils/canvas-resource-references"; -import type { CanvasAgentMode } from "../components/canvas-agent-chat-ui"; +import { NODE_DEFAULT_SIZE, getNodeSpec } from "@/constant/canvas"; +import { ActiveConnectionPath, ConnectionPath } from "@/components/canvas/canvas-connections"; +import { CanvasConfigComposer } from "@/components/canvas/canvas-config-composer"; +import { CanvasConfigNodePanel } from "@/components/canvas/canvas-config-node-panel"; +import { CANVAS_AGENT_PANEL_MOTION_MS, CanvasAssistantPanel } from "@/components/canvas/canvas-assistant-panel"; +import { CanvasNodeContextMenu } from "@/components/canvas/canvas-context-menu"; +import { CanvasNodeAngleDialog, type CanvasImageAngleParams } from "@/components/canvas/canvas-node-angle-dialog"; +import { CanvasNodeCropDialog, type CanvasImageCropRect } from "@/components/canvas/canvas-node-crop-dialog"; +import { CanvasNodeMaskEditDialog, type CanvasImageMaskEditPayload } from "@/components/canvas/canvas-node-mask-edit-dialog"; +import { CanvasNodeSplitDialog, type CanvasImageSplitParams } from "@/components/canvas/canvas-node-split-dialog"; +import { CanvasNodeUpscaleDialog, type CanvasImageUpscaleParams } from "@/components/canvas/canvas-node-upscale-dialog"; +import { buildNodeGenerationContext, buildNodeGenerationInputs, buildNodeResponseMessages, hydrateNodeGenerationContext, type NodeGenerationInput } from "@/components/canvas/canvas-node-generation"; +import { CanvasNodeHoverToolbar, CanvasNodeInfoModal } from "@/components/canvas/canvas-node-hover-toolbar"; +import { InfiniteCanvas } from "@/components/canvas/infinite-canvas"; +import { Minimap } from "@/components/canvas/canvas-mini-map"; +import { CanvasNode } from "@/components/canvas/canvas-node"; +import { CanvasNodePromptPanel, type CanvasNodeGenerationMode } from "@/components/canvas/canvas-node-prompt-panel"; +import { CanvasToolbar } from "@/components/canvas/canvas-toolbar"; +import { AssetPickerModal, type InsertAssetPayload } from "@/components/canvas/asset-picker-modal"; +import { CanvasZoomControls } from "@/components/canvas/canvas-zoom-controls"; +import { CanvasLocalAgentPanel } from "@/components/canvas/canvas-local-agent-panel"; +import { useCanvasAgentStore } from "@/stores/canvas/use-canvas-agent-store"; +import { useCanvasStore } from "@/stores/canvas/use-canvas-store"; +import { applyCanvasAgentOps, type CanvasAgentOp, type CanvasAgentSnapshot } from "@/lib/canvas/canvas-agent-ops"; +import { buildCanvasResourceReferences, buildNodeMentionReferences } from "@/lib/canvas/canvas-resource-references"; +import type { CanvasAgentMode } from "@/components/canvas/canvas-agent-chat-ui"; import { CanvasNodeType, type CanvasAssistantImage, @@ -61,7 +59,7 @@ import { type Position, type SelectionBox, type ViewportTransform, -} from "../types"; +} from "@/types/canvas"; import type { ReferenceImage } from "@/types/image"; import type { ReferenceAudio } from "@/types/media"; diff --git a/web/src/app/(user)/page.tsx b/web/src/pages/home/index.tsx similarity index 99% rename from web/src/app/(user)/page.tsx rename to web/src/pages/home/index.tsx index e7174d8..7007733 100644 --- a/web/src/app/(user)/page.tsx +++ b/web/src/pages/home/index.tsx @@ -1,5 +1,3 @@ -"use client"; - import { ArrowRight } from "lucide-react"; import { type ReactNode, useEffect, useState } from "react"; import { App, Button, Image, Tag } from "antd"; diff --git a/web/src/app/(user)/image/page.tsx b/web/src/pages/image/index.tsx similarity index 99% rename from web/src/app/(user)/image/page.tsx rename to web/src/pages/image/index.tsx index c7b50ac..78314ae 100644 --- a/web/src/app/(user)/image/page.tsx +++ b/web/src/pages/image/index.tsx @@ -1,5 +1,3 @@ -"use client"; - import { ArrowLeft, ArrowRight, BookOpen, CheckSquare, ClipboardPaste, Download, FolderPlus, History, ImagePlus, LoaderCircle, PenLine, Plus, SlidersHorizontal, Sparkles, Trash2, Upload } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { App, Button, Checkbox, Drawer, Empty, Image, Input, Modal, Tag, Tooltip, Typography } from "antd"; @@ -9,7 +7,7 @@ import { saveAs } from "file-saver"; import { ImageSettingsPanel } from "@/components/image-settings-panel"; import { ModelPicker } from "@/components/model-picker"; import { PromptSelectDialog } from "@/components/prompts/prompt-select-dialog"; -import { AssetPickerModal, type InsertAssetPayload } from "@/app/(user)/canvas/components/asset-picker-modal"; +import { AssetPickerModal, type InsertAssetPayload } from "@/components/canvas/asset-picker-modal"; import { canvasThemes } from "@/lib/canvas-theme"; import { imageReferenceLabel } from "@/lib/image-reference-prompt"; import { modelOptionLabel, useConfigStore, useEffectiveConfig, type AiConfig } from "@/stores/use-config-store"; diff --git a/web/src/app/not-found.tsx b/web/src/pages/not-found/index.tsx similarity index 100% rename from web/src/app/not-found.tsx rename to web/src/pages/not-found/index.tsx diff --git a/web/src/components/prompts/prompt-detail-dialog.tsx b/web/src/pages/prompts/components/prompt-detail-dialog.tsx similarity index 99% rename from web/src/components/prompts/prompt-detail-dialog.tsx rename to web/src/pages/prompts/components/prompt-detail-dialog.tsx index e32501f..b1bda43 100644 --- a/web/src/components/prompts/prompt-detail-dialog.tsx +++ b/web/src/pages/prompts/components/prompt-detail-dialog.tsx @@ -1,5 +1,3 @@ -"use client"; - import { Copy, FolderPlus } from "lucide-react"; import { Button, Modal, Space, Tag } from "antd"; diff --git a/web/src/app/(user)/prompts/page.tsx b/web/src/pages/prompts/index.tsx similarity index 98% rename from web/src/app/(user)/prompts/page.tsx rename to web/src/pages/prompts/index.tsx index 4d511ef..04a5f28 100644 --- a/web/src/app/(user)/prompts/page.tsx +++ b/web/src/pages/prompts/index.tsx @@ -1,12 +1,10 @@ -"use client"; - import { FolderPlus, Search } from "lucide-react"; import { type UIEvent, useEffect, useState } from "react"; import { App, Button, Empty, Input, Spin, Tag } from "antd"; import { PromptCard } from "@/components/prompts/prompt-card"; -import { PromptDetailDialog } from "@/components/prompts/prompt-detail-dialog"; import { usePromptList } from "@/components/prompts/use-prompt-list"; +import { PromptDetailDialog } from "./components/prompt-detail-dialog"; import { useCopyText } from "@/hooks/use-copy-text"; import { cn } from "@/lib/utils"; import { useAssetStore } from "@/stores/use-asset-store"; diff --git a/web/src/app/(user)/video/page.tsx b/web/src/pages/video/index.tsx similarity index 99% rename from web/src/app/(user)/video/page.tsx rename to web/src/pages/video/index.tsx index 1a07bb0..f896f27 100644 --- a/web/src/app/(user)/video/page.tsx +++ b/web/src/pages/video/index.tsx @@ -1,5 +1,3 @@ -"use client"; - import { ArrowLeft, ArrowRight, BookOpen, CheckSquare, ClipboardPaste, Download, FolderPlus, History, LoaderCircle, Music2, Plus, SlidersHorizontal, Sparkles, Trash2, Upload, VideoIcon } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { App, Button, Checkbox, Drawer, Empty, Input, Modal, Tag, Typography } from "antd"; @@ -7,7 +5,7 @@ import localforage from "localforage"; import { nanoid } from "nanoid"; import { saveAs } from "file-saver"; -import { AssetPickerModal, type InsertAssetPayload } from "@/app/(user)/canvas/components/asset-picker-modal"; +import { AssetPickerModal, type InsertAssetPayload } from "@/components/canvas/asset-picker-modal"; import { ModelPicker } from "@/components/model-picker"; import { PromptSelectDialog } from "@/components/prompts/prompt-select-dialog"; import { VideoSettingsPanel, normalizeVideoResolutionValue, normalizeVideoSizeValue, videoSizeLabel } from "@/components/video-settings-panel"; diff --git a/web/src/router.tsx b/web/src/router.tsx index 82e742e..dc00819 100644 --- a/web/src/router.tsx +++ b/web/src/router.tsx @@ -1,14 +1,14 @@ import { createBrowserRouter, Outlet } from "react-router-dom"; -import NotFound from "@/app/not-found"; -import UserLayout from "@/app/(user)/layout"; -import IndexPage from "@/app/(user)/page"; -import ImagePage from "@/app/(user)/image/page"; -import VideoPage from "@/app/(user)/video/page"; -import AssetsPage from "@/app/(user)/assets/page"; -import PromptsPage from "@/app/(user)/prompts/page"; -import CanvasPage from "@/app/(user)/canvas/page"; -import CanvasProjectPage from "@/app/(user)/canvas/[id]/page"; +import UserLayout from "@/layouts/user-layout"; +import AssetsPage from "@/pages/assets"; +import CanvasPage from "@/pages/canvas"; +import CanvasProjectPage from "@/pages/canvas/project"; +import HomePage from "@/pages/home"; +import ImagePage from "@/pages/image"; +import NotFound from "@/pages/not-found"; +import PromptsPage from "@/pages/prompts"; +import VideoPage from "@/pages/video"; export const router = createBrowserRouter([ { @@ -18,7 +18,7 @@ export const router = createBrowserRouter([ ), children: [ - { path: "/", element: }, + { path: "/", element: }, { path: "/image", element: }, { path: "/video", element: }, { path: "/assets", element: }, diff --git a/web/src/services/api/prompts.ts b/web/src/services/api/prompts.ts index 25bb039..62e658d 100644 --- a/web/src/services/api/prompts.ts +++ b/web/src/services/api/prompts.ts @@ -1,5 +1,3 @@ -"use client"; - import localforage from "localforage"; export type Prompt = { diff --git a/web/src/services/app-sync.ts b/web/src/services/app-sync.ts index 1f4a976..e08f569 100644 --- a/web/src/services/app-sync.ts +++ b/web/src/services/app-sync.ts @@ -1,5 +1,3 @@ -"use client"; - import localforage from "localforage"; import { getMediaBlob, resolveMediaUrl, setMediaBlob } from "@/services/file-storage"; @@ -8,8 +6,8 @@ import { downloadWebdavFile, uploadWebdavFile, WEBDAV_MANIFEST_FILE_NAME } from import type { Asset } from "@/stores/use-asset-store"; import { useAssetStore } from "@/stores/use-asset-store"; import type { WebdavSyncConfig } from "@/stores/use-config-store"; -import type { CanvasProject } from "@/app/(user)/canvas/stores/use-canvas-store"; -import { useCanvasStore } from "@/app/(user)/canvas/stores/use-canvas-store"; +import type { CanvasProject } from "@/stores/canvas/use-canvas-store"; +import { useCanvasStore } from "@/stores/canvas/use-canvas-store"; type StoredLog = Record & { id?: string }; export type AppSyncDomainKey = "canvas" | "assets" | "image-workbench" | "video-workbench"; diff --git a/web/src/services/file-storage.ts b/web/src/services/file-storage.ts index 60ee07a..fce89d4 100644 --- a/web/src/services/file-storage.ts +++ b/web/src/services/file-storage.ts @@ -1,5 +1,3 @@ -"use client"; - import localforage from "localforage"; import { nanoid } from "nanoid"; diff --git a/web/src/services/image-storage.ts b/web/src/services/image-storage.ts index 6729198..7e3079f 100644 --- a/web/src/services/image-storage.ts +++ b/web/src/services/image-storage.ts @@ -1,5 +1,3 @@ -"use client"; - import localforage from "localforage"; import { nanoid } from "nanoid"; diff --git a/web/src/services/webdav-sync.ts b/web/src/services/webdav-sync.ts index dc6dda8..166a963 100644 --- a/web/src/services/webdav-sync.ts +++ b/web/src/services/webdav-sync.ts @@ -1,5 +1,3 @@ -"use client"; - import type { WebdavSyncConfig } from "@/stores/use-config-store"; export const WEBDAV_MANIFEST_FILE_NAME = "manifest.json"; diff --git a/web/src/app/(user)/canvas/stores/use-canvas-agent-store.ts b/web/src/stores/canvas/use-canvas-agent-store.ts similarity index 97% rename from web/src/app/(user)/canvas/stores/use-canvas-agent-store.ts rename to web/src/stores/canvas/use-canvas-agent-store.ts index ed9b022..54bba90 100644 --- a/web/src/app/(user)/canvas/stores/use-canvas-agent-store.ts +++ b/web/src/stores/canvas/use-canvas-agent-store.ts @@ -1,6 +1,6 @@ import { create } from "zustand"; -import type { CanvasAgentOp } from "../utils/canvas-agent-ops"; +import type { CanvasAgentOp } from "@/lib/canvas/canvas-agent-ops"; export type AgentChatRole = "user" | "assistant" | "system" | "tool" | "error"; export type AgentAttachment = { id: string; name: string; type: string; size: number; url: string; dataUrl: string }; diff --git a/web/src/app/(user)/canvas/stores/use-canvas-store.ts b/web/src/stores/canvas/use-canvas-store.ts similarity index 99% rename from web/src/app/(user)/canvas/stores/use-canvas-store.ts rename to web/src/stores/canvas/use-canvas-store.ts index 1a17590..412d236 100644 --- a/web/src/app/(user)/canvas/stores/use-canvas-store.ts +++ b/web/src/stores/canvas/use-canvas-store.ts @@ -4,7 +4,7 @@ import { persist, type PersistStorage, type StorageValue } from "zustand/middlew import { nanoid } from "nanoid"; import { localForageStorage } from "@/lib/localforage-storage"; import type { CanvasBackgroundMode } from "@/lib/canvas-theme"; -import type { CanvasAssistantSession, CanvasConnection, CanvasNodeData, ViewportTransform } from "../types"; +import type { CanvasAssistantSession, CanvasConnection, CanvasNodeData, ViewportTransform } from "@/types/canvas"; export type CanvasProject = { id: string; diff --git a/web/src/app/(user)/canvas/stores/use-canvas-ui-store.ts b/web/src/stores/canvas/use-canvas-ui-store.ts similarity index 100% rename from web/src/app/(user)/canvas/stores/use-canvas-ui-store.ts rename to web/src/stores/canvas/use-canvas-ui-store.ts diff --git a/web/src/stores/use-asset-store.ts b/web/src/stores/use-asset-store.ts index e643637..12ddf1e 100644 --- a/web/src/stores/use-asset-store.ts +++ b/web/src/stores/use-asset-store.ts @@ -1,5 +1,3 @@ -"use client"; - import { create } from "zustand"; import { persist, type PersistStorage, type StorageValue } from "zustand/middleware"; @@ -89,7 +87,7 @@ export const useAssetStore = create()( replaceAssets: (assets) => set({ assets }), cleanupImages: (extra) => { window.setTimeout(async () => { - const { useCanvasStore } = await import("@/app/(user)/canvas/stores/use-canvas-store"); + const { useCanvasStore } = await import("@/stores/canvas/use-canvas-store"); await cleanupUnusedImages({ assets: get().assets, projects: useCanvasStore.getState().projects, extra }); await cleanupUnusedMedia({ assets: get().assets, projects: useCanvasStore.getState().projects, extra }); }, 0); diff --git a/web/src/stores/use-config-store.ts b/web/src/stores/use-config-store.ts index 981f45c..ca9d510 100644 --- a/web/src/stores/use-config-store.ts +++ b/web/src/stores/use-config-store.ts @@ -1,5 +1,3 @@ -"use client"; - import { useMemo } from "react"; import { create } from "zustand"; import { persist } from "zustand/middleware"; diff --git a/web/src/stores/use-user-store.ts b/web/src/stores/use-user-store.ts index bdf3ec2..46f19af 100644 --- a/web/src/stores/use-user-store.ts +++ b/web/src/stores/use-user-store.ts @@ -1,5 +1,3 @@ -"use client"; - import { create } from "zustand"; export type LocalUser = { diff --git a/web/src/app/globals.css b/web/src/styles/globals.css similarity index 100% rename from web/src/app/globals.css rename to web/src/styles/globals.css diff --git a/web/src/app/(user)/canvas/export-types.ts b/web/src/types/canvas-export.ts similarity index 83% rename from web/src/app/(user)/canvas/export-types.ts rename to web/src/types/canvas-export.ts index e48596e..1df7d55 100644 --- a/web/src/app/(user)/canvas/export-types.ts +++ b/web/src/types/canvas-export.ts @@ -1,4 +1,4 @@ -import type { CanvasProject } from "./stores/use-canvas-store"; +import type { CanvasProject } from "@/stores/canvas/use-canvas-store"; export type CanvasExportFile = { app: "infinite-canvas"; diff --git a/web/src/app/(user)/canvas/types.ts b/web/src/types/canvas.ts similarity index 100% rename from web/src/app/(user)/canvas/types.ts rename to web/src/types/canvas.ts