claude-code-workflow 7.2.15 → 7.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (526) hide show
  1. package/.ccw/workflows/cli-templates/schemas/team-tasks-schema.json +255 -0
  2. package/.codex/agents/team-supervisor.toml +39 -0
  3. package/.codex/agents/team-worker.toml +46 -0
  4. package/.codex/skills/team-arch-opt/SKILL.md +151 -698
  5. package/.codex/skills/team-arch-opt/roles/analyzer/role.md +78 -0
  6. package/.codex/skills/team-arch-opt/roles/coordinator/commands/analyze.md +57 -0
  7. package/.codex/skills/team-arch-opt/roles/coordinator/commands/dispatch.md +287 -0
  8. package/.codex/skills/team-arch-opt/roles/coordinator/commands/monitor.md +204 -0
  9. package/.codex/skills/team-arch-opt/roles/coordinator/role.md +162 -0
  10. package/.codex/skills/team-arch-opt/roles/designer/role.md +115 -0
  11. package/.codex/skills/team-arch-opt/roles/refactorer/role.md +102 -0
  12. package/.codex/skills/team-arch-opt/roles/reviewer/role.md +111 -0
  13. package/.codex/skills/team-arch-opt/roles/validator/role.md +115 -0
  14. package/.codex/skills/team-arch-opt/specs/pipelines.md +102 -0
  15. package/.codex/skills/team-arch-opt/specs/team-config.json +263 -0
  16. package/.codex/skills/team-brainstorm/SKILL.md +167 -724
  17. package/.codex/skills/team-brainstorm/roles/challenger/role.md +61 -0
  18. package/.codex/skills/team-brainstorm/roles/coordinator/commands/analyze.md +58 -0
  19. package/.codex/skills/team-brainstorm/roles/coordinator/commands/dispatch.md +162 -0
  20. package/.codex/skills/team-brainstorm/roles/coordinator/commands/monitor.md +171 -0
  21. package/.codex/skills/team-brainstorm/roles/coordinator/role.md +140 -0
  22. package/.codex/skills/team-brainstorm/roles/evaluator/role.md +56 -0
  23. package/.codex/skills/team-brainstorm/roles/ideator/role.md +69 -0
  24. package/.codex/skills/team-brainstorm/roles/synthesizer/role.md +57 -0
  25. package/.codex/skills/team-brainstorm/specs/pipelines.md +72 -0
  26. package/.codex/skills/team-brainstorm/specs/team-config.json +86 -0
  27. package/.codex/skills/team-coordinate/SKILL.md +267 -667
  28. package/.codex/skills/team-coordinate/roles/coordinator/commands/analyze-task.md +247 -0
  29. package/.codex/skills/team-coordinate/roles/coordinator/commands/dispatch.md +126 -0
  30. package/.codex/skills/team-coordinate/roles/coordinator/commands/monitor.md +327 -0
  31. package/.codex/skills/team-coordinate/roles/coordinator/role.md +361 -0
  32. package/.codex/skills/team-coordinate/specs/knowledge-transfer.md +111 -0
  33. package/.codex/skills/team-coordinate/specs/pipelines.md +97 -0
  34. package/.codex/skills/team-coordinate/specs/quality-gates.md +112 -0
  35. package/.codex/skills/team-coordinate/specs/role-spec-template.md +192 -0
  36. package/.codex/skills/team-designer/SKILL.md +153 -691
  37. package/.codex/skills/team-designer/phases/01-requirements-analysis.md +250 -0
  38. package/.codex/skills/team-designer/phases/02-scaffold-generation.md +228 -0
  39. package/.codex/skills/team-designer/phases/03-content-generation.md +330 -0
  40. package/.codex/skills/team-designer/phases/04-validation.md +320 -0
  41. package/.codex/skills/team-executor/SKILL.md +191 -515
  42. package/.codex/skills/team-executor/roles/executor/commands/monitor.md +280 -0
  43. package/.codex/skills/team-executor/roles/executor/role.md +170 -0
  44. package/.codex/skills/team-executor/specs/session-schema.md +264 -0
  45. package/.codex/skills/team-frontend/SKILL.md +129 -750
  46. package/.codex/skills/team-frontend/roles/analyst/role.md +92 -0
  47. package/.codex/skills/team-frontend/roles/architect/role.md +86 -0
  48. package/.codex/skills/team-frontend/roles/coordinator/commands/analyze.md +52 -0
  49. package/.codex/skills/team-frontend/roles/coordinator/commands/dispatch.md +151 -0
  50. package/.codex/skills/team-frontend/roles/coordinator/commands/monitor.md +188 -0
  51. package/.codex/skills/team-frontend/roles/coordinator/role.md +157 -0
  52. package/.codex/skills/team-frontend/roles/developer/role.md +93 -0
  53. package/.codex/skills/team-frontend/roles/qa/role.md +79 -0
  54. package/.codex/skills/team-frontend/specs/pipelines.md +76 -0
  55. package/.codex/skills/team-frontend/specs/team-config.json +84 -0
  56. package/.codex/skills/team-frontend-debug/SKILL.md +191 -821
  57. package/.codex/skills/team-frontend-debug/roles/analyzer/role.md +208 -0
  58. package/.codex/skills/team-frontend-debug/roles/coordinator/commands/analyze.md +174 -0
  59. package/.codex/skills/team-frontend-debug/roles/coordinator/commands/dispatch.md +198 -0
  60. package/.codex/skills/team-frontend-debug/roles/coordinator/commands/monitor.md +143 -0
  61. package/.codex/skills/team-frontend-debug/roles/coordinator/role.md +131 -0
  62. package/.codex/skills/team-frontend-debug/roles/fixer/role.md +147 -0
  63. package/.codex/skills/team-frontend-debug/roles/reproducer/role.md +147 -0
  64. package/.codex/skills/team-frontend-debug/roles/tester/role.md +231 -0
  65. package/.codex/skills/team-frontend-debug/roles/verifier/role.md +172 -0
  66. package/.codex/skills/team-frontend-debug/specs/debug-tools.md +215 -0
  67. package/.codex/skills/team-frontend-debug/specs/pipelines.md +94 -0
  68. package/.codex/skills/team-issue/SKILL.md +166 -751
  69. package/.codex/skills/team-issue/roles/coordinator/commands/analyze.md +64 -0
  70. package/.codex/skills/team-issue/roles/coordinator/commands/dispatch.md +273 -0
  71. package/.codex/skills/team-issue/roles/coordinator/commands/monitor.md +194 -0
  72. package/.codex/skills/team-issue/roles/coordinator/role.md +175 -0
  73. package/.codex/skills/team-issue/roles/explorer/role.md +94 -0
  74. package/.codex/skills/team-issue/roles/implementer/role.md +87 -0
  75. package/.codex/skills/team-issue/roles/integrator/role.md +84 -0
  76. package/.codex/skills/team-issue/roles/planner/role.md +81 -0
  77. package/.codex/skills/team-issue/roles/reviewer/role.md +86 -0
  78. package/.codex/skills/team-issue/specs/pipelines.md +124 -0
  79. package/.codex/skills/team-issue/specs/team-config.json +70 -0
  80. package/.codex/skills/team-iterdev/SKILL.md +134 -825
  81. package/.codex/skills/team-iterdev/roles/architect/role.md +65 -0
  82. package/.codex/skills/team-iterdev/roles/coordinator/commands/analyze.md +62 -0
  83. package/.codex/skills/team-iterdev/roles/coordinator/commands/dispatch.md +187 -0
  84. package/.codex/skills/team-iterdev/roles/coordinator/commands/monitor.md +186 -0
  85. package/.codex/skills/team-iterdev/roles/coordinator/role.md +161 -0
  86. package/.codex/skills/team-iterdev/roles/developer/role.md +74 -0
  87. package/.codex/skills/team-iterdev/roles/reviewer/role.md +66 -0
  88. package/.codex/skills/team-iterdev/roles/tester/role.md +88 -0
  89. package/.codex/skills/team-iterdev/specs/pipelines.md +94 -0
  90. package/.codex/skills/team-iterdev/specs/team-config.json +172 -0
  91. package/.codex/skills/team-lifecycle-v4/MIGRATION-PLAN.md +512 -0
  92. package/.codex/skills/team-lifecycle-v4/SKILL.md +166 -723
  93. package/.codex/skills/team-lifecycle-v4/roles/analyst/role.md +104 -0
  94. package/.codex/skills/team-lifecycle-v4/roles/coordinator/commands/analyze.md +56 -0
  95. package/.codex/skills/team-lifecycle-v4/roles/coordinator/commands/dispatch.md +61 -0
  96. package/.codex/skills/team-lifecycle-v4/roles/coordinator/commands/monitor.md +177 -0
  97. package/.codex/skills/team-lifecycle-v4/roles/coordinator/role.md +152 -0
  98. package/.codex/skills/team-lifecycle-v4/roles/executor/commands/fix.md +35 -0
  99. package/.codex/skills/team-lifecycle-v4/roles/executor/commands/implement.md +63 -0
  100. package/.codex/skills/team-lifecycle-v4/roles/executor/role.md +89 -0
  101. package/.codex/skills/team-lifecycle-v4/roles/planner/role.md +108 -0
  102. package/.codex/skills/team-lifecycle-v4/roles/reviewer/commands/review-code.md +57 -0
  103. package/.codex/skills/team-lifecycle-v4/roles/reviewer/commands/review-spec.md +44 -0
  104. package/.codex/skills/team-lifecycle-v4/roles/reviewer/role.md +98 -0
  105. package/.codex/skills/team-lifecycle-v4/roles/supervisor/role.md +210 -0
  106. package/.codex/skills/team-lifecycle-v4/roles/tester/role.md +126 -0
  107. package/.codex/skills/team-lifecycle-v4/roles/writer/role.md +125 -0
  108. package/.codex/skills/team-lifecycle-v4/schemas/tasks-schema.md +82 -160
  109. package/.codex/skills/team-lifecycle-v4/specs/knowledge-transfer.md +136 -0
  110. package/.codex/skills/team-lifecycle-v4/specs/pipelines.md +125 -0
  111. package/.codex/skills/team-lifecycle-v4/specs/quality-gates.md +130 -0
  112. package/.codex/skills/team-perf-opt/SKILL.md +169 -697
  113. package/.codex/skills/team-perf-opt/roles/benchmarker/role.md +89 -0
  114. package/.codex/skills/team-perf-opt/roles/coordinator/commands/analyze.md +61 -0
  115. package/.codex/skills/team-perf-opt/roles/coordinator/commands/dispatch.md +262 -0
  116. package/.codex/skills/team-perf-opt/roles/coordinator/commands/monitor.md +320 -0
  117. package/.codex/skills/team-perf-opt/roles/coordinator/role.md +147 -0
  118. package/.codex/skills/team-perf-opt/roles/optimizer/role.md +97 -0
  119. package/.codex/skills/team-perf-opt/roles/profiler/role.md +73 -0
  120. package/.codex/skills/team-perf-opt/roles/reviewer/role.md +75 -0
  121. package/.codex/skills/team-perf-opt/roles/strategist/role.md +94 -0
  122. package/.codex/skills/team-perf-opt/specs/pipelines.md +65 -0
  123. package/.codex/skills/team-perf-opt/specs/team-config.json +246 -0
  124. package/.codex/skills/team-planex/SKILL.md +103 -477
  125. package/.codex/skills/team-planex/roles/coordinator/commands/analyze.md +52 -0
  126. package/.codex/skills/team-planex/roles/coordinator/commands/dispatch.md +80 -0
  127. package/.codex/skills/team-planex/roles/coordinator/commands/monitor.md +164 -0
  128. package/.codex/skills/team-planex/roles/coordinator/role.md +140 -0
  129. package/.codex/skills/team-planex/roles/executor/role.md +91 -0
  130. package/.codex/skills/team-planex/roles/planner/role.md +112 -0
  131. package/.codex/skills/team-planex/specs/pipelines.md +93 -0
  132. package/.codex/skills/team-quality-assurance/SKILL.md +148 -813
  133. package/.codex/skills/team-quality-assurance/roles/analyst/role.md +80 -0
  134. package/.codex/skills/team-quality-assurance/roles/coordinator/commands/analyze.md +72 -0
  135. package/.codex/skills/team-quality-assurance/roles/coordinator/commands/dispatch.md +108 -0
  136. package/.codex/skills/team-quality-assurance/roles/coordinator/commands/monitor.md +209 -0
  137. package/.codex/skills/team-quality-assurance/roles/coordinator/role.md +143 -0
  138. package/.codex/skills/team-quality-assurance/roles/executor/role.md +66 -0
  139. package/.codex/skills/team-quality-assurance/roles/generator/role.md +68 -0
  140. package/.codex/skills/team-quality-assurance/roles/scout/role.md +67 -0
  141. package/.codex/skills/team-quality-assurance/roles/strategist/role.md +71 -0
  142. package/.codex/skills/team-quality-assurance/specs/pipelines.md +115 -0
  143. package/.codex/skills/team-quality-assurance/specs/team-config.json +131 -0
  144. package/.codex/skills/team-review/SKILL.md +148 -533
  145. package/.codex/skills/team-review/roles/coordinator/commands/analyze.md +71 -0
  146. package/.codex/skills/team-review/roles/coordinator/commands/dispatch.md +90 -0
  147. package/.codex/skills/team-review/roles/coordinator/commands/monitor.md +185 -0
  148. package/.codex/skills/team-review/roles/coordinator/role.md +142 -0
  149. package/.codex/skills/team-review/roles/fixer/role.md +76 -0
  150. package/.codex/skills/team-review/roles/reviewer/role.md +68 -0
  151. package/.codex/skills/team-review/roles/scanner/role.md +71 -0
  152. package/.codex/skills/team-review/specs/dimensions.md +82 -0
  153. package/.codex/skills/team-review/specs/finding-schema.json +82 -0
  154. package/.codex/skills/team-review/specs/pipelines.md +102 -0
  155. package/.codex/skills/team-review/specs/team-config.json +27 -0
  156. package/.codex/skills/team-roadmap-dev/SKILL.md +162 -683
  157. package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/analyze.md +61 -0
  158. package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/dispatch.md +241 -0
  159. package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/monitor.md +468 -0
  160. package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/pause.md +90 -0
  161. package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/resume.md +137 -0
  162. package/.codex/skills/team-roadmap-dev/roles/coordinator/commands/roadmap-discuss.md +243 -0
  163. package/.codex/skills/team-roadmap-dev/roles/coordinator/role.md +303 -0
  164. package/.codex/skills/team-roadmap-dev/roles/executor/role.md +71 -0
  165. package/.codex/skills/team-roadmap-dev/roles/planner/role.md +76 -0
  166. package/.codex/skills/team-roadmap-dev/roles/verifier/role.md +74 -0
  167. package/.codex/skills/team-roadmap-dev/specs/pipelines.md +93 -0
  168. package/.codex/skills/team-roadmap-dev/specs/team-config.json +95 -0
  169. package/.codex/skills/team-tech-debt/SKILL.md +129 -708
  170. package/.codex/skills/team-tech-debt/roles/assessor/role.md +69 -0
  171. package/.codex/skills/team-tech-debt/roles/coordinator/commands/analyze.md +47 -0
  172. package/.codex/skills/team-tech-debt/roles/coordinator/commands/dispatch.md +163 -0
  173. package/.codex/skills/team-tech-debt/roles/coordinator/commands/monitor.md +231 -0
  174. package/.codex/skills/team-tech-debt/roles/coordinator/role.md +141 -0
  175. package/.codex/skills/team-tech-debt/roles/executor/role.md +76 -0
  176. package/.codex/skills/team-tech-debt/roles/planner/role.md +69 -0
  177. package/.codex/skills/team-tech-debt/roles/scanner/role.md +82 -0
  178. package/.codex/skills/team-tech-debt/roles/validator/role.md +75 -0
  179. package/.codex/skills/team-tech-debt/specs/pipelines.md +47 -0
  180. package/.codex/skills/team-tech-debt/specs/team-config.json +129 -0
  181. package/.codex/skills/team-testing/SKILL.md +144 -769
  182. package/.codex/skills/team-testing/roles/analyst/role.md +95 -0
  183. package/.codex/skills/team-testing/roles/coordinator/commands/analyze.md +70 -0
  184. package/.codex/skills/team-testing/roles/coordinator/commands/dispatch.md +106 -0
  185. package/.codex/skills/team-testing/roles/coordinator/commands/monitor.md +242 -0
  186. package/.codex/skills/team-testing/roles/coordinator/role.md +151 -0
  187. package/.codex/skills/team-testing/roles/executor/role.md +96 -0
  188. package/.codex/skills/team-testing/roles/generator/role.md +95 -0
  189. package/.codex/skills/team-testing/roles/strategist/role.md +83 -0
  190. package/.codex/skills/team-testing/specs/pipelines.md +101 -0
  191. package/.codex/skills/team-testing/specs/team-config.json +93 -0
  192. package/.codex/skills/team-uidesign/SKILL.md +133 -767
  193. package/.codex/skills/team-uidesign/roles/coordinator/commands/analyze.md +59 -0
  194. package/.codex/skills/team-uidesign/roles/coordinator/commands/dispatch.md +156 -0
  195. package/.codex/skills/team-uidesign/roles/coordinator/commands/monitor.md +194 -0
  196. package/.codex/skills/team-uidesign/roles/coordinator/role.md +179 -0
  197. package/.codex/skills/team-uidesign/roles/designer/role.md +69 -0
  198. package/.codex/skills/team-uidesign/roles/implementer/role.md +72 -0
  199. package/.codex/skills/team-uidesign/roles/researcher/role.md +82 -0
  200. package/.codex/skills/team-uidesign/roles/reviewer/role.md +67 -0
  201. package/.codex/skills/team-uidesign/specs/pipelines.md +76 -0
  202. package/.codex/skills/team-uidesign/specs/team-config.json +107 -0
  203. package/.codex/skills/team-ultra-analyze/SKILL.md +166 -786
  204. package/.codex/skills/team-ultra-analyze/roles/analyst/role.md +90 -0
  205. package/.codex/skills/team-ultra-analyze/roles/coordinator/commands/analyze.md +73 -0
  206. package/.codex/skills/team-ultra-analyze/roles/coordinator/commands/dispatch.md +225 -0
  207. package/.codex/skills/team-ultra-analyze/roles/coordinator/commands/monitor.md +327 -0
  208. package/.codex/skills/team-ultra-analyze/roles/coordinator/role.md +223 -0
  209. package/.codex/skills/team-ultra-analyze/roles/discussant/role.md +104 -0
  210. package/.codex/skills/team-ultra-analyze/roles/explorer/role.md +74 -0
  211. package/.codex/skills/team-ultra-analyze/roles/synthesizer/role.md +78 -0
  212. package/.codex/skills/team-ultra-analyze/specs/pipelines.md +64 -0
  213. package/.codex/skills/team-ultra-analyze/specs/team-config.json +129 -0
  214. package/.codex/skills/team-ux-improve/SKILL.md +142 -638
  215. package/.codex/skills/team-ux-improve/roles/coordinator/commands/analyze.md +62 -0
  216. package/.codex/skills/team-ux-improve/roles/coordinator/commands/dispatch.md +233 -0
  217. package/.codex/skills/team-ux-improve/roles/coordinator/commands/monitor.md +160 -0
  218. package/.codex/skills/team-ux-improve/roles/coordinator/role.md +138 -0
  219. package/.codex/skills/team-ux-improve/roles/designer/role.md +122 -0
  220. package/.codex/skills/team-ux-improve/roles/diagnoser/role.md +93 -0
  221. package/.codex/skills/team-ux-improve/roles/explorer/role.md +77 -0
  222. package/.codex/skills/team-ux-improve/roles/implementer/role.md +102 -0
  223. package/.codex/skills/team-ux-improve/roles/scanner/role.md +93 -0
  224. package/.codex/skills/team-ux-improve/roles/tester/role.md +84 -0
  225. package/.codex/skills/team-ux-improve/specs/pipelines.md +54 -0
  226. package/.codex/skills/team-ux-improve/specs/team-config.json +181 -0
  227. package/.codex/skills/team-ux-improve/wisdom/anti-patterns/common-ux-pitfalls.md +17 -0
  228. package/.codex/skills/team-ux-improve/wisdom/contributions/.gitkeep +0 -0
  229. package/.codex/skills/team-ux-improve/wisdom/patterns/state-management.md +14 -0
  230. package/.codex/skills/team-ux-improve/wisdom/patterns/ui-feedback.md +16 -0
  231. package/.codex/skills/team-ux-improve/wisdom/principles/general-ux.md +16 -0
  232. package/ccw/dist/core/routes/cli-settings-routes.d.ts.map +1 -1
  233. package/ccw/dist/core/routes/cli-settings-routes.js +135 -133
  234. package/ccw/dist/core/routes/cli-settings-routes.js.map +1 -1
  235. package/ccw/frontend/dist/assets/{AlertDialog-BW9jiZ-p.js → AlertDialog-CnpjWAGm.js} +2 -2
  236. package/ccw/frontend/dist/assets/{AlertDialog-BW9jiZ-p.js.map → AlertDialog-CnpjWAGm.js.map} +1 -1
  237. package/ccw/frontend/dist/assets/{AnalysisPage-ds-w_nVO.js → AnalysisPage-BT2rDDUD.js} +2 -2
  238. package/ccw/frontend/dist/assets/{AnalysisPage-ds-w_nVO.js.map → AnalysisPage-BT2rDDUD.js.map} +1 -1
  239. package/ccw/frontend/dist/assets/{ApiSettingsPage-DlCbXxTz.js → ApiSettingsPage-DGpjiNVu.js} +2 -2
  240. package/ccw/frontend/dist/assets/{ApiSettingsPage-DlCbXxTz.js.map → ApiSettingsPage-DGpjiNVu.js.map} +1 -1
  241. package/ccw/frontend/dist/assets/{CliModeToggle-Dq3nL4fF.js → CliModeToggle-BqUadHn3.js} +2 -2
  242. package/ccw/frontend/dist/assets/{CliModeToggle-Dq3nL4fF.js.map → CliModeToggle-BqUadHn3.js.map} +1 -1
  243. package/ccw/frontend/dist/assets/{CliSessionSharePage-BNDkEE4u.js → CliSessionSharePage-C3AdsDkm.js} +2 -2
  244. package/ccw/frontend/dist/assets/{CliSessionSharePage-BNDkEE4u.js.map → CliSessionSharePage-C3AdsDkm.js.map} +1 -1
  245. package/ccw/frontend/dist/assets/{CliViewerPage-ChM-uNx_.js → CliViewerPage-BZXpgY0N.js} +2 -2
  246. package/ccw/frontend/dist/assets/{CliViewerPage-ChM-uNx_.js.map → CliViewerPage-BZXpgY0N.js.map} +1 -1
  247. package/ccw/frontend/dist/assets/{CodexLensPage-DOcsYNQk.js → CodexLensPage-CePoJz-u.js} +2 -2
  248. package/ccw/frontend/dist/assets/{CodexLensPage-DOcsYNQk.js.map → CodexLensPage-CePoJz-u.js.map} +1 -1
  249. package/ccw/frontend/dist/assets/{Collapsible-CRNbykXN.js → Collapsible-DXVzWwmb.js} +2 -2
  250. package/ccw/frontend/dist/assets/{Collapsible-CRNbykXN.js.map → Collapsible-DXVzWwmb.js.map} +1 -1
  251. package/ccw/frontend/dist/assets/{CommandsManagerPage-C2JWcemF.js → CommandsManagerPage-B6wJYF0z.js} +2 -2
  252. package/ccw/frontend/dist/assets/{CommandsManagerPage-C2JWcemF.js.map → CommandsManagerPage-B6wJYF0z.js.map} +1 -1
  253. package/ccw/frontend/dist/assets/{DeepWikiPage-CvleOtJy.js → DeepWikiPage-D55fcvSk.js} +2 -2
  254. package/ccw/frontend/dist/assets/{DeepWikiPage-CvleOtJy.js.map → DeepWikiPage-D55fcvSk.js.map} +1 -1
  255. package/ccw/frontend/dist/assets/{EndpointsPage-CMOWQG64.js → EndpointsPage-DcGziJ5t.js} +2 -2
  256. package/ccw/frontend/dist/assets/{EndpointsPage-CMOWQG64.js.map → EndpointsPage-DcGziJ5t.js.map} +1 -1
  257. package/ccw/frontend/dist/assets/{ExplorerPage-DaFPRlNo.js → ExplorerPage-C4eKzn7F.js} +2 -2
  258. package/ccw/frontend/dist/assets/{ExplorerPage-DaFPRlNo.js.map → ExplorerPage-C4eKzn7F.js.map} +1 -1
  259. package/ccw/frontend/dist/assets/{FixSessionPage-CC4p04Az.js → FixSessionPage-BUHh954A.js} +2 -2
  260. package/ccw/frontend/dist/assets/{FixSessionPage-CC4p04Az.js.map → FixSessionPage-BUHh954A.js.map} +1 -1
  261. package/ccw/frontend/dist/assets/{FloatingFileBrowser-DROn1xZ5.js → FloatingFileBrowser-C3GF_u1C.js} +2 -2
  262. package/ccw/frontend/dist/assets/{FloatingFileBrowser-DROn1xZ5.js.map → FloatingFileBrowser-C3GF_u1C.js.map} +1 -1
  263. package/ccw/frontend/dist/assets/{FloatingPanel-CmL_yhDv.js → FloatingPanel-Cn-q9PyJ.js} +2 -2
  264. package/ccw/frontend/dist/assets/{FloatingPanel-CmL_yhDv.js.map → FloatingPanel-Cn-q9PyJ.js.map} +1 -1
  265. package/ccw/frontend/dist/assets/{GraphExplorerPage-DCV5ybKE.js → GraphExplorerPage-DIpqgvoU.js} +2 -2
  266. package/ccw/frontend/dist/assets/{GraphExplorerPage-DCV5ybKE.js.map → GraphExplorerPage-DIpqgvoU.js.map} +1 -1
  267. package/ccw/frontend/dist/assets/{HistoryPage-D0fYQZgc.js → HistoryPage-DzSvEAFe.js} +2 -2
  268. package/ccw/frontend/dist/assets/{HistoryPage-D0fYQZgc.js.map → HistoryPage-DzSvEAFe.js.map} +1 -1
  269. package/ccw/frontend/dist/assets/{HookManagerPage-D2FuJfsM.js → HookManagerPage-C6LDhWrH.js} +2 -2
  270. package/ccw/frontend/dist/assets/{HookManagerPage-D2FuJfsM.js.map → HookManagerPage-C6LDhWrH.js.map} +1 -1
  271. package/ccw/frontend/dist/assets/{InstallationsPage-tjklillZ.js → InstallationsPage-D9ct9xFV.js} +2 -2
  272. package/ccw/frontend/dist/assets/{InstallationsPage-tjklillZ.js.map → InstallationsPage-D9ct9xFV.js.map} +1 -1
  273. package/ccw/frontend/dist/assets/{IssueHubPage-E4JVrhO1.js → IssueHubPage-CXgDC8pS.js} +2 -2
  274. package/ccw/frontend/dist/assets/{IssueHubPage-E4JVrhO1.js.map → IssueHubPage-CXgDC8pS.js.map} +1 -1
  275. package/ccw/frontend/dist/assets/{LiteTasksPage-aJuRoyLt.js → LiteTasksPage-DMkauCwG.js} +2 -2
  276. package/ccw/frontend/dist/assets/{LiteTasksPage-aJuRoyLt.js.map → LiteTasksPage-DMkauCwG.js.map} +1 -1
  277. package/ccw/frontend/dist/assets/{McpManagerPage-BJeuWJv1.js → McpManagerPage-DhLDydgc.js} +2 -2
  278. package/ccw/frontend/dist/assets/{McpManagerPage-BJeuWJv1.js.map → McpManagerPage-DhLDydgc.js.map} +1 -1
  279. package/ccw/frontend/dist/assets/{MemoryPage-BI4FAXhs.js → MemoryPage-Be3nhq40.js} +2 -2
  280. package/ccw/frontend/dist/assets/{MemoryPage-BI4FAXhs.js.map → MemoryPage-Be3nhq40.js.map} +1 -1
  281. package/ccw/frontend/dist/assets/{NotFoundPage-DD2svchp.js → NotFoundPage-0yGnCePd.js} +2 -2
  282. package/ccw/frontend/dist/assets/{NotFoundPage-DD2svchp.js.map → NotFoundPage-0yGnCePd.js.map} +1 -1
  283. package/ccw/frontend/dist/assets/{OrchestratorPage-FC__7yYa.js → OrchestratorPage-_SmXZcGl.js} +2 -2
  284. package/ccw/frontend/dist/assets/{OrchestratorPage-FC__7yYa.js.map → OrchestratorPage-_SmXZcGl.js.map} +1 -1
  285. package/ccw/frontend/dist/assets/{ProjectOverviewPage-DBB_-FzV.js → ProjectOverviewPage-BeXTMsdo.js} +2 -2
  286. package/ccw/frontend/dist/assets/{ProjectOverviewPage-DBB_-FzV.js.map → ProjectOverviewPage-BeXTMsdo.js.map} +1 -1
  287. package/ccw/frontend/dist/assets/{PromptHistoryPage-BwOAvCH8.js → PromptHistoryPage-DS6ycuAv.js} +2 -2
  288. package/ccw/frontend/dist/assets/{PromptHistoryPage-BwOAvCH8.js.map → PromptHistoryPage-DS6ycuAv.js.map} +1 -1
  289. package/ccw/frontend/dist/assets/{ReviewSessionPage-Dd1-g_gp.js → ReviewSessionPage-BoqyjhPo.js} +2 -2
  290. package/ccw/frontend/dist/assets/{ReviewSessionPage-Dd1-g_gp.js.map → ReviewSessionPage-BoqyjhPo.js.map} +1 -1
  291. package/ccw/frontend/dist/assets/{RulesManagerPage-B3RGdsKD.js → RulesManagerPage-DMAwkKlc.js} +2 -2
  292. package/ccw/frontend/dist/assets/{RulesManagerPage-B3RGdsKD.js.map → RulesManagerPage-DMAwkKlc.js.map} +1 -1
  293. package/ccw/frontend/dist/assets/{SessionDetailPage-DM-W5R8K.js → SessionDetailPage-BgJRHIF4.js} +2 -2
  294. package/ccw/frontend/dist/assets/{SessionDetailPage-DM-W5R8K.js.map → SessionDetailPage-BgJRHIF4.js.map} +1 -1
  295. package/ccw/frontend/dist/assets/{SessionsPage-BVz1KCc7.js → SessionsPage-DBPdWlji.js} +2 -2
  296. package/ccw/frontend/dist/assets/{SessionsPage-BVz1KCc7.js.map → SessionsPage-DBPdWlji.js.map} +1 -1
  297. package/ccw/frontend/dist/assets/{SettingsPage-ComW7EZS.js → SettingsPage-BY3QiJhm.js} +4 -4
  298. package/ccw/frontend/dist/assets/{SettingsPage-ComW7EZS.js.map → SettingsPage-BY3QiJhm.js.map} +1 -1
  299. package/ccw/frontend/dist/assets/{SkillsManagerPage-CKom9XwV.js → SkillsManagerPage-DS101Adm.js} +2 -2
  300. package/ccw/frontend/dist/assets/{SkillsManagerPage-CKom9XwV.js.map → SkillsManagerPage-DS101Adm.js.map} +1 -1
  301. package/ccw/frontend/dist/assets/{SpecsSettingsPage-DQz7WP2s.js → SpecsSettingsPage-BcsLu1qq.js} +2 -2
  302. package/ccw/frontend/dist/assets/{SpecsSettingsPage-DQz7WP2s.js.map → SpecsSettingsPage-BcsLu1qq.js.map} +1 -1
  303. package/ccw/frontend/dist/assets/{Switch-BPMdND9H.js → Switch-BL9AmNPC.js} +2 -2
  304. package/ccw/frontend/dist/assets/{Switch-BPMdND9H.js.map → Switch-BL9AmNPC.js.map} +1 -1
  305. package/ccw/frontend/dist/assets/{TabsNavigation-qqt70VYL.js → TabsNavigation-BUcjsLeE.js} +2 -2
  306. package/ccw/frontend/dist/assets/{TabsNavigation-qqt70VYL.js.map → TabsNavigation-BUcjsLeE.js.map} +1 -1
  307. package/ccw/frontend/dist/assets/{TaskDrawer-BqK_qiHX.js → TaskDrawer-BNvfS6dq.js} +2 -2
  308. package/ccw/frontend/dist/assets/{TaskDrawer-BqK_qiHX.js.map → TaskDrawer-BNvfS6dq.js.map} +1 -1
  309. package/ccw/frontend/dist/assets/{TeamPage-u5_i0Rgh.js → TeamPage-CT-zNCrF.js} +2 -2
  310. package/ccw/frontend/dist/assets/{TeamPage-u5_i0Rgh.js.map → TeamPage-CT-zNCrF.js.map} +1 -1
  311. package/ccw/frontend/dist/assets/{TerminalDashboardPage-rUtC9e40.js → TerminalDashboardPage-DfZFGs8g.js} +2 -2
  312. package/ccw/frontend/dist/assets/{TerminalDashboardPage-rUtC9e40.js.map → TerminalDashboardPage-DfZFGs8g.js.map} +1 -1
  313. package/ccw/frontend/dist/assets/{archive-C3u8YNQF.js → archive-Cev1SaQq.js} +2 -2
  314. package/ccw/frontend/dist/assets/{archive-C3u8YNQF.js.map → archive-Cev1SaQq.js.map} +1 -1
  315. package/ccw/frontend/dist/assets/{archive-restore-DfQ998g5.js → archive-restore-BIVluaHZ.js} +2 -2
  316. package/ccw/frontend/dist/assets/{archive-restore-DfQ998g5.js.map → archive-restore-BIVluaHZ.js.map} +1 -1
  317. package/ccw/frontend/dist/assets/{arrow-right-BshJM9Po.js → arrow-right-DrivbS5j.js} +2 -2
  318. package/ccw/frontend/dist/assets/{arrow-right-BshJM9Po.js.map → arrow-right-DrivbS5j.js.map} +1 -1
  319. package/ccw/frontend/dist/assets/{bookmark-plus-D03qJyOZ.js → bookmark-plus-DKyzL0Xg.js} +2 -2
  320. package/ccw/frontend/dist/assets/{bookmark-plus-D03qJyOZ.js.map → bookmark-plus-DKyzL0Xg.js.map} +1 -1
  321. package/ccw/frontend/dist/assets/{bot-CyzWuwq0.js → bot-GBUkPAe3.js} +2 -2
  322. package/ccw/frontend/dist/assets/{bot-CyzWuwq0.js.map → bot-GBUkPAe3.js.map} +1 -1
  323. package/ccw/frontend/dist/assets/{braces-BPgtyjsG.js → braces-BWhm2c4g.js} +2 -2
  324. package/ccw/frontend/dist/assets/{braces-BPgtyjsG.js.map → braces-BWhm2c4g.js.map} +1 -1
  325. package/ccw/frontend/dist/assets/{circle-stop-Dix1AOmw.js → circle-stop-CBcZSKNp.js} +2 -2
  326. package/ccw/frontend/dist/assets/{circle-stop-Dix1AOmw.js.map → circle-stop-CBcZSKNp.js.map} +1 -1
  327. package/ccw/frontend/dist/assets/{cpu-CCQ4Q0Zh.js → cpu-CzNmuTZD.js} +2 -2
  328. package/ccw/frontend/dist/assets/{cpu-CCQ4Q0Zh.js.map → cpu-CzNmuTZD.js.map} +1 -1
  329. package/ccw/frontend/dist/assets/{ellipsis-vertical-BpTysg-Y.js → ellipsis-vertical-BoIyQKaI.js} +2 -2
  330. package/ccw/frontend/dist/assets/{ellipsis-vertical-BpTysg-Y.js.map → ellipsis-vertical-BoIyQKaI.js.map} +1 -1
  331. package/ccw/frontend/dist/assets/{eye-DGY1rAZs.js → eye-BqxyhxQq.js} +2 -2
  332. package/ccw/frontend/dist/assets/{eye-DGY1rAZs.js.map → eye-BqxyhxQq.js.map} +1 -1
  333. package/ccw/frontend/dist/assets/{eye-off-D8t3JfWG.js → eye-off-D9dTZP1A.js} +2 -2
  334. package/ccw/frontend/dist/assets/{eye-off-D8t3JfWG.js.map → eye-off-D9dTZP1A.js.map} +1 -1
  335. package/ccw/frontend/dist/assets/{file-json-BAdJb0n8.js → file-json-CLYEUI6e.js} +2 -2
  336. package/ccw/frontend/dist/assets/{file-json-BAdJb0n8.js.map → file-json-CLYEUI6e.js.map} +1 -1
  337. package/ccw/frontend/dist/assets/{file-text-DrJFiOUB.js → file-text-D5j9C5XC.js} +2 -2
  338. package/ccw/frontend/dist/assets/{file-text-DrJFiOUB.js.map → file-text-D5j9C5XC.js.map} +1 -1
  339. package/ccw/frontend/dist/assets/{filter-CKqzYbz7.js → filter-CEUK5jsA.js} +2 -2
  340. package/ccw/frontend/dist/assets/{filter-CKqzYbz7.js.map → filter-CEUK5jsA.js.map} +1 -1
  341. package/ccw/frontend/dist/assets/{folder-CV8511y9.js → folder-BEOY8txM.js} +2 -2
  342. package/ccw/frontend/dist/assets/{folder-CV8511y9.js.map → folder-BEOY8txM.js.map} +1 -1
  343. package/ccw/frontend/dist/assets/{gauge-XKvmu_uU.js → gauge-CbumHmVn.js} +2 -2
  344. package/ccw/frontend/dist/assets/{gauge-XKvmu_uU.js.map → gauge-CbumHmVn.js.map} +1 -1
  345. package/ccw/frontend/dist/assets/{globe-C56cDUzX.js → globe-D8_IB9gV.js} +2 -2
  346. package/ccw/frontend/dist/assets/{globe-C56cDUzX.js.map → globe-D8_IB9gV.js.map} +1 -1
  347. package/ccw/frontend/dist/assets/{grid-3x3-Bya-suFW.js → grid-3x3-BpzWmYF5.js} +2 -2
  348. package/ccw/frontend/dist/assets/{grid-3x3-Bya-suFW.js.map → grid-3x3-BpzWmYF5.js.map} +1 -1
  349. package/ccw/frontend/dist/assets/{hard-drive-CmuTZpsB.js → hard-drive-QIHpGln7.js} +2 -2
  350. package/ccw/frontend/dist/assets/{hard-drive-CmuTZpsB.js.map → hard-drive-QIHpGln7.js.map} +1 -1
  351. package/ccw/frontend/dist/assets/{hash-CRPT_tJQ.js → hash-CP0YRHVs.js} +2 -2
  352. package/ccw/frontend/dist/assets/{hash-CRPT_tJQ.js.map → hash-CP0YRHVs.js.map} +1 -1
  353. package/ccw/frontend/dist/assets/{history-C1pJZQCL.js → history-hOjgVKax.js} +2 -2
  354. package/ccw/frontend/dist/assets/{history-C1pJZQCL.js.map → history-hOjgVKax.js.map} +1 -1
  355. package/ccw/frontend/dist/assets/{index-Dmt9OiEf.js → index-B_ysvdnP.js} +2 -2
  356. package/ccw/frontend/dist/assets/{index-Dmt9OiEf.js.map → index-B_ysvdnP.js.map} +1 -1
  357. package/ccw/frontend/dist/assets/{index-dWT2M6Ef.js → index-C5Oqx2xI.js} +3 -3
  358. package/ccw/frontend/dist/assets/{index-dWT2M6Ef.js.map → index-C5Oqx2xI.js.map} +1 -1
  359. package/ccw/frontend/dist/assets/{index-CI8-rBff.js → index-CJi0bWL-.js} +2 -2
  360. package/ccw/frontend/dist/assets/{index-CI8-rBff.js.map → index-CJi0bWL-.js.map} +1 -1
  361. package/ccw/frontend/dist/assets/{index-anSMmEF8.js → index-CdQpo1x0.js} +2 -2
  362. package/ccw/frontend/dist/assets/{index-anSMmEF8.js.map → index-CdQpo1x0.js.map} +1 -1
  363. package/ccw/frontend/dist/assets/{layout-grid-TSO0BFQE.js → layout-grid-C38fQyLs.js} +2 -2
  364. package/ccw/frontend/dist/assets/{layout-grid-TSO0BFQE.js.map → layout-grid-C38fQyLs.js.map} +1 -1
  365. package/ccw/frontend/dist/assets/{lightbulb-Caj6fIQD.js → lightbulb-CClbCUzu.js} +2 -2
  366. package/ccw/frontend/dist/assets/{lightbulb-Caj6fIQD.js.map → lightbulb-CClbCUzu.js.map} +1 -1
  367. package/ccw/frontend/dist/assets/{link-2-DE9lMxa-.js → link-2-CB-LKbI0.js} +2 -2
  368. package/ccw/frontend/dist/assets/{link-2-DE9lMxa-.js.map → link-2-CB-LKbI0.js.map} +1 -1
  369. package/ccw/frontend/dist/assets/{link-BZtPgLW0.js → link-BK6SBzHS.js} +2 -2
  370. package/ccw/frontend/dist/assets/{link-BZtPgLW0.js.map → link-BK6SBzHS.js.map} +1 -1
  371. package/ccw/frontend/dist/assets/{list-DubWyY-U.js → list-BME_WOA_.js} +2 -2
  372. package/ccw/frontend/dist/assets/{list-DubWyY-U.js.map → list-BME_WOA_.js.map} +1 -1
  373. package/ccw/frontend/dist/assets/{map-pin-DwN_48AF.js → map-pin-ADsnCyjJ.js} +2 -2
  374. package/ccw/frontend/dist/assets/{map-pin-DwN_48AF.js.map → map-pin-ADsnCyjJ.js.map} +1 -1
  375. package/ccw/frontend/dist/assets/{messages-square-bjxvaiM9.js → messages-square-CLflB1Cq.js} +2 -2
  376. package/ccw/frontend/dist/assets/{messages-square-bjxvaiM9.js.map → messages-square-CLflB1Cq.js.map} +1 -1
  377. package/ccw/frontend/dist/assets/{minimize-2-CGfBKD_V.js → minimize-2-B3ZNzfGr.js} +2 -2
  378. package/ccw/frontend/dist/assets/{minimize-2-CGfBKD_V.js.map → minimize-2-B3ZNzfGr.js.map} +1 -1
  379. package/ccw/frontend/dist/assets/{package-nzWY6ilt.js → package-CByPhtMG.js} +2 -2
  380. package/ccw/frontend/dist/assets/{package-nzWY6ilt.js.map → package-CByPhtMG.js.map} +1 -1
  381. package/ccw/frontend/dist/assets/{plug-CiLce49C.js → plug-BggRzPX9.js} +2 -2
  382. package/ccw/frontend/dist/assets/{plug-CiLce49C.js.map → plug-BggRzPX9.js.map} +1 -1
  383. package/ccw/frontend/dist/assets/{power-CFLmB-U9.js → power-CWuxQSJK.js} +2 -2
  384. package/ccw/frontend/dist/assets/{power-CFLmB-U9.js.map → power-CWuxQSJK.js.map} +1 -1
  385. package/ccw/frontend/dist/assets/{save-DuO6OF0C.js → save-BdJ6EX4Q.js} +2 -2
  386. package/ccw/frontend/dist/assets/{save-DuO6OF0C.js.map → save-BdJ6EX4Q.js.map} +1 -1
  387. package/ccw/frontend/dist/assets/{send-CZk9p0mM.js → send-Ce9wuY7Q.js} +2 -2
  388. package/ccw/frontend/dist/assets/{send-CZk9p0mM.js.map → send-Ce9wuY7Q.js.map} +1 -1
  389. package/ccw/frontend/dist/assets/{square-check-big-BY_1YQQg.js → square-check-big-D6jItkfw.js} +2 -2
  390. package/ccw/frontend/dist/assets/{square-check-big-BY_1YQQg.js.map → square-check-big-D6jItkfw.js.map} +1 -1
  391. package/ccw/frontend/dist/assets/{square-pen-CnZgm6g-.js → square-pen-Byxq21zp.js} +2 -2
  392. package/ccw/frontend/dist/assets/{square-pen-CnZgm6g-.js.map → square-pen-Byxq21zp.js.map} +1 -1
  393. package/ccw/frontend/dist/assets/{star-Cn1F0qy7.js → star-Codj9dvK.js} +2 -2
  394. package/ccw/frontend/dist/assets/{star-Cn1F0qy7.js.map → star-Codj9dvK.js.map} +1 -1
  395. package/ccw/frontend/dist/assets/{style-Dxs1iXCV.js → style-4bYpUGcc.js} +2 -2
  396. package/ccw/frontend/dist/assets/{style-Dxs1iXCV.js.map → style-4bYpUGcc.js.map} +1 -1
  397. package/ccw/frontend/dist/assets/{target-Bz1fLRKH.js → target-DKBoDNCn.js} +2 -2
  398. package/ccw/frontend/dist/assets/{target-Bz1fLRKH.js.map → target-DKBoDNCn.js.map} +1 -1
  399. package/ccw/frontend/dist/assets/{test-tube-C6qCYlDr.js → test-tube-DTqZcBtA.js} +2 -2
  400. package/ccw/frontend/dist/assets/{test-tube-C6qCYlDr.js.map → test-tube-DTqZcBtA.js.map} +1 -1
  401. package/ccw/frontend/dist/assets/{upload-C71kd4Qs.js → upload-DlUl-e6b.js} +2 -2
  402. package/ccw/frontend/dist/assets/{upload-C71kd4Qs.js.map → upload-DlUl-e6b.js.map} +1 -1
  403. package/ccw/frontend/dist/assets/{useApiSettings-CqP2BAJ7.js → useApiSettings-D4zhKKT-.js} +2 -2
  404. package/ccw/frontend/dist/assets/{useApiSettings-CqP2BAJ7.js.map → useApiSettings-D4zhKKT-.js.map} +1 -1
  405. package/ccw/frontend/dist/assets/{useCli-PCoPoVeM.js → useCli-D-qDwsAH.js} +2 -2
  406. package/ccw/frontend/dist/assets/{useCli-PCoPoVeM.js.map → useCli-D-qDwsAH.js.map} +1 -1
  407. package/ccw/frontend/dist/assets/{useCommands-3OfPQPw4.js → useCommands-B0sidbbW.js} +2 -2
  408. package/ccw/frontend/dist/assets/{useCommands-3OfPQPw4.js.map → useCommands-B0sidbbW.js.map} +1 -1
  409. package/ccw/frontend/dist/assets/{useDebounce-bXiFhQx9.js → useDebounce-eTtbKevt.js} +2 -2
  410. package/ccw/frontend/dist/assets/{useDebounce-bXiFhQx9.js.map → useDebounce-eTtbKevt.js.map} +1 -1
  411. package/ccw/frontend/dist/assets/{useFileExplorer-DEyUm46_.js → useFileExplorer-MGSK0h33.js} +2 -2
  412. package/ccw/frontend/dist/assets/{useFileExplorer-DEyUm46_.js.map → useFileExplorer-MGSK0h33.js.map} +1 -1
  413. package/ccw/frontend/dist/assets/{useLocale-sXTrdxcJ.js → useLocale-DDNxU7pJ.js} +2 -2
  414. package/ccw/frontend/dist/assets/{useLocale-sXTrdxcJ.js.map → useLocale-DDNxU7pJ.js.map} +1 -1
  415. package/ccw/frontend/dist/assets/{useSkills-D0W0kXYm.js → useSkills-CZCRBtMY.js} +3 -3
  416. package/ccw/frontend/dist/assets/{useSkills-D0W0kXYm.js.map → useSkills-CZCRBtMY.js.map} +1 -1
  417. package/ccw/frontend/dist/assets/{useSystemSettings-DZ-8lZsG.js → useSystemSettings-DfQEFXSD.js} +2 -2
  418. package/ccw/frontend/dist/assets/{useSystemSettings-DZ-8lZsG.js.map → useSystemSettings-DfQEFXSD.js.map} +1 -1
  419. package/ccw/frontend/dist/assets/{wand-sparkles-83GmAYuw.js → wand-sparkles-DCLvfgl1.js} +2 -2
  420. package/ccw/frontend/dist/assets/{wand-sparkles-83GmAYuw.js.map → wand-sparkles-DCLvfgl1.js.map} +1 -1
  421. package/ccw/frontend/dist/index.html +1 -1
  422. package/package.json +1 -1
  423. package/.codex/skills/team-arch-opt/agents/completion-handler.md +0 -138
  424. package/.codex/skills/team-arch-opt/agents/fix-cycle-handler.md +0 -146
  425. package/.codex/skills/team-arch-opt/agents/plan-reviewer.md +0 -150
  426. package/.codex/skills/team-arch-opt/instructions/agent-instruction.md +0 -114
  427. package/.codex/skills/team-arch-opt/schemas/tasks-schema.md +0 -174
  428. package/.codex/skills/team-brainstorm/agents/gc-controller.md +0 -122
  429. package/.codex/skills/team-brainstorm/agents/topic-clarifier.md +0 -126
  430. package/.codex/skills/team-brainstorm/instructions/agent-instruction.md +0 -105
  431. package/.codex/skills/team-brainstorm/schemas/tasks-schema.md +0 -171
  432. package/.codex/skills/team-coordinate/agents/completion-handler.md +0 -127
  433. package/.codex/skills/team-coordinate/agents/plan-reviewer.md +0 -145
  434. package/.codex/skills/team-coordinate/instructions/agent-instruction.md +0 -184
  435. package/.codex/skills/team-coordinate/schemas/tasks-schema.md +0 -165
  436. package/.codex/skills/team-designer/agents/requirement-clarifier.md +0 -247
  437. package/.codex/skills/team-designer/agents/validation-reporter.md +0 -186
  438. package/.codex/skills/team-designer/instructions/agent-instruction.md +0 -163
  439. package/.codex/skills/team-designer/schemas/tasks-schema.md +0 -180
  440. package/.codex/skills/team-executor/instructions/agent-instruction.md +0 -62
  441. package/.codex/skills/team-executor/schemas/tasks-schema.md +0 -141
  442. package/.codex/skills/team-frontend/agents/completion-handler.md +0 -131
  443. package/.codex/skills/team-frontend/agents/qa-gate-reviewer.md +0 -153
  444. package/.codex/skills/team-frontend/instructions/agent-instruction.md +0 -197
  445. package/.codex/skills/team-frontend/schemas/tasks-schema.md +0 -188
  446. package/.codex/skills/team-frontend-debug/agents/completion-handler.md +0 -142
  447. package/.codex/skills/team-frontend-debug/agents/conditional-skip-gate.md +0 -130
  448. package/.codex/skills/team-frontend-debug/agents/iteration-handler.md +0 -120
  449. package/.codex/skills/team-frontend-debug/instructions/agent-instruction.md +0 -272
  450. package/.codex/skills/team-frontend-debug/schemas/tasks-schema.md +0 -198
  451. package/.codex/skills/team-issue/agents/reviewer.md +0 -204
  452. package/.codex/skills/team-issue/instructions/agent-instruction.md +0 -198
  453. package/.codex/skills/team-issue/schemas/tasks-schema.md +0 -198
  454. package/.codex/skills/team-iterdev/agents/gc-controller.md +0 -193
  455. package/.codex/skills/team-iterdev/agents/task-analyzer.md +0 -206
  456. package/.codex/skills/team-iterdev/instructions/agent-instruction.md +0 -118
  457. package/.codex/skills/team-iterdev/schemas/tasks-schema.md +0 -174
  458. package/.codex/skills/team-lifecycle/SKILL.md +0 -906
  459. package/.codex/skills/team-lifecycle/agents/analyst.md +0 -424
  460. package/.codex/skills/team-lifecycle/agents/architect.md +0 -274
  461. package/.codex/skills/team-lifecycle/agents/discuss-agent.md +0 -422
  462. package/.codex/skills/team-lifecycle/agents/executor.md +0 -423
  463. package/.codex/skills/team-lifecycle/agents/explore-agent.md +0 -471
  464. package/.codex/skills/team-lifecycle/agents/fe-developer.md +0 -239
  465. package/.codex/skills/team-lifecycle/agents/fe-qa.md +0 -357
  466. package/.codex/skills/team-lifecycle/agents/planner.md +0 -437
  467. package/.codex/skills/team-lifecycle/agents/reviewer.md +0 -483
  468. package/.codex/skills/team-lifecycle/agents/tester.md +0 -423
  469. package/.codex/skills/team-lifecycle/agents/writer.md +0 -502
  470. package/.codex/skills/team-lifecycle/phases/01-requirement-clarification.md +0 -209
  471. package/.codex/skills/team-lifecycle/phases/02-team-initialization.md +0 -263
  472. package/.codex/skills/team-lifecycle/phases/03-task-chain-creation.md +0 -251
  473. package/.codex/skills/team-lifecycle/phases/04-pipeline-coordination.md +0 -831
  474. package/.codex/skills/team-lifecycle/phases/05-completion-report.md +0 -309
  475. package/.codex/skills/team-lifecycle/specs/document-standards.md +0 -192
  476. package/.codex/skills/team-lifecycle/specs/quality-gates.md +0 -207
  477. package/.codex/skills/team-lifecycle-v4/agents/quality-gate.md +0 -165
  478. package/.codex/skills/team-lifecycle-v4/agents/requirement-clarifier.md +0 -163
  479. package/.codex/skills/team-lifecycle-v4/agents/supervisor.md +0 -182
  480. package/.codex/skills/team-perf-opt/agents/completion-handler.md +0 -141
  481. package/.codex/skills/team-perf-opt/agents/fix-cycle-handler.md +0 -156
  482. package/.codex/skills/team-perf-opt/agents/plan-reviewer.md +0 -150
  483. package/.codex/skills/team-perf-opt/instructions/agent-instruction.md +0 -122
  484. package/.codex/skills/team-perf-opt/schemas/tasks-schema.md +0 -174
  485. package/.codex/skills/team-planex/instructions/agent-instruction.md +0 -301
  486. package/.codex/skills/team-planex/schemas/tasks-schema.md +0 -198
  487. package/.codex/skills/team-planex-v2/SKILL.md +0 -652
  488. package/.codex/skills/team-planex-v2/instructions/agent-instruction.md +0 -193
  489. package/.codex/skills/team-planex-v2/schemas/tasks-schema.md +0 -206
  490. package/.codex/skills/team-quality-assurance/agents/executor.md +0 -192
  491. package/.codex/skills/team-quality-assurance/agents/gc-loop-handler.md +0 -163
  492. package/.codex/skills/team-quality-assurance/instructions/agent-instruction.md +0 -185
  493. package/.codex/skills/team-quality-assurance/schemas/tasks-schema.md +0 -190
  494. package/.codex/skills/team-review/agents/fixer.md +0 -360
  495. package/.codex/skills/team-review/instructions/agent-instruction.md +0 -102
  496. package/.codex/skills/team-review/schemas/tasks-schema.md +0 -143
  497. package/.codex/skills/team-roadmap-dev/agents/roadmap-discusser.md +0 -176
  498. package/.codex/skills/team-roadmap-dev/agents/roadmap-planner.md +0 -194
  499. package/.codex/skills/team-roadmap-dev/agents/roadmap-verifier.md +0 -221
  500. package/.codex/skills/team-roadmap-dev/instructions/executor-instruction.md +0 -55
  501. package/.codex/skills/team-roadmap-dev/schemas/tasks-schema.md +0 -144
  502. package/.codex/skills/team-tech-debt/agents/gc-loop-manager.md +0 -130
  503. package/.codex/skills/team-tech-debt/agents/plan-approver.md +0 -151
  504. package/.codex/skills/team-tech-debt/instructions/agent-instruction.md +0 -390
  505. package/.codex/skills/team-tech-debt/schemas/tasks-schema.md +0 -196
  506. package/.codex/skills/team-testing/agents/executor.md +0 -195
  507. package/.codex/skills/team-testing/agents/gc-loop-handler.md +0 -155
  508. package/.codex/skills/team-testing/instructions/agent-instruction.md +0 -142
  509. package/.codex/skills/team-testing/schemas/tasks-schema.md +0 -172
  510. package/.codex/skills/team-uidesign/agents/completion-handler.md +0 -177
  511. package/.codex/skills/team-uidesign/agents/gc-loop-handler.md +0 -162
  512. package/.codex/skills/team-uidesign/instructions/agent-instruction.md +0 -509
  513. package/.codex/skills/team-uidesign/schemas/tasks-schema.md +0 -187
  514. package/.codex/skills/team-ultra-analyze/agents/discussion-feedback.md +0 -155
  515. package/.codex/skills/team-ultra-analyze/agents/topic-analyzer.md +0 -153
  516. package/.codex/skills/team-ultra-analyze/instructions/agent-instruction.md +0 -169
  517. package/.codex/skills/team-ultra-analyze/schemas/tasks-schema.md +0 -180
  518. package/.codex/skills/team-ux-improve/agents/ux-designer.md +0 -136
  519. package/.codex/skills/team-ux-improve/agents/ux-explorer.md +0 -158
  520. package/.codex/skills/team-ux-improve/agents/ux-tester.md +0 -174
  521. package/.codex/skills/team-ux-improve/instructions/ux-worker-instruction.md +0 -55
  522. package/.codex/skills/team-ux-improve/schemas/tasks-schema.md +0 -87
  523. /package/.codex/skills/{team-lifecycle/templates/architecture-doc.md → team-lifecycle-v4/templates/architecture.md} +0 -0
  524. /package/.codex/skills/{team-lifecycle/templates/epics-template.md → team-lifecycle-v4/templates/epics.md} +0 -0
  525. /package/.codex/skills/{team-lifecycle → team-lifecycle-v4}/templates/product-brief.md +0 -0
  526. /package/.codex/skills/{team-lifecycle/templates/requirements-prd.md → team-lifecycle-v4/templates/requirements.md} +0 -0
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":["BellOff","createLucideIcon","CircleArrowUp","Languages","LayoutPanelLeft","MessageSquareText","Volume2","getCsrfToken","match","searchUnsplash","query","page","perPage","params","response","body","uploadBackgroundImage","file","headers","csrfToken","triggerUnsplashDownload","downloadLocation","useUnsplashSearch","debouncedQuery","setDebouncedQuery","useState","useEffect","timer","useQuery","MODES","BackgroundImagePicker","formatMessage","useIntl","backgroundConfig","setBackgroundMode","setBackgroundImage","updateBackgroundEffect","useTheme","searchQuery","setSearchQuery","setPage","customUrl","setCustomUrl","isUploading","setIsUploading","uploadError","setUploadError","fileInputRef","useRef","data","isLoading","isError","error","showImageControls","handlePhotoSelect","useCallback","photo","handleCustomUrlApply","handleRemoveImage","handleFileUpload","e","_a","result","err","jsxs","jsx","value","labelId","Fragment","p","ThemeSelector","colorScheme","resolvedTheme","customHue","isCustomTheme","gradientLevel","enableHoverGlow","enableBackgroundAnimation","motionPreference","setColorScheme","setTheme","setCustomHue","setGradientLevel","setEnableHoverGlow","setEnableBackgroundAnimation","setMotionPreference","styleTier","setStyleTier","themeSlots","activeSlotId","canAddSlot","setActiveSlot","copySlot","renameSlot","deleteSlot","undoDeleteSlot","exportThemeCode","importThemeCode","setBackgroundConfig","addToast","removeToast","useNotifications","previewHue","setPreviewHue","contrastWarnings","setContrastWarnings","contrastFixes","setContrastFixes","showContrastWarning","setShowContrastWarning","renamingSlotId","setRenamingSlotId","renameValue","setRenameValue","pendingDeleteSlot","setPendingDeleteSlot","renameInputRef","undoToastIdRef","showImportPanel","setShowImportPanel","importCode","setImportCode","importPreview","setImportPreview","importWarning","setImportWarning","importError","setImportError","copyFeedback","setCopyFeedback","mode","getPreviewColor","variable","hslValue","generateThemeFromHue","STYLE_TIERS","getTierPreviewColors","tier","baseVars","tieredVars","applyStyleTier","handleSchemeSelect","scheme","handleCustomSelect","handleHueSave","vars","failures","checkThemeContrast","r","fixes","failure","key","generateContrastFix","handleHueReset","handleModeSelect","newMode","handleKeyDown","nextIndex","COLOR_SCHEMES","s","handleSlotSelect","slotId","handleCopySlot","handleStartRename","currentName","handleConfirmRename","handleCancelRename","handleRenameKeyDown","handleConfirmDelete","toastId","handleCancelDelete","handleCopyThemeCode","code","handleOpenImport","handleCloseImport","handleImportCodeChange","handleApplyImport","DEFAULT_BACKGROUND_CONFIG","getImportPreviewColors","payload","hue","getShareErrorMessageId","errorKey","THEME_SLOT_LIMIT","slot","isActive","isRenaming","preview","isSelected","level","pref","w","fix","i","THEME_MODES","modeOption","getThemeName","previewColors","AlertDialog","AlertDialogContent","AlertDialogHeader","AlertDialogTitle","AlertDialogDescription","AlertDialogFooter","AlertDialogCancel","AlertDialogAction","LANGUAGE_OPTIONS","LanguageSwitcher","compact","className","locale","setLocale","useLocale","Select","SelectTrigger","cn","SelectValue","SelectContent","option","SelectItem","PLATFORM_INFO","EVENT_INFO","getDefaultConfig","PlatformConfigCards","config","expandedPlatform","testing","onToggleExpand","onUpdateConfig","onTest","onSave","saving","platforms","getPlatformIcon","platform","MessageCircle","Send","MessageSquare","Bell","Users","Mail","Link","getPlatformConfig","isConfigured","platformConfig","emailConfig","info","configured","expanded","Card","Badge","Check","Button","X","ChevronUp","ChevronDown","DiscordConfigForm","updates","TelegramConfigForm","FeishuConfigForm","DingTalkConfigForm","WeComConfigForm","EmailConfigForm","WebhookConfigForm","TestTube","onUpdate","showUrl","setShowUrl","Input","EyeOff","Eye","showToken","setShowToken","k","m","showPassword","setShowPassword","t","RemoteNotificationSection","setConfig","loading","setLoading","setSaving","setTesting","setExpandedPlatform","expandedEvent","setExpandedEvent","loadConfig","saveConfig","newConfig","toast","testPlatform","toggleEnabled","updatePlatformConfig","updateEventConfig","eventIndex","newEvents","toggleEventPlatform","eventConfig","allPlatforms","resetConfig","RefreshCw","index","isExpanded","platformInfo","Plus","Save","StyleOption","label","description","selected","onClick","icons","DurationSlider","onChange","disabled","presets","seconds","A2UIPreferencesSection","preferences","updatePreference","resetPreferences","useDialogStyleContext","styleOptions","Label","Sparkles","Clock","v","FilePathInput","placeholder","isValidating","setIsValidating","pathError","setPathError","debouncedValue","useDebounce","timeoutId","handleBrowse","selectFile","__vitePreload","n","initialDir","Loader2","FolderOpen","ENV_FILE_TOOLS","SETTINGS_FILE_TOOLS","getConfigFileType","toolId","CliToolCard","isDefault","toolAvailable","isSaving","onToggleEnabled","onSetDefault","onUpdateModel","onUpdateTags","onUpdateAvailableModels","onUpdateEnvFile","onUpdateSettingsFile","onUpdateEffort","onSaveToBackend","tagInput","setTagInput","modelInput","setModelInput","handleAddTag","newTag","handleRemoveTag","tagToRemove","handleAddModel","newModel","currentModels","handleRemoveModel","modelToRemove","predefinedTags","configFileType","Cpu","tag","predefinedTag","model","effectiveEffort","ResponseLanguageSection","chineseStatus","chineseLoading","useChineseResponseStatus","toggleChinese","chineseToggling","useToggleChineseResponse","windowsStatus","windowsLoading","useWindowsPlatformStatus","toggleWindows","windowsToggling","useToggleWindowsPlatform","cliEnhStatus","cliEnhLoading","useCodexCliEnhancementStatus","toggleCliEnh","cliEnhToggling","useToggleCodexCliEnhancement","refreshCliEnh","refreshing","useRefreshCodexCliEnhancement","doExport","exporting","useExportSettings","doImport","importing","useImportSettings","handleExport","blob","url","a","timestamp","handleFileImport","text","AlertTriangle","Monitor","Terminal","Upload","Download","VersionCheckSection","versionData","setVersionData","checking","setChecking","setError","lastChecked","setLastChecked","autoCheck","setAutoCheck","saved","checkVersion","silent","interval","toggleAutoCheck","enabled","ArrowUpCircle","SystemStatusSection","installations","refetch","useCcwInstallations","upgrade","upgrading","useUpgradeCcwInstallation","ccwInstall","useCcwInstallStatus","Package","inst","isGlobal","installDate","version","Home","Folder","Calendar","File","f","CliToolsWithStatus","cliTools","defaultCliTool","expandedTools","savingTools","toolStatus","useCliToolStatus","status","field","tags","models","envFile","settingsFile","effort","SettingsPage","theme","useConfigStore","selectCliTools","selectDefaultCliTool","userPreferences","selectUserPreferences","updateCliTool","setDefaultCliTool","setUserPreferences","resetUserPreferences","setExpandedTools","setSavingTools","toggleToolExpand","prev","next","handleToggleToolEnabled","handleSetDefaultTool","handleUpdateModel","handleUpdateTags","handleUpdateAvailableModels","availableModels","handleUpdateEnvFile","handleUpdateSettingsFile","handleUpdateEffort","handleSaveToBackend","res","handlePreferenceChange","Settings","Moon","RotateCcw"],"ignoreList":[0,1,2,3,4,5],"sources":["../../../../node_modules/lucide-react/dist/esm/icons/bell-off.js","../../../../node_modules/lucide-react/dist/esm/icons/circle-arrow-up.js","../../../../node_modules/lucide-react/dist/esm/icons/languages.js","../../../../node_modules/lucide-react/dist/esm/icons/layout-panel-left.js","../../../../node_modules/lucide-react/dist/esm/icons/message-square-text.js","../../../../node_modules/lucide-react/dist/esm/icons/volume-2.js","../../src/lib/unsplash.ts","../../src/hooks/useUnsplashSearch.ts","../../src/components/shared/BackgroundImagePicker.tsx","../../src/components/shared/ThemeSelector.tsx","../../src/components/layout/LanguageSwitcher.tsx","../../src/types/remote-notification.ts","../../src/components/settings/PlatformConfigCards.tsx","../../src/components/settings/RemoteNotificationSection.tsx","../../src/components/settings/A2UIPreferencesSection.tsx","../../src/pages/SettingsPage.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst BellOff = createLucideIcon(\"BellOff\", [\n [\"path\", { d: \"M8.7 3A6 6 0 0 1 18 8a21.3 21.3 0 0 0 .6 5\", key: \"o7mx20\" }],\n [\"path\", { d: \"M17 17H3s3-2 3-9a4.67 4.67 0 0 1 .3-1.7\", key: \"16f1lm\" }],\n [\"path\", { d: \"M10.3 21a1.94 1.94 0 0 0 3.4 0\", key: \"qgo35s\" }],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n]);\n\nexport { BellOff as default };\n//# sourceMappingURL=bell-off.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleArrowUp = createLucideIcon(\"CircleArrowUp\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m16 12-4-4-4 4\", key: \"177agl\" }],\n [\"path\", { d: \"M12 16V8\", key: \"1sbj14\" }]\n]);\n\nexport { CircleArrowUp as default };\n//# sourceMappingURL=circle-arrow-up.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Languages = createLucideIcon(\"Languages\", [\n [\"path\", { d: \"m5 8 6 6\", key: \"1wu5hv\" }],\n [\"path\", { d: \"m4 14 6-6 2-3\", key: \"1k1g8d\" }],\n [\"path\", { d: \"M2 5h12\", key: \"or177f\" }],\n [\"path\", { d: \"M7 2h1\", key: \"1t2jsx\" }],\n [\"path\", { d: \"m22 22-5-10-5 10\", key: \"don7ne\" }],\n [\"path\", { d: \"M14 18h6\", key: \"1m8k6r\" }]\n]);\n\nexport { Languages as default };\n//# sourceMappingURL=languages.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutPanelLeft = createLucideIcon(\"LayoutPanelLeft\", [\n [\"rect\", { width: \"7\", height: \"18\", x: \"3\", y: \"3\", rx: \"1\", key: \"2obqm\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"3\", rx: \"1\", key: \"6d4xhi\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"14\", rx: \"1\", key: \"nxv5o0\" }]\n]);\n\nexport { LayoutPanelLeft as default };\n//# sourceMappingURL=layout-panel-left.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst MessageSquareText = createLucideIcon(\"MessageSquareText\", [\n [\"path\", { d: \"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\", key: \"1lielz\" }],\n [\"path\", { d: \"M13 8H7\", key: \"14i4kc\" }],\n [\"path\", { d: \"M17 12H7\", key: \"16if0g\" }]\n]);\n\nexport { MessageSquareText as default };\n//# sourceMappingURL=message-square-text.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Volume2 = createLucideIcon(\"Volume2\", [\n [\n \"path\",\n {\n d: \"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\",\n key: \"uqj9uw\"\n }\n ],\n [\"path\", { d: \"M16 9a5 5 0 0 1 0 6\", key: \"1q6k2b\" }],\n [\"path\", { d: \"M19.364 18.364a9 9 0 0 0 0-12.728\", key: \"ijwkga\" }]\n]);\n\nexport { Volume2 as default };\n//# sourceMappingURL=volume-2.js.map\n","/**\n * Unsplash API Client\n * Frontend functions to search Unsplash via the backend proxy.\n */\n\nexport interface UnsplashPhoto {\n id: string;\n thumbUrl: string;\n smallUrl: string;\n regularUrl: string;\n photographer: string;\n photographerUrl: string;\n photoUrl: string;\n blurHash: string | null;\n downloadLocation: string;\n}\n\nexport interface UnsplashSearchResult {\n photos: UnsplashPhoto[];\n total: number;\n totalPages: number;\n}\n\nfunction getCsrfToken(): string | null {\n const match = document.cookie.match(/XSRF-TOKEN=([^;]+)/);\n return match ? decodeURIComponent(match[1]) : null;\n}\n\n/**\n * Search Unsplash photos via backend proxy.\n */\nexport async function searchUnsplash(\n query: string,\n page = 1,\n perPage = 20\n): Promise<UnsplashSearchResult> {\n const params = new URLSearchParams({\n query,\n page: String(page),\n per_page: String(perPage),\n });\n\n const response = await fetch(`/api/unsplash/search?${params}`, {\n credentials: 'same-origin',\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({}));\n throw new Error(body.error || `Unsplash search failed: ${response.status}`);\n }\n\n return response.json();\n}\n\n/**\n * Upload a local image as background.\n * Sends raw binary to avoid base64 overhead.\n */\nexport async function uploadBackgroundImage(file: File): Promise<{ url: string; filename: string }> {\n const headers: Record<string, string> = {\n 'Content-Type': file.type,\n 'X-Filename': encodeURIComponent(file.name),\n };\n const csrfToken = getCsrfToken();\n if (csrfToken) {\n headers['X-CSRF-Token'] = csrfToken;\n }\n\n const response = await fetch('/api/background/upload', {\n method: 'POST',\n headers,\n credentials: 'same-origin',\n body: file,\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({}));\n throw new Error(body.error || `Upload failed: ${response.status}`);\n }\n\n return response.json();\n}\n\n/**\n * Trigger Unsplash download event (required by API guidelines).\n */\nexport async function triggerUnsplashDownload(downloadLocation: string): Promise<void> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const csrfToken = getCsrfToken();\n if (csrfToken) {\n headers['X-CSRF-Token'] = csrfToken;\n }\n\n await fetch('/api/unsplash/download', {\n method: 'POST',\n headers,\n credentials: 'same-origin',\n body: JSON.stringify({ downloadLocation }),\n });\n}\n","/**\n * React Query hook for searching Unsplash photos with debounce.\n */\nimport { useState, useEffect } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { searchUnsplash } from '@/lib/unsplash';\nimport type { UnsplashSearchResult } from '@/lib/unsplash';\n\nexport function useUnsplashSearch(query: string, page = 1, perPage = 20) {\n const [debouncedQuery, setDebouncedQuery] = useState(query);\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setDebouncedQuery(query);\n }, 500);\n return () => clearTimeout(timer);\n }, [query]);\n\n return useQuery<UnsplashSearchResult>({\n queryKey: ['unsplash-search', debouncedQuery, page, perPage],\n queryFn: () => searchUnsplash(debouncedQuery, page, perPage),\n enabled: debouncedQuery.trim().length > 0,\n staleTime: 5 * 60 * 1000, // 5 minutes\n retry: 1,\n });\n}\n","import { useState, useCallback, useRef } from 'react';\nimport { useIntl } from 'react-intl';\nimport { useTheme } from '@/hooks/useTheme';\nimport { useUnsplashSearch } from '@/hooks/useUnsplashSearch';\nimport { triggerUnsplashDownload, uploadBackgroundImage } from '@/lib/unsplash';\nimport type { UnsplashPhoto } from '@/lib/unsplash';\nimport type { BackgroundMode } from '@/types/store';\n\nconst MODES: { value: BackgroundMode; labelId: string }[] = [\n { value: 'gradient-only', labelId: 'theme.background.mode.gradientOnly' },\n { value: 'image-only', labelId: 'theme.background.mode.imageOnly' },\n { value: 'image-gradient', labelId: 'theme.background.mode.imageGradient' },\n];\n\n/**\n * BackgroundImagePicker Component\n * Allows users to search Unsplash, pick a background image,\n * adjust visual effects, and switch between background modes.\n */\nexport function BackgroundImagePicker() {\n const { formatMessage } = useIntl();\n const {\n backgroundConfig,\n setBackgroundMode,\n setBackgroundImage,\n updateBackgroundEffect,\n } = useTheme();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [page, setPage] = useState(1);\n const [customUrl, setCustomUrl] = useState('');\n const [isUploading, setIsUploading] = useState(false);\n const [uploadError, setUploadError] = useState<string | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const { data, isLoading, isError, error } = useUnsplashSearch(searchQuery, page);\n\n const showImageControls = backgroundConfig.mode !== 'gradient-only';\n\n const handlePhotoSelect = useCallback(async (photo: UnsplashPhoto) => {\n setBackgroundImage(photo.regularUrl, {\n photographerName: photo.photographer,\n photographerUrl: photo.photographerUrl,\n photoUrl: photo.photoUrl,\n });\n // Trigger download event per Unsplash API guidelines\n triggerUnsplashDownload(photo.downloadLocation).catch(() => {});\n }, [setBackgroundImage]);\n\n const handleCustomUrlApply = useCallback(() => {\n if (customUrl.trim()) {\n setBackgroundImage(customUrl.trim(), null);\n setCustomUrl('');\n }\n }, [customUrl, setBackgroundImage]);\n\n const handleRemoveImage = useCallback(() => {\n setBackgroundImage(null, null);\n }, [setBackgroundImage]);\n\n const handleFileUpload = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n // Reset file input so the same file can be re-selected\n e.target.value = '';\n\n setUploadError(null);\n\n if (file.size > 10 * 1024 * 1024) {\n setUploadError(formatMessage({ id: 'theme.background.fileTooLarge' }));\n return;\n }\n\n if (!file.type.startsWith('image/') || !['image/jpeg', 'image/png', 'image/webp', 'image/gif'].includes(file.type)) {\n setUploadError(formatMessage({ id: 'theme.background.invalidType' }));\n return;\n }\n\n setIsUploading(true);\n try {\n const result = await uploadBackgroundImage(file);\n setBackgroundImage(result.url, null);\n } catch (err) {\n setUploadError((err as Error).message || formatMessage({ id: 'theme.background.uploadError' }));\n } finally {\n setIsUploading(false);\n }\n }, [formatMessage, setBackgroundImage]);\n\n return (\n <div className=\"space-y-4\">\n {/* Section title */}\n <h3 className=\"text-sm font-medium text-text\">\n {formatMessage({ id: 'theme.background.title' })}\n </h3>\n\n {/* Background mode selector */}\n <div\n className=\"flex gap-2\"\n role=\"radiogroup\"\n aria-label={formatMessage({ id: 'theme.background.title' })}\n >\n {MODES.map(({ value, labelId }) => (\n <button\n key={value}\n onClick={() => setBackgroundMode(value)}\n role=\"radio\"\n aria-checked={backgroundConfig.mode === value}\n className={`\n flex-1 px-3 py-2 rounded-lg text-xs font-medium\n transition-all duration-200 border-2\n ${backgroundConfig.mode === value\n ? 'border-accent bg-surface shadow-md'\n : 'border-border bg-bg hover:bg-surface'\n }\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\n `}\n >\n {formatMessage({ id: labelId })}\n </button>\n ))}\n </div>\n\n {/* Image selection area */}\n {showImageControls && (\n <div className=\"space-y-3\">\n {/* Current image preview */}\n {backgroundConfig.imageUrl && (\n <div className=\"relative rounded-lg overflow-hidden border border-border\">\n <img\n src={backgroundConfig.imageUrl}\n alt=\"Current background\"\n className=\"w-full h-32 object-cover\"\n />\n <button\n onClick={handleRemoveImage}\n className=\"absolute top-2 right-2 px-2 py-1 text-xs bg-black/60 text-white rounded hover:bg-black/80 transition-colors\"\n >\n {formatMessage({ id: 'theme.background.removeImage' })}\n </button>\n {/* Unsplash attribution */}\n {backgroundConfig.attribution && (\n <div className=\"absolute bottom-0 left-0 right-0 px-2 py-1 bg-black/50 text-white text-xs\">\n Photo by{' '}\n <a\n href={`${backgroundConfig.attribution.photographerUrl}?utm_source=ccw&utm_medium=referral`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline\"\n >\n {backgroundConfig.attribution.photographerName}\n </a>{' '}\n on{' '}\n <a\n href=\"https://unsplash.com/?utm_source=ccw&utm_medium=referral\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline\"\n >\n Unsplash\n </a>\n </div>\n )}\n </div>\n )}\n\n {/* Search box */}\n <input\n type=\"text\"\n value={searchQuery}\n onChange={(e) => { setSearchQuery(e.target.value); setPage(1); }}\n placeholder={formatMessage({ id: 'theme.background.searchPlaceholder' })}\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border bg-bg text-text\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1\"\n />\n\n {/* Photo grid */}\n {isLoading && (\n <div className=\"flex justify-center py-4\">\n <div className=\"w-5 h-5 border-2 border-border border-t-accent rounded-full animate-spin\" />\n </div>\n )}\n\n {isError && (\n <p className=\"text-xs text-destructive py-2\">\n {(error as Error)?.message || formatMessage({ id: 'theme.background.searchError' })}\n </p>\n )}\n\n {data && data.photos.length > 0 && (\n <>\n <div className=\"grid grid-cols-3 gap-2 max-h-60 overflow-y-auto\">\n {data.photos.map((photo) => (\n <button\n key={photo.id}\n onClick={() => handlePhotoSelect(photo)}\n className={`\n relative rounded overflow-hidden border-2 transition-all\n hover:border-accent focus:outline-none focus:ring-2 focus:ring-accent\n ${backgroundConfig.imageUrl === photo.regularUrl\n ? 'border-accent ring-2 ring-accent'\n : 'border-transparent'\n }\n `}\n >\n <img\n src={photo.thumbUrl}\n alt={`Photo by ${photo.photographer}`}\n className=\"w-full h-20 object-cover\"\n loading=\"lazy\"\n />\n </button>\n ))}\n </div>\n\n {/* Pagination */}\n {data.totalPages > 1 && (\n <div className=\"flex items-center justify-between\">\n <button\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n disabled={page <= 1}\n className=\"px-2 py-1 text-xs rounded border border-border disabled:opacity-50 hover:bg-surface\"\n >\n {formatMessage({ id: 'theme.background.prev' })}\n </button>\n <span className=\"text-xs text-text-secondary\">\n {page} / {data.totalPages}\n </span>\n <button\n onClick={() => setPage((p) => Math.min(data.totalPages, p + 1))}\n disabled={page >= data.totalPages}\n className=\"px-2 py-1 text-xs rounded border border-border disabled:opacity-50 hover:bg-surface\"\n >\n {formatMessage({ id: 'theme.background.next' })}\n </button>\n </div>\n )}\n </>\n )}\n\n {data && data.photos.length === 0 && searchQuery.trim() && (\n <p className=\"text-xs text-text-secondary py-2 text-center\">\n {formatMessage({ id: 'theme.background.noResults' })}\n </p>\n )}\n\n {/* Custom URL input */}\n <div className=\"flex gap-2\">\n <input\n type=\"url\"\n value={customUrl}\n onChange={(e) => setCustomUrl(e.target.value)}\n placeholder={formatMessage({ id: 'theme.background.customUrlPlaceholder' })}\n className=\"flex-1 px-3 py-2 text-xs rounded-lg border border-border bg-bg text-text\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1\"\n />\n <button\n onClick={handleCustomUrlApply}\n disabled={!customUrl.trim()}\n className=\"px-3 py-2 text-xs rounded-lg bg-accent text-white disabled:opacity-50 hover:opacity-90 transition-opacity\"\n >\n {formatMessage({ id: 'theme.background.apply' })}\n </button>\n </div>\n\n {/* Upload local image */}\n <div className=\"space-y-1\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/jpeg,image/png,image/webp,image/gif\"\n onChange={handleFileUpload}\n className=\"hidden\"\n />\n <button\n onClick={() => fileInputRef.current?.click()}\n disabled={isUploading}\n className=\"w-full px-3 py-2 text-xs rounded-lg border border-dashed border-border\n bg-bg text-text hover:bg-surface hover:border-accent\n disabled:opacity-50 transition-all flex items-center justify-center gap-2\"\n >\n {isUploading ? (\n <>\n <div className=\"w-3.5 h-3.5 border-2 border-border border-t-accent rounded-full animate-spin\" />\n {formatMessage({ id: 'theme.background.uploading' })}\n </>\n ) : (\n formatMessage({ id: 'theme.background.upload' })\n )}\n </button>\n {uploadError && (\n <p className=\"text-xs text-destructive\">{uploadError}</p>\n )}\n </div>\n </div>\n )}\n\n {/* Effects panel */}\n {showImageControls && (\n <div className=\"space-y-3 pt-2 border-t border-border\">\n <h4 className=\"text-xs font-medium text-text-secondary\">\n {formatMessage({ id: 'theme.background.effects' })}\n </h4>\n\n {/* Blur slider */}\n <div className=\"space-y-1\">\n <div className=\"flex justify-between\">\n <label className=\"text-xs text-text\">\n {formatMessage({ id: 'theme.background.blur' })}\n </label>\n <span className=\"text-xs text-text-secondary\">{backgroundConfig.effects.blur}px</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"20\"\n step=\"1\"\n value={backgroundConfig.effects.blur}\n onChange={(e) => updateBackgroundEffect('blur', Number(e.target.value))}\n className=\"w-full accent-[hsl(var(--accent))]\"\n />\n </div>\n\n {/* Darken slider */}\n <div className=\"space-y-1\">\n <div className=\"flex justify-between\">\n <label className=\"text-xs text-text\">\n {formatMessage({ id: 'theme.background.darken' })}\n </label>\n <span className=\"text-xs text-text-secondary\">{backgroundConfig.effects.darkenOpacity}%</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"80\"\n step=\"1\"\n value={backgroundConfig.effects.darkenOpacity}\n onChange={(e) => updateBackgroundEffect('darkenOpacity', Number(e.target.value))}\n className=\"w-full accent-[hsl(var(--accent))]\"\n />\n </div>\n\n {/* Saturation slider */}\n <div className=\"space-y-1\">\n <div className=\"flex justify-between\">\n <label className=\"text-xs text-text\">\n {formatMessage({ id: 'theme.background.saturation' })}\n </label>\n <span className=\"text-xs text-text-secondary\">{backgroundConfig.effects.saturation}%</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"200\"\n step=\"5\"\n value={backgroundConfig.effects.saturation}\n onChange={(e) => updateBackgroundEffect('saturation', Number(e.target.value))}\n className=\"w-full accent-[hsl(var(--accent))]\"\n />\n </div>\n\n {/* Frosted glass checkbox */}\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={backgroundConfig.effects.enableFrostedGlass}\n onChange={(e) => updateBackgroundEffect('enableFrostedGlass', e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-accent focus:ring-2 focus:ring-accent focus:ring-offset-2\"\n />\n <span className=\"text-sm text-text\">\n {formatMessage({ id: 'theme.background.frostedGlass' })}\n </span>\n </label>\n\n {/* Grain checkbox */}\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={backgroundConfig.effects.enableGrain}\n onChange={(e) => updateBackgroundEffect('enableGrain', e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-accent focus:ring-2 focus:ring-accent focus:ring-offset-2\"\n />\n <span className=\"text-sm text-text\">\n {formatMessage({ id: 'theme.background.grain' })}\n </span>\n </label>\n\n {/* Vignette checkbox */}\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={backgroundConfig.effects.enableVignette}\n onChange={(e) => updateBackgroundEffect('enableVignette', e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-accent focus:ring-2 focus:ring-accent focus:ring-offset-2\"\n />\n <span className=\"text-sm text-text\">\n {formatMessage({ id: 'theme.background.vignette' })}\n </span>\n </label>\n </div>\n )}\n </div>\n );\n}\n","import React, { useState, useEffect, useRef, useCallback } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { useTheme } from '@/hooks/useTheme';\r\nimport { useNotifications } from '@/hooks/useNotifications';\r\nimport { COLOR_SCHEMES, THEME_MODES, getThemeName, THEME_SLOT_LIMIT, DEFAULT_BACKGROUND_CONFIG } from '@/lib/theme';\r\nimport type { ColorScheme, ThemeMode } from '@/lib/theme';\r\nimport type { ThemeSlotId, StyleTier } from '@/types/store';\r\nimport { generateThemeFromHue, applyStyleTier } from '@/lib/colorGenerator';\r\nimport { checkThemeContrast, generateContrastFix } from '@/lib/accessibility';\r\nimport type { ContrastResult, FixSuggestion } from '@/lib/accessibility';\r\nimport type { ThemeSharePayload } from '@/lib/themeShare';\r\nimport { BackgroundImagePicker } from './BackgroundImagePicker';\r\nimport {\r\n AlertDialog,\r\n AlertDialogContent,\r\n AlertDialogHeader,\r\n AlertDialogTitle,\r\n AlertDialogDescription,\r\n AlertDialogFooter,\r\n AlertDialogAction,\r\n AlertDialogCancel,\r\n} from '@/components/ui/AlertDialog';\r\n\r\n/**\r\n * Theme Selector Component\r\n * Allows users to select from 4 color schemes (blue/green/orange/purple)\r\n * and 2 theme modes (light/dark), plus custom hue customization\r\n *\r\n * Features:\r\n * - 8 preset theme combinations + custom hue support\r\n * - Keyboard navigation support (Arrow keys)\r\n * - ARIA labels for accessibility\r\n * - Visual feedback for selected theme\r\n * - System dark mode detection\r\n * - Custom hue slider (0-360) with real-time preview\r\n */\r\nexport function ThemeSelector() {\r\n const { formatMessage } = useIntl();\r\n const {\r\n colorScheme,\r\n resolvedTheme,\r\n customHue,\r\n isCustomTheme,\r\n gradientLevel,\r\n enableHoverGlow,\r\n enableBackgroundAnimation,\r\n motionPreference,\r\n setColorScheme,\r\n setTheme,\r\n setCustomHue,\r\n setGradientLevel,\r\n setEnableHoverGlow,\r\n setEnableBackgroundAnimation,\r\n setMotionPreference,\r\n styleTier,\r\n setStyleTier,\r\n themeSlots,\r\n activeSlotId,\r\n canAddSlot,\r\n setActiveSlot,\r\n copySlot,\r\n renameSlot,\r\n deleteSlot,\r\n undoDeleteSlot,\r\n exportThemeCode,\r\n importThemeCode,\r\n setBackgroundConfig,\r\n } = useTheme();\r\n const { addToast, removeToast } = useNotifications();\r\n\r\n // Local state for preview hue (uncommitted changes)\r\n const [previewHue, setPreviewHue] = useState<number | null>(customHue);\r\n\r\n // Contrast warning state (non-blocking)\r\n const [contrastWarnings, setContrastWarnings] = useState<ContrastResult[]>([]);\r\n const [contrastFixes, setContrastFixes] = useState<Record<string, FixSuggestion[]>>({});\r\n const [showContrastWarning, setShowContrastWarning] = useState(false);\r\n\r\n // Slot management state\r\n const [renamingSlotId, setRenamingSlotId] = useState<ThemeSlotId | null>(null);\r\n const [renameValue, setRenameValue] = useState('');\r\n const [pendingDeleteSlot, setPendingDeleteSlot] = useState<ThemeSlotId | null>(null);\r\n const renameInputRef = useRef<HTMLInputElement>(null);\r\n const undoToastIdRef = useRef<string | null>(null);\r\n\r\n // Share/import state (local to component, not in store)\r\n const [showImportPanel, setShowImportPanel] = useState(false);\r\n const [importCode, setImportCode] = useState('');\r\n const [importPreview, setImportPreview] = useState<ThemeSharePayload | null>(null);\r\n const [importWarning, setImportWarning] = useState<string | null>(null);\r\n const [importError, setImportError] = useState<string | null>(null);\r\n const [copyFeedback, setCopyFeedback] = useState(false);\r\n\r\n // Sync preview with customHue from store\r\n useEffect(() => {\r\n setPreviewHue(customHue);\r\n }, [customHue]);\r\n\r\n // Resolved mode is either 'light' or 'dark'\r\n const mode: ThemeMode = resolvedTheme;\r\n\r\n // Get preview colors for the custom theme swatches\r\n const getPreviewColor = (variable: string) => {\r\n const hue = previewHue ?? 180; // Default to cyan if null\r\n const colors = generateThemeFromHue(hue, mode);\r\n const hslValue = colors[variable];\r\n return hslValue ? `hsl(${hslValue})` : '#888';\r\n };\r\n\r\n // Style tier definitions for the selector UI\r\n const STYLE_TIERS: Array<{ id: StyleTier; nameKey: string; descKey: string }> = [\r\n { id: 'soft', nameKey: 'theme.styleTier.soft', descKey: 'theme.styleTier.softDesc' },\r\n { id: 'standard', nameKey: 'theme.styleTier.standard', descKey: 'theme.styleTier.standardDesc' },\r\n { id: 'high-contrast', nameKey: 'theme.styleTier.highContrast', descKey: 'theme.styleTier.highContrastDesc' },\r\n ];\r\n\r\n // Get tier preview swatch colors (bg, surface, accent for a sample tier)\r\n const getTierPreviewColors = (tier: StyleTier): { bg: string; surface: string; accent: string } => {\r\n const sampleHue = customHue ?? 220; // Use current hue or default blue\r\n const baseVars = generateThemeFromHue(sampleHue, mode);\r\n const tieredVars = tier === 'standard' ? baseVars : applyStyleTier(baseVars, tier, mode);\r\n return {\r\n bg: tieredVars['--bg'] ? `hsl(${tieredVars['--bg']})` : '#888',\r\n surface: tieredVars['--surface'] ? `hsl(${tieredVars['--surface']})` : '#888',\r\n accent: tieredVars['--accent'] ? `hsl(${tieredVars['--accent']})` : '#888',\r\n };\r\n };\r\n\r\n const handleSchemeSelect = (scheme: ColorScheme) => {\r\n // When selecting a preset scheme, reset custom hue\r\n if (isCustomTheme) {\r\n setCustomHue(null);\r\n }\r\n setColorScheme(scheme);\r\n };\r\n\r\n const handleCustomSelect = () => {\r\n // Set custom hue to a default value if null\r\n if (customHue === null) {\r\n setCustomHue(180); // Default cyan\r\n }\r\n };\r\n\r\n const handleHueSave = () => {\r\n if (previewHue !== null) {\r\n setCustomHue(previewHue);\r\n\r\n // Run contrast check on the new custom theme\r\n const mode: ThemeMode = resolvedTheme;\r\n const vars = generateThemeFromHue(previewHue, mode);\r\n const results = checkThemeContrast(vars);\r\n const failures = results.filter(r => !r.passed);\r\n\r\n if (failures.length > 0) {\r\n setContrastWarnings(failures);\r\n // Generate fixes for each failing pair\r\n const fixes: Record<string, FixSuggestion[]> = {};\r\n for (const failure of failures) {\r\n const key = `${failure.fgVar}|${failure.bgVar}`;\r\n fixes[key] = generateContrastFix(failure.fgVar, failure.bgVar, vars, failure.required);\r\n }\r\n setContrastFixes(fixes);\r\n setShowContrastWarning(true);\r\n } else {\r\n setContrastWarnings([]);\r\n setContrastFixes({});\r\n setShowContrastWarning(false);\r\n }\r\n }\r\n };\r\n\r\n const handleHueReset = () => {\r\n setCustomHue(null);\r\n setPreviewHue(null);\r\n };\r\n\r\n const handleModeSelect = (newMode: ThemeMode) => {\r\n setTheme(newMode);\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\r\n e.preventDefault();\r\n const currentIndex = COLOR_SCHEMES.findIndex(s => s.id === colorScheme);\r\n const nextIndex = (currentIndex + 1) % COLOR_SCHEMES.length;\r\n handleSchemeSelect(COLOR_SCHEMES[nextIndex].id);\r\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\r\n e.preventDefault();\r\n const currentIndex = COLOR_SCHEMES.findIndex(s => s.id === colorScheme);\r\n const nextIndex = (currentIndex - 1 + COLOR_SCHEMES.length) % COLOR_SCHEMES.length;\r\n handleSchemeSelect(COLOR_SCHEMES[nextIndex].id);\r\n }\r\n };\r\n\r\n // ========== Slot Management Handlers ==========\r\n\r\n const handleSlotSelect = useCallback((slotId: ThemeSlotId) => {\r\n if (slotId !== activeSlotId) {\r\n setActiveSlot(slotId);\r\n }\r\n }, [activeSlotId, setActiveSlot]);\r\n\r\n const handleCopySlot = useCallback(() => {\r\n if (!canAddSlot) return;\r\n copySlot();\r\n }, [canAddSlot, copySlot]);\r\n\r\n const handleStartRename = useCallback((slotId: ThemeSlotId, currentName: string) => {\r\n setRenamingSlotId(slotId);\r\n setRenameValue(currentName);\r\n // Focus input after render\r\n setTimeout(() => renameInputRef.current?.focus(), 0);\r\n }, []);\r\n\r\n const handleConfirmRename = useCallback(() => {\r\n if (renamingSlotId && renameValue.trim()) {\r\n renameSlot(renamingSlotId, renameValue.trim());\r\n }\r\n setRenamingSlotId(null);\r\n setRenameValue('');\r\n }, [renamingSlotId, renameValue, renameSlot]);\r\n\r\n const handleCancelRename = useCallback(() => {\r\n setRenamingSlotId(null);\r\n setRenameValue('');\r\n }, []);\r\n\r\n const handleRenameKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n handleConfirmRename();\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n handleCancelRename();\r\n }\r\n }, [handleConfirmRename, handleCancelRename]);\r\n\r\n const handleConfirmDelete = useCallback(() => {\r\n if (!pendingDeleteSlot) return;\r\n\r\n deleteSlot(pendingDeleteSlot);\r\n setPendingDeleteSlot(null);\r\n\r\n // Remove previous undo toast if exists\r\n if (undoToastIdRef.current) {\r\n removeToast(undoToastIdRef.current);\r\n }\r\n\r\n // Show undo toast with 10-second duration\r\n const toastId = addToast('info',\r\n formatMessage({ id: 'theme.slot.undoDelete' }),\r\n undefined,\r\n {\r\n duration: 10000,\r\n dismissible: true,\r\n action: {\r\n label: formatMessage({ id: 'theme.slot.undo' }),\r\n onClick: () => {\r\n undoDeleteSlot();\r\n removeToast(toastId);\r\n undoToastIdRef.current = null;\r\n },\r\n },\r\n }\r\n );\r\n undoToastIdRef.current = toastId;\r\n }, [pendingDeleteSlot, deleteSlot, addToast, removeToast, undoDeleteSlot, formatMessage]);\r\n\r\n const handleCancelDelete = useCallback(() => {\r\n setPendingDeleteSlot(null);\r\n }, []);\r\n\r\n // ========== Share/Import Handlers ==========\r\n\r\n const handleCopyThemeCode = useCallback(async () => {\r\n try {\r\n const code = exportThemeCode();\r\n await navigator.clipboard.writeText(code);\r\n setCopyFeedback(true);\r\n setTimeout(() => setCopyFeedback(false), 2000);\r\n } catch {\r\n // Clipboard API may not be available\r\n addToast('error', 'Failed to copy to clipboard');\r\n }\r\n }, [exportThemeCode, addToast]);\r\n\r\n const handleOpenImport = useCallback(() => {\r\n setShowImportPanel(true);\r\n setImportCode('');\r\n setImportPreview(null);\r\n setImportWarning(null);\r\n setImportError(null);\r\n }, []);\r\n\r\n const handleCloseImport = useCallback(() => {\r\n setShowImportPanel(false);\r\n setImportCode('');\r\n setImportPreview(null);\r\n setImportWarning(null);\r\n setImportError(null);\r\n }, []);\r\n\r\n const handleImportCodeChange = useCallback((value: string) => {\r\n setImportCode(value);\r\n setImportError(null);\r\n setImportWarning(null);\r\n setImportPreview(null);\r\n\r\n if (!value.trim()) return;\r\n\r\n const result = importThemeCode(value);\r\n if (result.ok) {\r\n setImportPreview(result.payload);\r\n if (result.warning) {\r\n setImportWarning(result.warning);\r\n }\r\n } else {\r\n setImportError(result.error);\r\n }\r\n }, [importThemeCode]);\r\n\r\n const handleApplyImport = useCallback(() => {\r\n if (!importPreview) return;\r\n\r\n // Check if we can add a slot or overwrite current\r\n if (!canAddSlot && activeSlotId === 'default') {\r\n // Apply to the default slot directly via individual setters\r\n if (importPreview.customHue !== null) {\r\n setCustomHue(importPreview.customHue);\r\n } else {\r\n setCustomHue(null);\r\n setColorScheme(importPreview.colorScheme);\r\n }\r\n setGradientLevel(importPreview.gradientLevel);\r\n setEnableHoverGlow(importPreview.enableHoverGlow);\r\n setEnableBackgroundAnimation(importPreview.enableBackgroundAnimation);\r\n setStyleTier(importPreview.styleTier);\r\n } else if (canAddSlot) {\r\n // Create a new slot via copySlot then apply settings\r\n copySlot();\r\n // After copySlot, the new slot is active. Apply imported settings.\r\n if (importPreview.customHue !== null) {\r\n setCustomHue(importPreview.customHue);\r\n } else {\r\n setCustomHue(null);\r\n setColorScheme(importPreview.colorScheme);\r\n }\r\n setGradientLevel(importPreview.gradientLevel);\r\n setEnableHoverGlow(importPreview.enableHoverGlow);\r\n setEnableBackgroundAnimation(importPreview.enableBackgroundAnimation);\r\n setStyleTier(importPreview.styleTier);\r\n } else {\r\n // Apply to current active slot via individual setters\r\n if (importPreview.customHue !== null) {\r\n setCustomHue(importPreview.customHue);\r\n } else {\r\n setCustomHue(null);\r\n setColorScheme(importPreview.colorScheme);\r\n }\r\n setGradientLevel(importPreview.gradientLevel);\r\n setEnableHoverGlow(importPreview.enableHoverGlow);\r\n setEnableBackgroundAnimation(importPreview.enableBackgroundAnimation);\r\n setStyleTier(importPreview.styleTier);\r\n }\r\n\r\n // Apply background config from import (v2+ feature)\r\n setBackgroundConfig(importPreview.backgroundConfig ?? DEFAULT_BACKGROUND_CONFIG);\r\n\r\n addToast('success', formatMessage({ id: 'theme.share.importSuccess' }));\r\n handleCloseImport();\r\n }, [\r\n importPreview, canAddSlot, activeSlotId, copySlot,\r\n setCustomHue, setColorScheme, setGradientLevel,\r\n setEnableHoverGlow, setEnableBackgroundAnimation, setStyleTier,\r\n setBackgroundConfig,\r\n addToast, formatMessage, handleCloseImport,\r\n ]);\r\n\r\n /** Generate preview swatch colors from an import payload */\r\n const getImportPreviewColors = useCallback((payload: ThemeSharePayload) => {\r\n const hue = payload.customHue ?? 220;\r\n const baseVars = generateThemeFromHue(hue, mode);\r\n const tieredVars = payload.styleTier === 'standard'\r\n ? baseVars\r\n : applyStyleTier(baseVars, payload.styleTier, mode);\r\n return {\r\n bg: tieredVars['--bg'] ? `hsl(${tieredVars['--bg']})` : '#888',\r\n surface: tieredVars['--surface'] ? `hsl(${tieredVars['--surface']})` : '#888',\r\n accent: tieredVars['--accent'] ? `hsl(${tieredVars['--accent']})` : '#888',\r\n text: tieredVars['--text'] ? `hsl(${tieredVars['--text']})` : '#888',\r\n };\r\n }, [mode]);\r\n\r\n /** Map error keys to i18n message IDs */\r\n const getShareErrorMessageId = (errorKey: string): string => {\r\n switch (errorKey) {\r\n case 'incompatible_version':\r\n return 'theme.share.incompatibleVersion';\r\n default:\r\n return 'theme.share.invalidCode';\r\n }\r\n };\r\n\r\n // Focus rename input when entering rename mode\r\n useEffect(() => {\r\n if (renamingSlotId && renameInputRef.current) {\r\n renameInputRef.current.focus();\r\n renameInputRef.current.select();\r\n }\r\n }, [renamingSlotId]);\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Theme Slot Switcher */}\r\n <div>\r\n <div className=\"flex items-center justify-between mb-3\">\r\n <h3 className=\"text-sm font-medium text-text\">\r\n {formatMessage({ id: 'theme.slot.title' })}\r\n </h3>\r\n <button\r\n onClick={handleCopySlot}\r\n disabled={!canAddSlot}\r\n title={\r\n canAddSlot\r\n ? formatMessage({ id: 'theme.slot.copy' })\r\n : formatMessage({ id: 'theme.slot.limitReached' }, { limit: THEME_SLOT_LIMIT })\r\n }\r\n className={`\r\n px-2 py-1 rounded text-xs font-medium\r\n transition-all duration-200\r\n ${canAddSlot\r\n ? 'bg-accent text-white hover:bg-accent-hover focus:ring-2 focus:ring-accent focus:ring-offset-1'\r\n : 'bg-muted text-muted-text cursor-not-allowed'\r\n }\r\n focus:outline-none\r\n `}\r\n >\r\n + {formatMessage({ id: 'theme.slot.copy' })}\r\n </button>\r\n </div>\r\n\r\n <div className=\"flex gap-2\" role=\"tablist\" aria-label={formatMessage({ id: 'theme.slot.title' })}>\r\n {themeSlots.map((slot) => {\r\n const isActive = slot.id === activeSlotId;\r\n const isRenaming = slot.id === renamingSlotId;\r\n\r\n return (\r\n <div\r\n key={slot.id}\r\n role=\"tab\"\r\n aria-selected={isActive}\r\n tabIndex={isActive ? 0 : -1}\r\n onClick={() => handleSlotSelect(slot.id)}\r\n className={`\r\n relative flex-1 min-w-0 p-2.5 rounded-lg cursor-pointer\r\n transition-all duration-200 border-2 group\r\n ${isActive\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1\r\n `}\r\n >\r\n {/* Active indicator */}\r\n {isActive && (\r\n <span className=\"absolute -top-1 -right-1 w-2.5 h-2.5 rounded-full bg-accent border-2 border-bg\" />\r\n )}\r\n\r\n {/* Slot name - inline rename or display */}\r\n <div className=\"flex items-center gap-1 min-w-0\">\r\n {isRenaming ? (\r\n <input\r\n ref={renameInputRef}\r\n type=\"text\"\r\n value={renameValue}\r\n onChange={(e) => setRenameValue(e.target.value)}\r\n onKeyDown={handleRenameKeyDown}\r\n onBlur={handleConfirmRename}\r\n onClick={(e) => e.stopPropagation()}\r\n className=\"\r\n w-full px-1 py-0.5 text-xs font-medium text-text\r\n bg-bg border border-accent rounded\r\n focus:outline-none focus:ring-1 focus:ring-accent\r\n \"\r\n maxLength={20}\r\n />\r\n ) : (\r\n <span\r\n className=\"text-xs font-medium text-text truncate\"\r\n title={slot.name}\r\n onDoubleClick={(e) => {\r\n e.stopPropagation();\r\n if (!slot.isDefault) {\r\n handleStartRename(slot.id, slot.name);\r\n }\r\n }}\r\n >\r\n {slot.name}\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* Active label */}\r\n {isActive && !isRenaming && (\r\n <span className=\"text-[10px] text-accent font-medium mt-0.5 block\">\r\n {formatMessage({ id: 'theme.slot.active' })}\r\n </span>\r\n )}\r\n\r\n {/* Action buttons - show on hover for non-default slots */}\r\n {!slot.isDefault && !isRenaming && (\r\n <div className=\"\r\n absolute top-1 right-1 flex gap-0.5\r\n opacity-0 group-hover:opacity-100 transition-opacity duration-150\r\n \">\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleStartRename(slot.id, slot.name);\r\n }}\r\n title={formatMessage({ id: 'theme.slot.rename' })}\r\n className=\"\r\n p-0.5 rounded text-text-tertiary hover:text-text hover:bg-surface-hover\r\n transition-colors duration-150 focus:outline-none\r\n \"\r\n >\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M11.5 1.5L14.5 4.5L5 14H2V11L11.5 1.5Z\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n setPendingDeleteSlot(slot.id);\r\n }}\r\n title={formatMessage({ id: 'theme.slot.delete' })}\r\n className=\"\r\n p-0.5 rounded text-text-tertiary hover:text-error hover:bg-error-light\r\n transition-colors duration-150 focus:outline-none\r\n \"\r\n >\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M4 4L12 12M12 4L4 12\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Default slot: show disabled delete tooltip */}\r\n {slot.isDefault && (\r\n <div className=\"\r\n absolute top-1 right-1 flex gap-0.5\r\n opacity-0 group-hover:opacity-100 transition-opacity duration-150\r\n \">\r\n <button\r\n disabled\r\n title={formatMessage({ id: 'theme.slot.cannotDeleteDefault' })}\r\n className=\"p-0.5 rounded text-muted-text cursor-not-allowed\"\r\n >\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M4 4L12 12M12 4L4 12\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Color Scheme Selection */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.title.colorScheme' })}\r\n </h3>\r\n <div\r\n className=\"grid grid-cols-5 gap-3\"\r\n role=\"group\"\r\n aria-label=\"Color scheme selection\"\r\n onKeyDown={handleKeyDown}\r\n >\r\n {COLOR_SCHEMES.map((scheme) => (\r\n <button\r\n key={scheme.id}\r\n onClick={() => handleSchemeSelect(scheme.id)}\r\n aria-label={formatMessage({ id: 'theme.select.colorScheme' }, { name: formatMessage({ id: `theme.colorScheme.${scheme.id}` }) })}\r\n aria-selected={colorScheme === scheme.id && !isCustomTheme}\r\n role=\"radio\"\r\n className={`\r\n flex flex-col items-center gap-2 p-3 rounded-lg\r\n transition-all duration-200 border-2\r\n ${colorScheme === scheme.id && !isCustomTheme\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {/* Color swatch */}\r\n <div\r\n className=\"w-8 h-8 rounded-full border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: scheme.accentColor }}\r\n aria-hidden=\"true\"\r\n />\r\n {/* Label */}\r\n <span className=\"text-xs font-medium text-text text-center\">\r\n {formatMessage({ id: `theme.colorScheme.${scheme.id}` })}\r\n </span>\r\n </button>\r\n ))}\r\n\r\n {/* Custom Color Option */}\r\n <button\r\n onClick={handleCustomSelect}\r\n aria-label={formatMessage({ id: 'theme.select.colorScheme' }, { name: formatMessage({ id: 'theme.colorScheme.custom' }) })}\r\n aria-selected={isCustomTheme}\r\n role=\"radio\"\r\n className={`\r\n flex flex-col items-center gap-2 p-3 rounded-lg\r\n transition-all duration-200 border-2\r\n ${isCustomTheme\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {/* Gradient swatch showing current custom hue */}\r\n <div\r\n className=\"w-8 h-8 rounded-full border-2 border-border shadow-sm\"\r\n style={{\r\n background: `linear-gradient(135deg, ${getPreviewColor('--accent')}, ${getPreviewColor('--primary')})`\r\n }}\r\n aria-hidden=\"true\"\r\n />\r\n {/* Label */}\r\n <span className=\"text-xs font-medium text-text text-center\">\r\n {formatMessage({ id: 'theme.colorScheme.custom' })}\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Custom Hue Selection - Only shown when custom theme is active */}\r\n {isCustomTheme && (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.title.customHue' })}\r\n </h3>\r\n\r\n {/* Hue Slider */}\r\n <div className=\"space-y-3\">\r\n <div className=\"flex items-center justify-between\">\r\n <label htmlFor=\"hue-slider\" className=\"text-xs text-text-secondary\">\r\n {formatMessage({ id: 'theme.hueValue' }, { value: previewHue ?? 180 })}\r\n </label>\r\n </div>\r\n <input\r\n id=\"hue-slider\"\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"360\"\r\n step=\"1\"\r\n value={previewHue ?? 180}\r\n onChange={(e) => setPreviewHue(Number(e.target.value))}\r\n className=\"w-full h-2 rounded-lg appearance-none cursor-pointer\"\r\n style={{\r\n background: `linear-gradient(to right,\r\n hsl(0, 70%, 60%), hsl(60, 70%, 60%), hsl(120, 70%, 60%),\r\n hsl(180, 70%, 60%), hsl(240, 70%, 60%), hsl(300, 70%, 60%), hsl(360, 70%, 60%))`\r\n }}\r\n aria-label={formatMessage({ id: 'theme.title.customHue' })}\r\n />\r\n\r\n {/* Preview Swatches */}\r\n <div className=\"flex gap-3 items-end\">\r\n <span className=\"text-xs text-text-secondary pb-1\">\r\n {formatMessage({ id: 'theme.preview' })}:\r\n </span>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: getPreviewColor('--bg') }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">{formatMessage({ id: 'theme.preview.background' })}</span>\r\n </div>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: getPreviewColor('--surface') }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">{formatMessage({ id: 'theme.preview.surface' })}</span>\r\n </div>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: getPreviewColor('--accent') }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">{formatMessage({ id: 'theme.preview.accent' })}</span>\r\n </div>\r\n </div>\r\n\r\n {/* Save and Reset Buttons */}\r\n <div className=\"flex gap-2 pt-2\">\r\n <button\r\n onClick={handleHueSave}\r\n disabled={previewHue === customHue}\r\n className={`\r\n flex-1 px-4 py-2 rounded-lg text-sm font-medium\r\n transition-all duration-200\r\n ${previewHue === customHue\r\n ? 'bg-muted text-muted-text cursor-not-allowed'\r\n : 'bg-accent text-white hover:bg-accent-hover focus:ring-2 focus:ring-accent focus:ring-offset-2'\r\n }\r\n `}\r\n >\r\n {formatMessage({ id: 'theme.save' })}\r\n </button>\r\n <button\r\n onClick={handleHueReset}\r\n className=\"\r\n px-4 py-2 rounded-lg text-sm font-medium\r\n border-2 border-border bg-bg text-text\r\n hover:bg-surface transition-all duration-200\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n >\r\n {formatMessage({ id: 'theme.reset' })}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Style Tier Selection */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.styleTier.label' })}\r\n </h3>\r\n <div\r\n className=\"grid grid-cols-3 gap-3\"\r\n role=\"radiogroup\"\r\n aria-label={formatMessage({ id: 'theme.styleTier.label' })}\r\n >\r\n {STYLE_TIERS.map((tier) => {\r\n const preview = getTierPreviewColors(tier.id);\r\n const isSelected = styleTier === tier.id;\r\n return (\r\n <button\r\n key={tier.id}\r\n onClick={() => setStyleTier(tier.id)}\r\n role=\"radio\"\r\n aria-checked={isSelected}\r\n className={`\r\n flex flex-col items-center gap-2 p-3 rounded-lg\r\n transition-all duration-200 border-2\r\n ${isSelected\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {/* Preview swatches */}\r\n <div className=\"flex gap-1\" aria-hidden=\"true\">\r\n <div\r\n className=\"w-5 h-5 rounded-sm border border-border\"\r\n style={{ backgroundColor: preview.bg }}\r\n />\r\n <div\r\n className=\"w-5 h-5 rounded-sm border border-border\"\r\n style={{ backgroundColor: preview.surface }}\r\n />\r\n <div\r\n className=\"w-5 h-5 rounded-sm border border-border\"\r\n style={{ backgroundColor: preview.accent }}\r\n />\r\n </div>\r\n {/* Tier name */}\r\n <span className=\"text-xs font-medium text-text text-center\">\r\n {formatMessage({ id: tier.nameKey })}\r\n </span>\r\n {/* Description */}\r\n <span className=\"text-[10px] text-text-tertiary text-center leading-tight\">\r\n {formatMessage({ id: tier.descKey })}\r\n </span>\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Gradient Effects Settings */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.gradient.title' })}\r\n </h3>\r\n\r\n {/* Gradient Level Selection */}\r\n <div className=\"space-y-4\">\r\n <div\r\n className=\"flex gap-2\"\r\n role=\"radiogroup\"\r\n aria-label={formatMessage({ id: 'theme.gradient.title' })}\r\n >\r\n {(['off', 'standard', 'enhanced'] as const).map((level) => (\r\n <button\r\n key={level}\r\n onClick={() => setGradientLevel(level)}\r\n role=\"radio\"\r\n aria-checked={gradientLevel === level}\r\n className={`\r\n flex-1 px-3 py-2 rounded-lg text-sm font-medium\r\n transition-all duration-200 border-2\r\n ${gradientLevel === level\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {formatMessage({ id: `theme.gradient.${level}` })}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Hover Glow Checkbox */}\r\n <label className=\"flex items-center gap-3 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={enableHoverGlow}\r\n onChange={(e) => setEnableHoverGlow(e.target.checked)}\r\n className=\"\r\n w-4 h-4 rounded border-border text-accent\r\n focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n />\r\n <span className=\"text-sm text-text\">\r\n {formatMessage({ id: 'theme.gradient.hoverGlow' })}\r\n </span>\r\n </label>\r\n\r\n {/* Background Animation Checkbox */}\r\n <label className=\"flex items-center gap-3 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={enableBackgroundAnimation}\r\n onChange={(e) => setEnableBackgroundAnimation(e.target.checked)}\r\n className=\"\r\n w-4 h-4 rounded border-border text-accent\r\n focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n />\r\n <span className=\"text-sm text-text\">\r\n {formatMessage({ id: 'theme.gradient.bgAnimation' })}\r\n </span>\r\n </label>\r\n </div>\r\n </div>\r\n\r\n {/* Background Image */}\r\n <BackgroundImagePicker />\r\n\r\n {/* Motion Preference */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.motion.label' })}\r\n </h3>\r\n <div\r\n className=\"flex gap-2\"\r\n role=\"radiogroup\"\r\n aria-label={formatMessage({ id: 'theme.motion.label' })}\r\n >\r\n {(['system', 'reduce', 'enable'] as const).map((pref) => (\r\n <button\r\n key={pref}\r\n onClick={() => setMotionPreference(pref)}\r\n role=\"radio\"\r\n aria-checked={motionPreference === pref}\r\n className={`\r\n flex-1 px-3 py-2 rounded-lg text-sm font-medium\r\n transition-all duration-200 border-2\r\n ${motionPreference === pref\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {formatMessage({ id: `theme.motion.${pref}` })}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Contrast Warning Banner (non-blocking) */}\r\n {showContrastWarning && contrastWarnings.length > 0 && (\r\n <div className=\"p-3 rounded-lg bg-warning-light border border-warning text-warning-text space-y-2\">\r\n <p className=\"text-xs font-medium\">\r\n {formatMessage({ id: 'theme.accessibility.contrastWarning' })}\r\n </p>\r\n <ul className=\"text-xs space-y-1\">\r\n {contrastWarnings.map((w) => {\r\n const key = `${w.fgVar}|${w.bgVar}`;\r\n const fixes = contrastFixes[key] || [];\r\n return (\r\n <li key={key} className=\"space-y-1\">\r\n <span>\r\n {w.fgVar} / {w.bgVar}: {w.ratio}:1 (min {w.required}:1)\r\n </span>\r\n {fixes.length > 0 && (\r\n <div className=\"ml-2 text-[10px]\">\r\n {fixes.slice(0, 1).map((fix, i) => (\r\n <span key={i} className=\"block\">\r\n {formatMessage(\r\n { id: 'theme.accessibility.fixSuggestion' },\r\n {\r\n target: fix.target === 'fg' ? w.fgVar : w.bgVar,\r\n original: fix.original,\r\n suggested: fix.suggested,\r\n ratio: fix.resultRatio,\r\n }\r\n )}\r\n </span>\r\n ))}\r\n </div>\r\n )}\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n <button\r\n onClick={() => setShowContrastWarning(false)}\r\n className=\"text-xs font-medium underline\"\r\n >\r\n {formatMessage({ id: 'theme.accessibility.dismiss' })}\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Theme Mode Selection */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.title.themeMode' })}\r\n </h3>\r\n <div\r\n className=\"grid grid-cols-2 gap-3\"\r\n role=\"group\"\r\n aria-label=\"Theme mode selection\"\r\n >\r\n {THEME_MODES.map((modeOption) => (\r\n <button\r\n key={modeOption.id}\r\n onClick={() => handleModeSelect(modeOption.id)}\r\n aria-label={formatMessage({ id: 'theme.select.themeMode' }, { name: formatMessage({ id: `theme.themeMode.${modeOption.id}` }) })}\r\n aria-selected={mode === modeOption.id}\r\n role=\"radio\"\r\n className={`\r\n flex items-center justify-center gap-2 p-3 rounded-lg\r\n transition-all duration-200 border-2\r\n ${mode === modeOption.id\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {/* Icon */}\r\n <span className=\"text-lg\" aria-hidden=\"true\">\r\n {modeOption.id === 'light' ? '☀️' : '🌙'}\r\n </span>\r\n {/* Label */}\r\n <span className=\"text-sm font-medium text-text\">\r\n {formatMessage({ id: `theme.themeMode.${modeOption.id}` })}\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Current Theme Display */}\r\n <div className=\"p-3 rounded-lg bg-surface border border-border\">\r\n <p className=\"text-xs text-text-secondary\">\r\n {formatMessage({ id: 'theme.current' }, { name: getThemeName(colorScheme, mode) })}\r\n </p>\r\n </div>\r\n\r\n {/* Theme Sharing Section */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.share.label' })}\r\n </h3>\r\n\r\n <div className=\"flex gap-2\">\r\n {/* Copy Theme Code button */}\r\n <button\r\n onClick={handleCopyThemeCode}\r\n className=\"\r\n flex-1 px-3 py-2 rounded-lg text-sm font-medium\r\n border-2 border-border bg-bg text-text\r\n hover:bg-surface transition-all duration-200\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n >\r\n {copyFeedback\r\n ? formatMessage({ id: 'theme.share.copied' })\r\n : formatMessage({ id: 'theme.share.copyCode' })\r\n }\r\n </button>\r\n\r\n {/* Import Theme button */}\r\n <button\r\n onClick={showImportPanel ? handleCloseImport : handleOpenImport}\r\n className={`\r\n flex-1 px-3 py-2 rounded-lg text-sm font-medium\r\n transition-all duration-200 border-2\r\n ${showImportPanel\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg text-text hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {formatMessage({ id: 'theme.share.import' })}\r\n </button>\r\n </div>\r\n\r\n {/* Import Panel */}\r\n {showImportPanel && (\r\n <div className=\"mt-3 space-y-3\">\r\n {/* Paste textarea */}\r\n <textarea\r\n value={importCode}\r\n onChange={(e) => handleImportCodeChange(e.target.value)}\r\n placeholder={formatMessage({ id: 'theme.share.paste' })}\r\n rows={3}\r\n className=\"\r\n w-full px-3 py-2 rounded-lg text-sm font-mono\r\n bg-bg border-2 border-border text-text\r\n placeholder-text-tertiary resize-none\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:border-accent\r\n \"\r\n />\r\n\r\n {/* Error message */}\r\n {importError && (\r\n <div className=\"p-2 rounded-lg bg-error-light border border-error text-error-text text-xs\">\r\n {formatMessage({ id: getShareErrorMessageId(importError) })}\r\n </div>\r\n )}\r\n\r\n {/* Version warning */}\r\n {importWarning && !importError && (\r\n <div className=\"p-2 rounded-lg bg-warning-light border border-warning text-warning-text text-xs\">\r\n {formatMessage({ id: 'theme.share.versionWarning' })}\r\n </div>\r\n )}\r\n\r\n {/* Import Preview Card */}\r\n {importPreview && !importError && (\r\n <div className=\"p-3 rounded-lg bg-surface border border-border space-y-3\">\r\n <p className=\"text-xs font-medium text-text\">\r\n {formatMessage({ id: 'theme.share.preview' })}\r\n </p>\r\n\r\n {/* Preview swatches */}\r\n <div className=\"flex gap-3 items-end\">\r\n {(() => {\r\n const previewColors = getImportPreviewColors(importPreview);\r\n return (\r\n <>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: previewColors.bg }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">\r\n {formatMessage({ id: 'theme.preview.background' })}\r\n </span>\r\n </div>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: previewColors.surface }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">\r\n {formatMessage({ id: 'theme.preview.surface' })}\r\n </span>\r\n </div>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: previewColors.accent }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">\r\n {formatMessage({ id: 'theme.preview.accent' })}\r\n </span>\r\n </div>\r\n </>\r\n );\r\n })()}\r\n </div>\r\n\r\n {/* Settings summary */}\r\n <div className=\"text-xs text-text-secondary space-y-1\">\r\n <p>\r\n {formatMessage({ id: 'theme.styleTier.label' })}: {formatMessage({ id: `theme.styleTier.${importPreview.styleTier === 'high-contrast' ? 'highContrast' : importPreview.styleTier}` })}\r\n </p>\r\n <p>\r\n {formatMessage({ id: 'theme.gradient.title' })}: {formatMessage({ id: `theme.gradient.${importPreview.gradientLevel}` })}\r\n </p>\r\n {importPreview.customHue !== null && (\r\n <p>\r\n {formatMessage({ id: 'theme.hueValue' }, { value: importPreview.customHue })}\r\n </p>\r\n )}\r\n {importPreview.customHue === null && (\r\n <p>\r\n {formatMessage({ id: 'theme.title.colorScheme' })}: {formatMessage({ id: `theme.colorScheme.${importPreview.colorScheme}` })}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {/* Apply / Cancel buttons */}\r\n <div className=\"flex gap-2 pt-1\">\r\n <button\r\n onClick={handleApplyImport}\r\n className=\"\r\n flex-1 px-4 py-2 rounded-lg text-sm font-medium\r\n bg-accent text-white hover:bg-accent-hover\r\n transition-all duration-200\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n >\r\n {formatMessage({ id: 'theme.share.apply' })}\r\n </button>\r\n <button\r\n onClick={handleCloseImport}\r\n className=\"\r\n px-4 py-2 rounded-lg text-sm font-medium\r\n border-2 border-border bg-bg text-text\r\n hover:bg-surface transition-all duration-200\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n >\r\n {formatMessage({ id: 'theme.share.cancel' })}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Delete Confirmation Dialog */}\r\n <AlertDialog open={pendingDeleteSlot !== null} onOpenChange={handleCancelDelete}>\r\n <AlertDialogContent>\r\n <AlertDialogHeader>\r\n <AlertDialogTitle>Delete Theme Slot?</AlertDialogTitle>\r\n <AlertDialogDescription>\r\n This action cannot be undone. The theme slot will be permanently deleted.\r\n </AlertDialogDescription>\r\n </AlertDialogHeader>\r\n <AlertDialogFooter>\r\n <AlertDialogCancel onClick={handleCancelDelete}>Cancel</AlertDialogCancel>\r\n <AlertDialogAction onClick={handleConfirmDelete}>Delete</AlertDialogAction>\r\n </AlertDialogFooter>\r\n </AlertDialogContent>\r\n </AlertDialog>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","// ========================================\r\n// Language Switcher Component\r\n// ========================================\r\n// Language selection dropdown with flag icons\r\n\r\nimport { Languages } from 'lucide-react';\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '@/components/ui/Select';\r\nimport { useLocale } from '@/hooks/useLocale';\r\nimport { cn } from '@/lib/utils';\r\n\r\nexport interface LanguageSwitcherProps {\r\n /** Compact variant for header (smaller, icon-only trigger) */\r\n compact?: boolean;\r\n /** Additional CSS classes */\r\n className?: string;\r\n}\r\n\r\n// Language options with flag emojis and labels\r\nconst LANGUAGE_OPTIONS = [\r\n { value: 'en' as const, label: 'English', flag: '🇺🇸' },\r\n { value: 'zh' as const, label: '中文', flag: '🇨🇳' },\r\n] as const;\r\n\r\n/**\r\n * Language switcher component\r\n * Allows users to switch between English and Chinese\r\n */\r\nexport function LanguageSwitcher({ compact = false, className }: LanguageSwitcherProps) {\r\n const { locale, setLocale } = useLocale();\r\n\r\n return (\r\n <Select value={locale} onValueChange={setLocale}>\r\n <SelectTrigger\r\n className={cn(\r\n compact ? 'w-[110px]' : 'w-[160px]',\r\n 'gap-2',\r\n className\r\n )}\r\n aria-label=\"Select language\"\r\n >\r\n {compact ? (\r\n <>\r\n <Languages className=\"w-4 h-4\" />\r\n <SelectValue />\r\n </>\r\n ) : (\r\n <SelectValue />\r\n )}\r\n </SelectTrigger>\r\n <SelectContent>\r\n {LANGUAGE_OPTIONS.map((option) => (\r\n <SelectItem key={option.value} value={option.value}>\r\n <span className=\"flex items-center gap-2\">\r\n <span className=\"text-base\">{option.flag}</span>\r\n <span>{option.label}</span>\r\n </span>\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n );\r\n}\r\n\r\nexport default LanguageSwitcher;\r\n","// ========================================\r\n// Remote Notification Types (Frontend)\r\n// ========================================\r\n// Type definitions for remote notification system UI\r\n// Mirrors backend types with UI-specific additions\r\n\r\n/**\r\n * Supported notification platforms\r\n */\r\nexport type NotificationPlatform = 'discord' | 'telegram' | 'feishu' | 'dingtalk' | 'wecom' | 'email' | 'webhook';\r\n\r\n/**\r\n * Event types that can trigger notifications\r\n */\r\nexport type NotificationEventType =\r\n | 'ask-user-question'\r\n | 'session-start'\r\n | 'session-end'\r\n | 'task-completed'\r\n | 'task-failed';\r\n\r\n/**\r\n * Discord platform configuration\r\n */\r\nexport interface DiscordConfig {\r\n enabled: boolean;\r\n webhookUrl: string;\r\n username?: string;\r\n avatarUrl?: string;\r\n}\r\n\r\n/**\r\n * Telegram platform configuration\r\n */\r\nexport interface TelegramConfig {\r\n enabled: boolean;\r\n botToken: string;\r\n chatId: string;\r\n parseMode?: 'HTML' | 'Markdown' | 'MarkdownV2';\r\n}\r\n\r\n/**\r\n * Feishu (Lark) platform configuration\r\n */\r\nexport interface FeishuConfig {\r\n enabled: boolean;\r\n webhookUrl: string;\r\n useCard?: boolean;\r\n title?: string;\r\n}\r\n\r\n/**\r\n * DingTalk platform configuration\r\n */\r\nexport interface DingTalkConfig {\r\n enabled: boolean;\r\n webhookUrl: string;\r\n keywords?: string[];\r\n}\r\n\r\n/**\r\n * WeCom (WeChat Work) platform configuration\r\n */\r\nexport interface WeComConfig {\r\n enabled: boolean;\r\n webhookUrl: string;\r\n mentionedList?: string[];\r\n}\r\n\r\n/**\r\n * Email SMTP platform configuration\r\n */\r\nexport interface EmailConfig {\r\n enabled: boolean;\r\n host: string;\r\n port: number;\r\n secure?: boolean;\r\n username: string;\r\n password: string;\r\n from: string;\r\n to: string[];\r\n}\r\n\r\n/**\r\n * Generic Webhook platform configuration\r\n */\r\nexport interface WebhookConfig {\r\n enabled: boolean;\r\n url: string;\r\n method: 'POST' | 'PUT';\r\n headers?: Record<string, string>;\r\n timeout?: number;\r\n}\r\n\r\n/**\r\n * Event configuration\r\n */\r\nexport interface EventConfig {\r\n event: NotificationEventType;\r\n platforms: NotificationPlatform[];\r\n enabled: boolean;\r\n}\r\n\r\n/**\r\n * Full remote notification configuration\r\n */\r\nexport interface RemoteNotificationConfig {\r\n enabled: boolean;\r\n platforms: {\r\n discord?: DiscordConfig;\r\n telegram?: TelegramConfig;\r\n feishu?: FeishuConfig;\r\n dingtalk?: DingTalkConfig;\r\n wecom?: WeComConfig;\r\n email?: EmailConfig;\r\n webhook?: WebhookConfig;\r\n };\r\n events: EventConfig[];\r\n timeout: number;\r\n}\r\n\r\n/**\r\n * Test notification request\r\n */\r\nexport interface TestNotificationRequest {\r\n platform: NotificationPlatform;\r\n config: DiscordConfig | TelegramConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig | WebhookConfig;\r\n}\r\n\r\n/**\r\n * Test notification result\r\n */\r\nexport interface TestNotificationResult {\r\n success: boolean;\r\n error?: string;\r\n responseTime?: number;\r\n}\r\n\r\n/**\r\n * Platform display info\r\n */\r\nexport interface PlatformInfo {\r\n id: NotificationPlatform;\r\n name: string;\r\n icon: string;\r\n description: string;\r\n requiredFields: string[];\r\n}\r\n\r\n/**\r\n * Event display info\r\n */\r\nexport interface EventInfo {\r\n id: NotificationEventType;\r\n name: string;\r\n description: string;\r\n icon: string;\r\n}\r\n\r\n/**\r\n * Predefined platform information\r\n */\r\nexport const PLATFORM_INFO: Record<NotificationPlatform, PlatformInfo> = {\r\n discord: {\r\n id: 'discord',\r\n name: 'Discord',\r\n icon: 'message-circle',\r\n description: 'Send notifications to Discord channels via webhook',\r\n requiredFields: ['webhookUrl'],\r\n },\r\n telegram: {\r\n id: 'telegram',\r\n name: 'Telegram',\r\n icon: 'send',\r\n description: 'Send notifications to Telegram chats via bot',\r\n requiredFields: ['botToken', 'chatId'],\r\n },\r\n feishu: {\r\n id: 'feishu',\r\n name: 'Feishu',\r\n icon: 'message-square',\r\n description: 'Send notifications to Feishu (Lark) via webhook with rich card support',\r\n requiredFields: ['webhookUrl'],\r\n },\r\n dingtalk: {\r\n id: 'dingtalk',\r\n name: 'DingTalk',\r\n icon: 'bell',\r\n description: 'Send notifications to DingTalk via webhook',\r\n requiredFields: ['webhookUrl'],\r\n },\r\n wecom: {\r\n id: 'wecom',\r\n name: 'WeCom',\r\n icon: 'users',\r\n description: 'Send notifications to WeCom (WeChat Work) via webhook',\r\n requiredFields: ['webhookUrl'],\r\n },\r\n email: {\r\n id: 'email',\r\n name: 'Email',\r\n icon: 'mail',\r\n description: 'Send notifications via SMTP email',\r\n requiredFields: ['host', 'username', 'password', 'from', 'to'],\r\n },\r\n webhook: {\r\n id: 'webhook',\r\n name: 'Custom Webhook',\r\n icon: 'link',\r\n description: 'Send notifications to a custom HTTP endpoint',\r\n requiredFields: ['url'],\r\n },\r\n};\r\n\r\n/**\r\n * Predefined event information\r\n */\r\nexport const EVENT_INFO: Record<NotificationEventType, EventInfo> = {\r\n 'ask-user-question': {\r\n id: 'ask-user-question',\r\n name: 'Ask User Question',\r\n description: 'Notification when Claude asks a question via AskUserQuestion',\r\n icon: 'help-circle',\r\n },\r\n 'session-start': {\r\n id: 'session-start',\r\n name: 'Session Start',\r\n description: 'Notification when a CLI session starts',\r\n icon: 'play',\r\n },\r\n 'session-end': {\r\n id: 'session-end',\r\n name: 'Session End',\r\n description: 'Notification when a CLI session ends',\r\n icon: 'square',\r\n },\r\n 'task-completed': {\r\n id: 'task-completed',\r\n name: 'Task Completed',\r\n description: 'Notification when a task completes successfully',\r\n icon: 'check-circle',\r\n },\r\n 'task-failed': {\r\n id: 'task-failed',\r\n name: 'Task Failed',\r\n description: 'Notification when a task fails',\r\n icon: 'alert-circle',\r\n },\r\n};\r\n\r\n/**\r\n * Default configuration for UI initialization\r\n */\r\nexport function getDefaultConfig(): RemoteNotificationConfig {\r\n return {\r\n enabled: false,\r\n platforms: {},\r\n events: [\r\n { event: 'ask-user-question', platforms: ['discord', 'telegram'], enabled: true },\r\n { event: 'session-start', platforms: [], enabled: false },\r\n { event: 'session-end', platforms: [], enabled: false },\r\n { event: 'task-completed', platforms: [], enabled: false },\r\n { event: 'task-failed', platforms: ['discord', 'telegram'], enabled: true },\r\n ],\r\n timeout: 10000,\r\n };\r\n}\r\n","// ========================================\r\n// Platform Configuration Cards\r\n// ========================================\r\n// Individual configuration cards for each notification platform\r\n\r\nimport { useState } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport {\r\n MessageCircle,\r\n Send,\r\n Link,\r\n Check,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n TestTube,\r\n Eye,\r\n EyeOff,\r\n MessageSquare,\r\n Bell,\r\n Users,\r\n Mail,\r\n} from 'lucide-react';\r\nimport { Card } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { cn } from '@/lib/utils';\r\nimport type {\r\n RemoteNotificationConfig,\r\n NotificationPlatform,\r\n DiscordConfig,\r\n TelegramConfig,\r\n WebhookConfig,\r\n FeishuConfig,\r\n DingTalkConfig,\r\n WeComConfig,\r\n EmailConfig,\r\n} from '@/types/remote-notification';\r\nimport { PLATFORM_INFO } from '@/types/remote-notification';\r\n\r\ninterface PlatformConfigCardsProps {\r\n config: RemoteNotificationConfig;\r\n expandedPlatform: NotificationPlatform | null;\r\n testing: NotificationPlatform | null;\r\n onToggleExpand: (platform: NotificationPlatform | null) => void;\r\n onUpdateConfig: (\r\n platform: NotificationPlatform,\r\n updates: Partial<DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig>\r\n ) => void;\r\n onTest: (\r\n platform: NotificationPlatform,\r\n config: DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig\r\n ) => void;\r\n onSave: () => void;\r\n saving: boolean;\r\n}\r\n\r\nexport function PlatformConfigCards({\r\n config,\r\n expandedPlatform,\r\n testing,\r\n onToggleExpand,\r\n onUpdateConfig,\r\n onTest,\r\n onSave,\r\n saving,\r\n}: PlatformConfigCardsProps) {\r\n const { formatMessage } = useIntl();\r\n\r\n const platforms: NotificationPlatform[] = ['discord', 'telegram', 'feishu', 'dingtalk', 'wecom', 'email', 'webhook'];\r\n\r\n const getPlatformIcon = (platform: NotificationPlatform) => {\r\n switch (platform) {\r\n case 'discord':\r\n return <MessageCircle className=\"w-4 h-4\" />;\r\n case 'telegram':\r\n return <Send className=\"w-4 h-4\" />;\r\n case 'feishu':\r\n return <MessageSquare className=\"w-4 h-4\" />;\r\n case 'dingtalk':\r\n return <Bell className=\"w-4 h-4\" />;\r\n case 'wecom':\r\n return <Users className=\"w-4 h-4\" />;\r\n case 'email':\r\n return <Mail className=\"w-4 h-4\" />;\r\n case 'webhook':\r\n return <Link className=\"w-4 h-4\" />;\r\n }\r\n };\r\n\r\n const getPlatformConfig = (\r\n platform: NotificationPlatform\r\n ): DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig => {\r\n switch (platform) {\r\n case 'discord':\r\n return config.platforms.discord || { enabled: false, webhookUrl: '' };\r\n case 'telegram':\r\n return config.platforms.telegram || { enabled: false, botToken: '', chatId: '' };\r\n case 'feishu':\r\n return config.platforms.feishu || { enabled: false, webhookUrl: '' };\r\n case 'dingtalk':\r\n return config.platforms.dingtalk || { enabled: false, webhookUrl: '' };\r\n case 'wecom':\r\n return config.platforms.wecom || { enabled: false, webhookUrl: '' };\r\n case 'email':\r\n return config.platforms.email || { enabled: false, host: '', port: 587, username: '', password: '', from: '', to: [] };\r\n case 'webhook':\r\n return config.platforms.webhook || { enabled: false, url: '', method: 'POST' };\r\n }\r\n };\r\n\r\n const isConfigured = (platform: NotificationPlatform): boolean => {\r\n const platformConfig = getPlatformConfig(platform);\r\n switch (platform) {\r\n case 'discord':\r\n return !!(platformConfig as DiscordConfig).webhookUrl;\r\n case 'telegram':\r\n return !!(platformConfig as TelegramConfig).botToken && !!(platformConfig as TelegramConfig).chatId;\r\n case 'feishu':\r\n return !!(platformConfig as FeishuConfig).webhookUrl;\r\n case 'dingtalk':\r\n return !!(platformConfig as DingTalkConfig).webhookUrl;\r\n case 'wecom':\r\n return !!(platformConfig as WeComConfig).webhookUrl;\r\n case 'email':\r\n const emailConfig = platformConfig as EmailConfig;\r\n return !!(emailConfig.host && emailConfig.username && emailConfig.password && emailConfig.from && emailConfig.to?.length > 0);\r\n case 'webhook':\r\n return !!(platformConfig as WebhookConfig).url;\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"grid gap-3\">\r\n {platforms.map((platform) => {\r\n const info = PLATFORM_INFO[platform];\r\n const platformConfig = getPlatformConfig(platform);\r\n const configured = isConfigured(platform);\r\n const expanded = expandedPlatform === platform;\r\n\r\n return (\r\n <Card key={platform} className=\"overflow-hidden\">\r\n {/* Header */}\r\n <div\r\n className=\"p-4 cursor-pointer hover:bg-muted/50 transition-colors\"\r\n onClick={() => onToggleExpand(expanded ? null : platform)}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className={cn(\r\n 'p-2 rounded-lg',\r\n platformConfig.enabled && configured\r\n ? 'bg-primary/10 text-primary'\r\n : 'bg-muted text-muted-foreground'\r\n )}>\r\n {getPlatformIcon(platform)}\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium\">{info.name}</span>\r\n {configured && (\r\n <Badge variant=\"outline\" className=\"text-xs text-green-600 border-green-500/30\">\r\n <Check className=\"w-3 h-3 mr-1\" />\r\n {formatMessage({ id: 'settings.remoteNotifications.configured' })}\r\n </Badge>\r\n )}\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-0.5\">{info.description}</p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant={platformConfig.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onUpdateConfig(platform, { enabled: !platformConfig.enabled });\r\n }}\r\n >\r\n {platformConfig.enabled ? (\r\n <Check className=\"w-3.5 h-3.5\" />\r\n ) : (\r\n <X className=\"w-3.5 h-3.5\" />\r\n )}\r\n </Button>\r\n {expanded ? (\r\n <ChevronUp className=\"w-4 h-4 text-muted-foreground\" />\r\n ) : (\r\n <ChevronDown className=\"w-4 h-4 text-muted-foreground\" />\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Expanded Content */}\r\n {expanded && (\r\n <div className=\"border-t border-border p-4 space-y-4 bg-muted/30\">\r\n {platform === 'discord' && (\r\n <DiscordConfigForm\r\n config={platformConfig as DiscordConfig}\r\n onUpdate={(updates) => onUpdateConfig('discord', updates)}\r\n />\r\n )}\r\n {platform === 'telegram' && (\r\n <TelegramConfigForm\r\n config={platformConfig as TelegramConfig}\r\n onUpdate={(updates) => onUpdateConfig('telegram', updates)}\r\n />\r\n )}\r\n {platform === 'feishu' && (\r\n <FeishuConfigForm\r\n config={platformConfig as FeishuConfig}\r\n onUpdate={(updates) => onUpdateConfig('feishu', updates)}\r\n />\r\n )}\r\n {platform === 'dingtalk' && (\r\n <DingTalkConfigForm\r\n config={platformConfig as DingTalkConfig}\r\n onUpdate={(updates) => onUpdateConfig('dingtalk', updates)}\r\n />\r\n )}\r\n {platform === 'wecom' && (\r\n <WeComConfigForm\r\n config={platformConfig as WeComConfig}\r\n onUpdate={(updates) => onUpdateConfig('wecom', updates)}\r\n />\r\n )}\r\n {platform === 'email' && (\r\n <EmailConfigForm\r\n config={platformConfig as EmailConfig}\r\n onUpdate={(updates) => onUpdateConfig('email', updates)}\r\n />\r\n )}\r\n {platform === 'webhook' && (\r\n <WebhookConfigForm\r\n config={platformConfig as WebhookConfig}\r\n onUpdate={(updates) => onUpdateConfig('webhook', updates)}\r\n />\r\n )}\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center gap-2 pt-2\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => onTest(platform, platformConfig)}\r\n disabled={testing === platform || !configured}\r\n >\r\n <TestTube className={cn('w-3.5 h-3.5 mr-1', testing === platform && 'animate-pulse')} />\r\n {formatMessage({ id: 'settings.remoteNotifications.testConnection' })}\r\n </Button>\r\n <Button\r\n variant=\"default\"\r\n size=\"sm\"\r\n onClick={onSave}\r\n disabled={saving}\r\n >\r\n {formatMessage({ id: 'settings.remoteNotifications.save' })}\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n </Card>\r\n );\r\n })}\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Discord Config Form ==========\r\n\r\nfunction DiscordConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: DiscordConfig;\r\n onUpdate: (updates: Partial<DiscordConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showUrl, setShowUrl] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.discord.webhookUrl' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showUrl ? 'text' : 'password'}\r\n value={config.webhookUrl || ''}\r\n onChange={(e) => onUpdate({ webhookUrl: e.target.value })}\r\n placeholder=\"https://discord.com/api/webhooks/...\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowUrl(!showUrl)}\r\n >\r\n {showUrl ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.discord.webhookUrlHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.discord.username' })}\r\n </label>\r\n <Input\r\n value={config.username || ''}\r\n onChange={(e) => onUpdate({ username: e.target.value })}\r\n placeholder=\"CCW Notification\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Telegram Config Form ==========\r\n\r\nfunction TelegramConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: TelegramConfig;\r\n onUpdate: (updates: Partial<TelegramConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showToken, setShowToken] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.telegram.botToken' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showToken ? 'text' : 'password'}\r\n value={config.botToken || ''}\r\n onChange={(e) => onUpdate({ botToken: e.target.value })}\r\n placeholder=\"1234567890:ABCdefGHIjklMNOpqrsTUVwxyz\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowToken(!showToken)}\r\n >\r\n {showToken ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.telegram.botTokenHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.telegram.chatId' })}\r\n </label>\r\n <Input\r\n value={config.chatId || ''}\r\n onChange={(e) => onUpdate({ chatId: e.target.value })}\r\n placeholder=\"-1001234567890\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.telegram.chatIdHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Webhook Config Form ==========\r\n\r\nfunction WebhookConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: WebhookConfig;\r\n onUpdate: (updates: Partial<WebhookConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.webhook.url' })}\r\n </label>\r\n <Input\r\n value={config.url || ''}\r\n onChange={(e) => onUpdate({ url: e.target.value })}\r\n placeholder=\"https://your-server.com/webhook\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.webhook.method' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Button\r\n variant={config.method === 'POST' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => onUpdate({ method: 'POST' })}\r\n >\r\n POST\r\n </Button>\r\n <Button\r\n variant={config.method === 'PUT' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => onUpdate({ method: 'PUT' })}\r\n >\r\n PUT\r\n </Button>\r\n </div>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.webhook.headers' })}\r\n </label>\r\n <Input\r\n value={config.headers ? JSON.stringify(config.headers) : ''}\r\n onChange={(e) => {\r\n try {\r\n const headers = e.target.value ? JSON.parse(e.target.value) : undefined;\r\n onUpdate({ headers });\r\n } catch {\r\n // Invalid JSON, ignore\r\n }\r\n }}\r\n placeholder='{\"Authorization\": \"Bearer token\"}'\r\n className=\"mt-1 font-mono text-xs\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.webhook.headersHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Feishu Config Form ==========\r\n\r\nfunction FeishuConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: FeishuConfig;\r\n onUpdate: (updates: Partial<FeishuConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showUrl, setShowUrl] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.webhookUrl' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showUrl ? 'text' : 'password'}\r\n value={config.webhookUrl || ''}\r\n onChange={(e) => onUpdate({ webhookUrl: e.target.value })}\r\n placeholder=\"https://open.feishu.cn/open-apis/bot/v2/hook/...\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowUrl(!showUrl)}\r\n >\r\n {showUrl ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.webhookUrlHint' })}\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <input\r\n type=\"checkbox\"\r\n id=\"feishu-useCard\"\r\n checked={config.useCard || false}\r\n onChange={(e) => onUpdate({ useCard: e.target.checked })}\r\n className=\"rounded border-border\"\r\n />\r\n <label htmlFor=\"feishu-useCard\" className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.useCard' })}\r\n </label>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground -mt-2\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.useCardHint' })}\r\n </p>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.title' })}\r\n </label>\r\n <Input\r\n value={config.title || ''}\r\n onChange={(e) => onUpdate({ title: e.target.value })}\r\n placeholder=\"CCW Notification\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== DingTalk Config Form ==========\r\n\r\nfunction DingTalkConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: DingTalkConfig;\r\n onUpdate: (updates: Partial<DingTalkConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showUrl, setShowUrl] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.dingtalk.webhookUrl' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showUrl ? 'text' : 'password'}\r\n value={config.webhookUrl || ''}\r\n onChange={(e) => onUpdate({ webhookUrl: e.target.value })}\r\n placeholder=\"https://oapi.dingtalk.com/robot/send?access_token=...\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowUrl(!showUrl)}\r\n >\r\n {showUrl ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.dingtalk.webhookUrlHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.dingtalk.keywords' })}\r\n </label>\r\n <Input\r\n value={config.keywords?.join(', ') || ''}\r\n onChange={(e) => onUpdate({ keywords: e.target.value.split(',').map(k => k.trim()).filter(Boolean) })}\r\n placeholder=\"keyword1, keyword2\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.dingtalk.keywordsHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== WeCom Config Form ==========\r\n\r\nfunction WeComConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: WeComConfig;\r\n onUpdate: (updates: Partial<WeComConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showUrl, setShowUrl] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.wecom.webhookUrl' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showUrl ? 'text' : 'password'}\r\n value={config.webhookUrl || ''}\r\n onChange={(e) => onUpdate({ webhookUrl: e.target.value })}\r\n placeholder=\"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowUrl(!showUrl)}\r\n >\r\n {showUrl ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.wecom.webhookUrlHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.wecom.mentionedList' })}\r\n </label>\r\n <Input\r\n value={config.mentionedList?.join(', ') || ''}\r\n onChange={(e) => onUpdate({ mentionedList: e.target.value.split(',').map(m => m.trim()).filter(Boolean) })}\r\n placeholder=\"userid1, userid2, @all\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.wecom.mentionedListHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Email Config Form ==========\r\n\r\nfunction EmailConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: EmailConfig;\r\n onUpdate: (updates: Partial<EmailConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showPassword, setShowPassword] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div className=\"grid grid-cols-2 gap-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.host' })}\r\n </label>\r\n <Input\r\n value={config.host || ''}\r\n onChange={(e) => onUpdate({ host: e.target.value })}\r\n placeholder=\"smtp.gmail.com\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.hostHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.port' })}\r\n </label>\r\n <Input\r\n type=\"number\"\r\n value={config.port || 587}\r\n onChange={(e) => onUpdate({ port: parseInt(e.target.value, 10) || 587 })}\r\n placeholder=\"587\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <input\r\n type=\"checkbox\"\r\n id=\"email-secure\"\r\n checked={config.secure || false}\r\n onChange={(e) => onUpdate({ secure: e.target.checked })}\r\n className=\"rounded border-border\"\r\n />\r\n <label htmlFor=\"email-secure\" className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.secure' })}\r\n </label>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.username' })}\r\n </label>\r\n <Input\r\n value={config.username || ''}\r\n onChange={(e) => onUpdate({ username: e.target.value })}\r\n placeholder=\"your-email@gmail.com\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.password' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showPassword ? 'text' : 'password'}\r\n value={config.password || ''}\r\n onChange={(e) => onUpdate({ password: e.target.value })}\r\n placeholder=\"********\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowPassword(!showPassword)}\r\n >\r\n {showPassword ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.from' })}\r\n </label>\r\n <Input\r\n value={config.from || ''}\r\n onChange={(e) => onUpdate({ from: e.target.value })}\r\n placeholder=\"noreply@example.com\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.to' })}\r\n </label>\r\n <Input\r\n value={config.to?.join(', ') || ''}\r\n onChange={(e) => onUpdate({ to: e.target.value.split(',').map(t => t.trim()).filter(Boolean) })}\r\n placeholder=\"user1@example.com, user2@example.com\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.toHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default PlatformConfigCards;\r\n","// ========================================\r\n// Remote Notification Settings Section\r\n// ========================================\r\n// Configuration UI for remote notification platforms\r\n\r\nimport { useState, useEffect, useCallback } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport {\r\n Bell,\r\n BellOff,\r\n RefreshCw,\r\n Check,\r\n X,\r\n Save,\r\n ChevronDown,\r\n ChevronUp,\r\n Plus,\r\n} from 'lucide-react';\r\nimport { Card } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { cn } from '@/lib/utils';\r\nimport { toast } from 'sonner';\r\nimport type {\r\n RemoteNotificationConfig,\r\n NotificationPlatform,\r\n EventConfig,\r\n DiscordConfig,\r\n TelegramConfig,\r\n WebhookConfig,\r\n FeishuConfig,\r\n DingTalkConfig,\r\n WeComConfig,\r\n EmailConfig,\r\n} from '@/types/remote-notification';\r\nimport { PLATFORM_INFO, EVENT_INFO, getDefaultConfig } from '@/types/remote-notification';\r\nimport { PlatformConfigCards } from './PlatformConfigCards';\r\n\r\ninterface RemoteNotificationSectionProps {\r\n className?: string;\r\n}\r\n\r\nexport function RemoteNotificationSection({ className }: RemoteNotificationSectionProps) {\r\n const { formatMessage } = useIntl();\r\n const [config, setConfig] = useState<RemoteNotificationConfig | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [testing, setTesting] = useState<NotificationPlatform | null>(null);\r\n const [expandedPlatform, setExpandedPlatform] = useState<NotificationPlatform | null>(null);\r\n const [expandedEvent, setExpandedEvent] = useState<number | null>(null);\r\n\r\n // Load configuration\r\n const loadConfig = useCallback(async () => {\r\n setLoading(true);\r\n try {\r\n const response = await fetch('/api/notifications/remote/config');\r\n if (response.ok) {\r\n const data = await response.json();\r\n setConfig(data);\r\n } else {\r\n // Use default config if not found\r\n setConfig(getDefaultConfig());\r\n }\r\n } catch (error) {\r\n console.error('Failed to load remote notification config:', error);\r\n setConfig(getDefaultConfig());\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n loadConfig();\r\n }, [loadConfig]);\r\n\r\n // Save configuration\r\n const saveConfig = useCallback(async (newConfig: RemoteNotificationConfig) => {\r\n setSaving(true);\r\n try {\r\n const response = await fetch('/api/notifications/remote/config', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(newConfig),\r\n });\r\n\r\n if (response.ok) {\r\n const data = await response.json();\r\n setConfig(data.config);\r\n toast.success(formatMessage({ id: 'settings.remoteNotifications.saved' }));\r\n } else {\r\n throw new Error(`HTTP ${response.status}`);\r\n }\r\n } catch (error) {\r\n toast.error(formatMessage({ id: 'settings.remoteNotifications.saveError' }));\r\n } finally {\r\n setSaving(false);\r\n }\r\n }, [formatMessage]);\r\n\r\n // Test platform\r\n const testPlatform = useCallback(async (\r\n platform: NotificationPlatform,\r\n platformConfig: DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig\r\n ) => {\r\n setTesting(platform);\r\n try {\r\n const response = await fetch('/api/notifications/remote/test', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ platform, config: platformConfig }),\r\n });\r\n\r\n const result = await response.json();\r\n\r\n if (result.success) {\r\n toast.success(\r\n formatMessage({ id: 'settings.remoteNotifications.testSuccess' }),\r\n { description: `${result.responseTime}ms` }\r\n );\r\n } else {\r\n toast.error(\r\n formatMessage({ id: 'settings.remoteNotifications.testFailed' }),\r\n { description: result.error }\r\n );\r\n }\r\n } catch (error) {\r\n toast.error(formatMessage({ id: 'settings.remoteNotifications.testError' }));\r\n } finally {\r\n setTesting(null);\r\n }\r\n }, [formatMessage]);\r\n\r\n // Toggle master switch\r\n const toggleEnabled = () => {\r\n if (!config) return;\r\n saveConfig({ ...config, enabled: !config.enabled });\r\n };\r\n\r\n // Update platform config\r\n const updatePlatformConfig = (\r\n platform: NotificationPlatform,\r\n updates: Partial<DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig>\r\n ) => {\r\n if (!config) return;\r\n const newConfig = {\r\n ...config,\r\n platforms: {\r\n ...config.platforms,\r\n [platform]: {\r\n ...config.platforms[platform as keyof typeof config.platforms],\r\n ...updates,\r\n },\r\n },\r\n };\r\n setConfig(newConfig);\r\n };\r\n\r\n // Update event config\r\n const updateEventConfig = (eventIndex: number, updates: Partial<EventConfig>) => {\r\n if (!config) return;\r\n const newEvents = [...config.events];\r\n newEvents[eventIndex] = { ...newEvents[eventIndex], ...updates };\r\n setConfig({ ...config, events: newEvents });\r\n };\r\n\r\n // Toggle platform for event\r\n const toggleEventPlatform = (eventIndex: number, platform: NotificationPlatform) => {\r\n if (!config) return;\r\n const eventConfig = config.events[eventIndex];\r\n const platforms = eventConfig.platforms.includes(platform)\r\n ? eventConfig.platforms.filter((p) => p !== platform)\r\n : [...eventConfig.platforms, platform];\r\n updateEventConfig(eventIndex, { platforms });\r\n };\r\n\r\n // All available platforms\r\n const allPlatforms: NotificationPlatform[] = ['discord', 'telegram', 'feishu', 'dingtalk', 'wecom', 'email', 'webhook'];\r\n\r\n // Reset to defaults\r\n const resetConfig = async () => {\r\n if (!confirm(formatMessage({ id: 'settings.remoteNotifications.resetConfirm' }))) {\r\n return;\r\n }\r\n try {\r\n const response = await fetch('/api/notifications/remote/reset', {\r\n method: 'POST',\r\n });\r\n if (response.ok) {\r\n const data = await response.json();\r\n setConfig(data.config);\r\n toast.success(formatMessage({ id: 'settings.remoteNotifications.resetSuccess' }));\r\n }\r\n } catch {\r\n toast.error(formatMessage({ id: 'settings.remoteNotifications.resetError' }));\r\n }\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <Card className={cn('p-6', className)}>\r\n <div className=\"flex items-center justify-center py-8\">\r\n <RefreshCw className=\"w-5 h-5 animate-spin text-muted-foreground\" />\r\n </div>\r\n </Card>\r\n );\r\n }\r\n\r\n if (!config) {\r\n return null;\r\n }\r\n\r\n return (\r\n <Card className={cn('p-6', className)}>\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between mb-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2\">\r\n {config.enabled ? (\r\n <Bell className=\"w-5 h-5 text-primary\" />\r\n ) : (\r\n <BellOff className=\"w-5 h-5 text-muted-foreground\" />\r\n )}\r\n {formatMessage({ id: 'settings.remoteNotifications.title' })}\r\n </h2>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => loadConfig()}\r\n disabled={loading}\r\n >\r\n <RefreshCw className={cn('w-3.5 h-3.5', loading && 'animate-spin')} />\r\n </Button>\r\n <Button\r\n variant={config.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={toggleEnabled}\r\n >\r\n {config.enabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.remoteNotifications.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.remoteNotifications.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Description */}\r\n <p className=\"text-sm text-muted-foreground mb-6\">\r\n {formatMessage({ id: 'settings.remoteNotifications.description' })}\r\n </p>\r\n\r\n {config.enabled && (\r\n <>\r\n {/* Platform Configuration */}\r\n <div className=\"space-y-4 mb-6\">\r\n <h3 className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.platforms' })}\r\n </h3>\r\n <PlatformConfigCards\r\n config={config}\r\n expandedPlatform={expandedPlatform}\r\n testing={testing}\r\n onToggleExpand={setExpandedPlatform}\r\n onUpdateConfig={updatePlatformConfig}\r\n onTest={testPlatform}\r\n onSave={() => saveConfig(config)}\r\n saving={saving}\r\n />\r\n </div>\r\n\r\n {/* Event Configuration */}\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.events' })}\r\n </h3>\r\n <div className=\"grid gap-3\">\r\n {config.events.map((eventConfig, index) => {\r\n const info = EVENT_INFO[eventConfig.event];\r\n const isExpanded = expandedEvent === index;\r\n return (\r\n <div\r\n key={eventConfig.event}\r\n className=\"rounded-lg border border-border bg-muted/30 overflow-hidden\"\r\n >\r\n {/* Event Header */}\r\n <div\r\n className=\"flex items-center justify-between p-3 cursor-pointer hover:bg-muted/50 transition-colors\"\r\n onClick={() => setExpandedEvent(isExpanded ? null : index)}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n <div className={cn(\r\n 'p-2 rounded-lg',\r\n eventConfig.enabled ? 'bg-primary/10 text-primary' : 'bg-muted text-muted-foreground'\r\n )}>\r\n <span className=\"text-sm\">{info.icon}</span>\r\n </div>\r\n <div>\r\n <p className=\"text-sm font-medium\">{info.name}</p>\r\n <p className=\"text-xs text-muted-foreground\">{info.description}</p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n {/* Platform badges */}\r\n <div className=\"flex gap-1 flex-wrap max-w-xs\">\r\n {eventConfig.platforms.slice(0, 3).map((platform) => (\r\n <Badge key={platform} variant=\"secondary\" className=\"text-xs\">\r\n {PLATFORM_INFO[platform].name}\r\n </Badge>\r\n ))}\r\n {eventConfig.platforms.length > 3 && (\r\n <Badge variant=\"secondary\" className=\"text-xs\">\r\n +{eventConfig.platforms.length - 3}\r\n </Badge>\r\n )}\r\n {eventConfig.platforms.length === 0 && (\r\n <Badge variant=\"outline\" className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.noPlatforms' })}\r\n </Badge>\r\n )}\r\n </div>\r\n {/* Toggle */}\r\n <Button\r\n variant={eventConfig.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n updateEventConfig(index, { enabled: !eventConfig.enabled });\r\n }}\r\n >\r\n {eventConfig.enabled ? (\r\n <Check className=\"w-3.5 h-3.5\" />\r\n ) : (\r\n <X className=\"w-3.5 h-3.5\" />\r\n )}\r\n </Button>\r\n {/* Expand icon */}\r\n {isExpanded ? (\r\n <ChevronUp className=\"w-4 h-4 text-muted-foreground\" />\r\n ) : (\r\n <ChevronDown className=\"w-4 h-4 text-muted-foreground\" />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Expanded Content - Platform Selection */}\r\n {isExpanded && (\r\n <div className=\"border-t border-border p-4 space-y-3 bg-muted/20\">\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.selectPlatforms' })}\r\n </p>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {allPlatforms.map((platform) => {\r\n const isSelected = eventConfig.platforms.includes(platform);\r\n const platformInfo = PLATFORM_INFO[platform];\r\n const platformConfig = config.platforms[platform];\r\n const isConfigured = platformConfig?.enabled;\r\n return (\r\n <Button\r\n key={platform}\r\n variant={isSelected ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className={cn(\r\n 'h-8',\r\n !isConfigured && !isSelected && 'opacity-50'\r\n )}\r\n onClick={() => toggleEventPlatform(index, platform)}\r\n >\r\n {isSelected && <Check className=\"w-3 h-3 mr-1\" />}\r\n {platformInfo.name}\r\n {!isConfigured && !isSelected && (\r\n <Plus className=\"w-3 h-3 ml-1 opacity-50\" />\r\n )}\r\n </Button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center justify-between mt-6 pt-4 border-t border-border\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={resetConfig}\r\n >\r\n {formatMessage({ id: 'settings.remoteNotifications.reset' })}\r\n </Button>\r\n <Button\r\n variant=\"default\"\r\n size=\"sm\"\r\n onClick={() => saveConfig(config)}\r\n disabled={saving}\r\n >\r\n <Save className=\"w-4 h-4 mr-1\" />\r\n {saving\r\n ? formatMessage({ id: 'settings.remoteNotifications.saving' })\r\n : formatMessage({ id: 'settings.remoteNotifications.save' })}\r\n </Button>\r\n </div>\r\n </>\r\n )}\r\n </Card>\r\n );\r\n}\r\n\r\nexport default RemoteNotificationSection;\r\n","// ========================================\n// A2UI Preferences Section\n// ========================================\n// Settings section for A2UI dialog style preferences\n\nimport { useIntl } from 'react-intl';\nimport { MessageSquare, Clock, Volume2, LayoutPanelLeft, Sparkles } from 'lucide-react';\nimport { Card } from '@/components/ui/Card';\nimport { Button } from '@/components/ui/Button';\nimport { Label } from '@/components/ui/Label';\nimport { cn } from '@/lib/utils';\nimport { useDialogStyleContext, type DialogStyle } from '@/contexts/DialogStyleContext';\n\n// ========== Style Option Button ==========\n\ninterface StyleOptionProps {\n value: DialogStyle;\n label: string;\n description: string;\n selected: boolean;\n onClick: () => void;\n}\n\nfunction StyleOption({ value, label, description, selected, onClick }: StyleOptionProps) {\n const icons: Record<DialogStyle, React.ReactNode> = {\n modal: (\n <div className=\"w-8 h-8 border-2 border-current rounded-lg flex items-center justify-center\">\n <div className=\"w-4 h-3 border border-current rounded-sm\" />\n </div>\n ),\n drawer: (\n <div className=\"w-8 h-8 border-2 border-current rounded-lg flex items-end justify-end p-0.5\">\n <div className=\"w-2 h-6 border border-current rounded-sm\" />\n </div>\n ),\n sheet: (\n <div className=\"w-8 h-8 border-2 border-current rounded-lg flex items-end justify-center p-0.5\">\n <div className=\"w-6 h-2 border border-current rounded-sm\" />\n </div>\n ),\n fullscreen: (\n <div className=\"w-8 h-8 border-2 border-current rounded-lg flex items-center justify-center\">\n <div className=\"w-5 h-4 border border-current rounded-sm\" />\n </div>\n ),\n };\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n 'flex flex-col items-center gap-2 p-3 rounded-lg border-2 transition-all',\n 'hover:bg-accent/50',\n selected\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border text-muted-foreground'\n )}\n >\n {icons[value]}\n <div className=\"text-center\">\n <div className={cn('text-sm font-medium', selected && 'text-primary')}>{label}</div>\n <div className=\"text-xs text-muted-foreground\">{description}</div>\n </div>\n </button>\n );\n}\n\n// ========== Duration Slider ==========\n\ninterface DurationSliderProps {\n value: number;\n onChange: (value: number) => void;\n disabled?: boolean;\n}\n\nfunction DurationSlider({ value, onChange, disabled }: DurationSliderProps) {\n const presets = [10, 20, 30, 45, 60, 90, 120];\n\n return (\n <div className=\"flex flex-wrap gap-2\">\n {presets.map((seconds) => (\n <Button\n key={seconds}\n type=\"button\"\n variant={value === seconds ? 'default' : 'outline'}\n size=\"sm\"\n disabled={disabled}\n onClick={() => onChange(seconds)}\n >\n {seconds}s\n </Button>\n ))}\n </div>\n );\n}\n\n// ========== Main Component ==========\n\nexport function A2UIPreferencesSection() {\n const { formatMessage } = useIntl();\n const { preferences, updatePreference, resetPreferences } = useDialogStyleContext();\n\n const styleOptions: Array<{ value: DialogStyle; label: string; description: string }> = [\n {\n value: 'modal',\n label: formatMessage({ id: 'settings.a2ui.styleModal', defaultMessage: 'Modal' }),\n description: formatMessage({ id: 'settings.a2ui.styleModalDesc', defaultMessage: 'Centered' }),\n },\n {\n value: 'drawer',\n label: formatMessage({ id: 'settings.a2ui.styleDrawer', defaultMessage: 'Drawer' }),\n description: formatMessage({ id: 'settings.a2ui.styleDrawerDesc', defaultMessage: 'Side panel' }),\n },\n {\n value: 'sheet',\n label: formatMessage({ id: 'settings.a2ui.styleSheet', defaultMessage: 'Sheet' }),\n description: formatMessage({ id: 'settings.a2ui.styleSheetDesc', defaultMessage: 'Bottom' }),\n },\n {\n value: 'fullscreen',\n label: formatMessage({ id: 'settings.a2ui.styleFullscreen', defaultMessage: 'Fullscreen' }),\n description: formatMessage({ id: 'settings.a2ui.styleFullscreenDesc', defaultMessage: 'Full screen' }),\n },\n ];\n\n return (\n <Card className=\"p-6\">\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\n <MessageSquare className=\"w-5 h-5\" />\n {formatMessage({ id: 'settings.sections.a2ui', defaultMessage: 'A2UI Preferences' })}\n </h2>\n\n <div className=\"space-y-6\">\n {/* Dialog Style Selection */}\n <div className=\"space-y-3\">\n <Label className=\"text-sm font-medium flex items-center gap-2\">\n <LayoutPanelLeft className=\"w-4 h-4\" />\n {formatMessage({ id: 'settings.a2ui.dialogStyle', defaultMessage: 'Dialog Style' })}\n </Label>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.dialogStyleDesc',\n defaultMessage: 'Choose how A2UI dialogs are displayed',\n })}\n </p>\n <div className=\"grid grid-cols-4 gap-2\">\n {styleOptions.map((option) => (\n <StyleOption\n key={option.value}\n value={option.value}\n label={option.label}\n description={option.description}\n selected={preferences.dialogStyle === option.value}\n onClick={() => updatePreference('dialogStyle', option.value)}\n />\n ))}\n </div>\n </div>\n\n {/* Smart Mode */}\n <div className=\"flex items-center justify-between py-2 border-t border-border\">\n <div className=\"flex items-center gap-2\">\n <Sparkles className=\"w-4 h-4 text-muted-foreground\" />\n <div>\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.smartMode', defaultMessage: 'Smart Mode' })}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.smartModeDesc',\n defaultMessage: 'Auto-select style based on question type',\n })}\n </p>\n </div>\n </div>\n <Button\n variant={preferences.smartModeEnabled ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => updatePreference('smartModeEnabled', !preferences.smartModeEnabled)}\n >\n {preferences.smartModeEnabled\n ? formatMessage({ id: 'common.enabled', defaultMessage: 'Enabled' })\n : formatMessage({ id: 'common.disabled', defaultMessage: 'Disabled' })}\n </Button>\n </div>\n\n {/* Auto Selection Duration */}\n <div className=\"space-y-3 py-2 border-t border-border\">\n <div className=\"flex items-center gap-2\">\n <Clock className=\"w-4 h-4 text-muted-foreground\" />\n <Label className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.autoSelectionDuration', defaultMessage: 'Auto-Selection Duration' })}\n </Label>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.autoSelectionDurationDesc',\n defaultMessage: 'Countdown before auto-selecting default option',\n })}\n </p>\n <DurationSlider\n value={preferences.autoSelectionDuration}\n onChange={(v) => updatePreference('autoSelectionDuration', v)}\n />\n </div>\n\n {/* Pause on Interaction */}\n <div className=\"flex items-center justify-between py-2 border-t border-border\">\n <div>\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.pauseOnInteraction', defaultMessage: 'Pause on Interaction' })}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.pauseOnInteractionDesc',\n defaultMessage: 'Pause countdown when you interact with the dialog',\n })}\n </p>\n </div>\n <Button\n variant={preferences.pauseOnInteraction ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => updatePreference('pauseOnInteraction', !preferences.pauseOnInteraction)}\n >\n {preferences.pauseOnInteraction\n ? formatMessage({ id: 'common.enabled', defaultMessage: 'Enabled' })\n : formatMessage({ id: 'common.disabled', defaultMessage: 'Disabled' })}\n </Button>\n </div>\n\n {/* Sound Notification */}\n <div className=\"flex items-center justify-between py-2 border-t border-border\">\n <div className=\"flex items-center gap-2\">\n <Volume2 className=\"w-4 h-4 text-muted-foreground\" />\n <div>\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.soundNotification', defaultMessage: 'Sound Notification' })}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.soundNotificationDesc',\n defaultMessage: 'Play sound before auto-submit (3 seconds before)',\n })}\n </p>\n </div>\n </div>\n <Button\n variant={preferences.autoSelectionSoundEnabled ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => updatePreference('autoSelectionSoundEnabled', !preferences.autoSelectionSoundEnabled)}\n >\n {preferences.autoSelectionSoundEnabled\n ? formatMessage({ id: 'common.enabled', defaultMessage: 'Enabled' })\n : formatMessage({ id: 'common.disabled', defaultMessage: 'Disabled' })}\n </Button>\n </div>\n\n {/* Show A2UI Button in Toolbar */}\n <div className=\"flex items-center justify-between py-2 border-t border-border\">\n <div>\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.showToolbarButton', defaultMessage: 'Show Toolbar Button' })}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.showToolbarButtonDesc',\n defaultMessage: 'Show A2UI quick action button in the toolbar',\n })}\n </p>\n </div>\n <Button\n variant={preferences.showA2UIButtonInToolbar ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => updatePreference('showA2UIButtonInToolbar', !preferences.showA2UIButtonInToolbar)}\n >\n {preferences.showA2UIButtonInToolbar\n ? formatMessage({ id: 'common.enabled', defaultMessage: 'Enabled' })\n : formatMessage({ id: 'common.disabled', defaultMessage: 'Disabled' })}\n </Button>\n </div>\n\n {/* Reset Button */}\n <div className=\"flex justify-end pt-4 border-t border-border\">\n <Button variant=\"outline\" size=\"sm\" onClick={resetPreferences}>\n {formatMessage({ id: 'common.resetToDefaults', defaultMessage: 'Reset to Defaults' })}\n </Button>\n </div>\n </div>\n </Card>\n );\n}\n\nexport default A2UIPreferencesSection;\n","// ========================================\r\n// Settings Page\r\n// ========================================\r\n// Application settings and configuration with CLI tools management\r\n\r\nimport { useState, useCallback, useEffect, useRef } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport {\r\n Settings,\r\n Moon,\r\n Bell,\r\n Cpu,\r\n RefreshCw,\r\n RotateCcw,\r\n Check,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n Languages,\r\n Plus,\r\n MessageSquareText,\r\n Monitor,\r\n Terminal,\r\n AlertTriangle,\r\n Package,\r\n Home,\r\n Folder,\r\n FolderOpen,\r\n Calendar,\r\n File,\r\n ArrowUpCircle,\r\n Save,\r\n Download,\r\n Upload,\r\n} from 'lucide-react';\r\nimport { Card } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { ThemeSelector } from '@/components/shared/ThemeSelector';\r\nimport { useTheme } from '@/hooks';\r\nimport { toast } from 'sonner';\r\nimport { useConfigStore, selectCliTools, selectDefaultCliTool, selectUserPreferences } from '@/stores/configStore';\r\nimport type { CliToolConfig, UserPreferences } from '@/types/store';\r\nimport { cn } from '@/lib/utils';\r\nimport { LanguageSwitcher } from '@/components/layout/LanguageSwitcher';\r\nimport {\r\n useChineseResponseStatus,\r\n useToggleChineseResponse,\r\n useWindowsPlatformStatus,\r\n useToggleWindowsPlatform,\r\n useCodexCliEnhancementStatus,\r\n useToggleCodexCliEnhancement,\r\n useRefreshCodexCliEnhancement,\r\n useCcwInstallStatus,\r\n useCliToolStatus,\r\n useCcwInstallations,\r\n useUpgradeCcwInstallation,\r\n useExportSettings,\r\n useImportSettings,\r\n} from '@/hooks/useSystemSettings';\r\nimport type { ExportedSettings } from '@/lib/api';\r\nimport { RemoteNotificationSection } from '@/components/settings/RemoteNotificationSection';\r\nimport { A2UIPreferencesSection } from '@/components/settings/A2UIPreferencesSection';\r\n\r\n// ========== CSRF Token Helper ==========\r\nfunction getCsrfToken(): string | null {\r\n const match = document.cookie.match(/XSRF-TOKEN=([^;]+)/);\r\n return match ? decodeURIComponent(match[1]) : null;\r\n}\r\n\r\n// ========== File Path Input with Native File Picker ==========\r\n\r\nimport { useDebounce } from '@/hooks/useDebounce';\r\nimport { Loader2 } from 'lucide-react';\r\n\r\n// ...\r\n\r\ninterface FilePathInputProps {\r\n value: string;\r\n onChange: (value: string) => void;\r\n placeholder: string;\r\n}\r\n\r\nfunction FilePathInput({ value, onChange, placeholder }: FilePathInputProps) {\r\n const [isValidating, setIsValidating] = useState(false);\r\n const [pathError, setPathError] = useState<string | null>(null);\r\n const debouncedValue = useDebounce(value, 500);\r\n\r\n useEffect(() => {\r\n if (debouncedValue) {\r\n setIsValidating(true);\r\n setPathError(null);\r\n // Simulate async validation\r\n const timeoutId = setTimeout(() => {\r\n // Simple validation: check if path is not empty.\r\n // In a real scenario, this would check for path existence.\r\n if (debouncedValue.trim().length > 0) {\r\n setPathError(null);\r\n } else {\r\n setPathError('Path cannot be empty.');\r\n }\r\n setIsValidating(false);\r\n }, 1000);\r\n\r\n return () => clearTimeout(timeoutId);\r\n } else {\r\n setPathError(null);\r\n setIsValidating(false);\r\n }\r\n }, [debouncedValue]);\r\n\r\n const handleBrowse = async () => {\r\n const { selectFile } = await import('@/lib/nativeDialog');\r\n const initialDir = value ? value.replace(/[/\\\\][^/\\\\]*$/, '') : undefined;\r\n const result = await selectFile(initialDir);\r\n if (result.path && !result.cancelled && !result.error) {\r\n onChange(result.path);\r\n }\r\n };\r\n\r\n return (\r\n <div>\r\n <div className=\"flex gap-2 items-center\">\r\n <div className=\"relative flex-1\">\r\n <Input\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n placeholder={placeholder}\r\n className={cn(\r\n \"flex-1\",\r\n pathError && \"border-destructive\"\r\n )}\r\n />\r\n {isValidating && (\r\n <div className=\"absolute inset-y-0 right-0 flex items-center pr-3\">\r\n <Loader2 className=\"h-4 w-4 animate-spin text-muted-foreground\" />\r\n </div>\r\n )}\r\n </div>\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0 h-9\"\r\n onClick={handleBrowse}\r\n title=\"Browse\"\r\n >\r\n <FolderOpen className=\"w-4 h-4\" />\r\n </Button>\r\n </div>\r\n {pathError && (\r\n <p className=\"text-xs text-destructive mt-1\">{pathError}</p>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Tool Config File Helpers ==========\r\n\r\n/** Tools that use .env file for environment variables */\r\nconst ENV_FILE_TOOLS = new Set(['gemini', 'qwen', 'opencode']);\r\n/** Tools that use --settings for Claude CLI settings file */\r\nconst SETTINGS_FILE_TOOLS = new Set(['claude']);\r\nfunction getConfigFileType(toolId: string): 'envFile' | 'settingsFile' | 'none' {\r\n if (ENV_FILE_TOOLS.has(toolId)) return 'envFile';\r\n if (SETTINGS_FILE_TOOLS.has(toolId)) return 'settingsFile';\r\n return 'none';\r\n}\r\n\r\n// ========== CLI Tool Card Component ==========\r\n\r\ninterface CliToolCardProps {\r\n toolId: string;\r\n config: CliToolConfig;\r\n isDefault: boolean;\r\n isExpanded: boolean;\r\n toolAvailable?: boolean;\r\n isSaving?: boolean;\r\n onToggleExpand: () => void;\r\n onToggleEnabled: () => void;\r\n onSetDefault: () => void;\r\n onUpdateModel: (field: 'primaryModel' | 'secondaryModel', value: string) => void;\r\n onUpdateTags: (tags: string[]) => void;\r\n onUpdateAvailableModels: (models: string[]) => void;\r\n onUpdateEnvFile: (envFile: string | undefined) => void;\r\n onUpdateSettingsFile: (settingsFile: string | undefined) => void;\r\n onUpdateEffort: (effort: string | undefined) => void;\r\n onSaveToBackend: () => void;\r\n}\r\n\r\nfunction CliToolCard({\r\n toolId,\r\n config,\r\n isDefault,\r\n isExpanded,\r\n toolAvailable,\r\n isSaving,\r\n onToggleExpand,\r\n onToggleEnabled,\r\n onSetDefault,\r\n onUpdateModel,\r\n onUpdateTags,\r\n onUpdateAvailableModels,\r\n onUpdateEnvFile,\r\n onUpdateSettingsFile,\r\n onUpdateEffort,\r\n onSaveToBackend,\r\n}: CliToolCardProps) {\r\n const { formatMessage } = useIntl();\r\n\r\n // Local state for tag and model input\r\n const [tagInput, setTagInput] = useState('');\r\n const [modelInput, setModelInput] = useState('');\r\n\r\n // Handler for adding tags\r\n const handleAddTag = () => {\r\n const newTag = tagInput.trim();\r\n if (newTag && !config.tags.includes(newTag)) {\r\n onUpdateTags([...config.tags, newTag]);\r\n setTagInput('');\r\n }\r\n };\r\n\r\n // Handler for removing tags\r\n const handleRemoveTag = (tagToRemove: string) => {\r\n onUpdateTags(config.tags.filter((t) => t !== tagToRemove));\r\n };\r\n\r\n // Handler for adding available models\r\n const handleAddModel = () => {\r\n const newModel = modelInput.trim();\r\n const currentModels = config.availableModels || [];\r\n if (newModel && !currentModels.includes(newModel)) {\r\n onUpdateAvailableModels([...currentModels, newModel]);\r\n setModelInput('');\r\n }\r\n };\r\n\r\n // Handler for removing available models\r\n const handleRemoveModel = (modelToRemove: string) => {\r\n const currentModels = config.availableModels || [];\r\n onUpdateAvailableModels(currentModels.filter((m) => m !== modelToRemove));\r\n };\r\n\r\n // Predefined tags\r\n const predefinedTags = ['分析', 'Debug', 'implementation', 'refactoring', 'testing'];\r\n\r\n const configFileType = getConfigFileType(toolId);\r\n\r\n return (\r\n <Card className={cn('overflow-hidden', !config.enabled && 'opacity-60')}>\r\n {/* Header */}\r\n <div\r\n className=\"p-4 cursor-pointer hover:bg-muted/50 transition-colors\"\r\n onClick={onToggleExpand}\r\n >\r\n <div className=\"flex items-center justify-between gap-2\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className={cn(\r\n 'p-2 rounded-lg',\r\n config.enabled ? 'bg-primary/10' : 'bg-muted'\r\n )}>\r\n <Cpu className={cn(\r\n 'w-5 h-5',\r\n config.enabled ? 'text-primary' : 'text-muted-foreground'\r\n )} />\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium text-foreground capitalize\">\r\n {toolId}\r\n </span>\r\n {isDefault && (\r\n <Badge variant=\"default\" className=\"text-xs\">{formatMessage({ id: 'settings.cliTools.default' })}</Badge>\r\n )}\r\n <Badge variant=\"outline\" className=\"text-xs\">{config.type}</Badge>\r\n {toolAvailable !== undefined && (\r\n <span className={cn(\r\n 'inline-block w-2 h-2 rounded-full',\r\n toolAvailable ? 'bg-green-500' : 'bg-red-400'\r\n )} title={toolAvailable ? 'Available' : 'Unavailable'} />\r\n )}\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-0.5\">\r\n {config.primaryModel}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant={config.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-8\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onToggleEnabled();\r\n }}\r\n >\r\n {config.enabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.cliTools.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.cliTools.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n {isExpanded ? (\r\n <ChevronUp className=\"w-5 h-5 text-muted-foreground\" />\r\n ) : (\r\n <ChevronDown className=\"w-5 h-5 text-muted-foreground\" />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Tags */}\r\n {config.tags && config.tags.length > 0 && (\r\n <div className=\"flex flex-wrap gap-1 mt-2\">\r\n {config.tags.map((tag) => (\r\n <Badge key={tag} variant=\"secondary\" className=\"text-xs\">\r\n {tag}\r\n </Badge>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Expanded Content */}\r\n {isExpanded && (\r\n <div className=\"border-t border-border p-4 space-y-4 bg-muted/30\">\r\n <div className=\"grid gap-4 md:grid-cols-2\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">{formatMessage({ id: 'settings.cliTools.primaryModel' })}</label>\r\n <Input\r\n value={config.primaryModel}\r\n onChange={(e) => onUpdateModel('primaryModel', e.target.value)}\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">{formatMessage({ id: 'settings.cliTools.secondaryModel' })}</label>\r\n <Input\r\n value={config.secondaryModel}\r\n onChange={(e) => onUpdateModel('secondaryModel', e.target.value)}\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Tags Section */}\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.tags' })}\r\n </label>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.tagsDescription' })}\r\n </p>\r\n <div className=\"flex gap-2\">\r\n <div className=\"flex-1 flex flex-wrap gap-1.5 p-2 border border-input bg-background rounded-md min-h-[38px] focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2\">\r\n {config.tags.map((tag) => (\r\n <span\r\n key={tag}\r\n className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-primary/10 text-primary rounded text-xs h-6\"\r\n >\r\n {tag}\r\n <button\r\n type=\"button\"\r\n onClick={() => handleRemoveTag(tag)}\r\n className=\"hover:text-destructive transition-colors\"\r\n aria-label={formatMessage({ id: 'apiSettings.cliSettings.removeTag' })}\r\n >\r\n <X className=\"w-3 h-3\" />\r\n </button>\r\n </span>\r\n ))}\r\n <input\r\n type=\"text\"\r\n value={tagInput}\r\n onChange={(e) => setTagInput(e.target.value)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n handleAddTag();\r\n }\r\n }}\r\n placeholder={config.tags.length === 0 ? formatMessage({ id: 'apiSettings.cliSettings.tagInputPlaceholder' }) : ''}\r\n className=\"flex-1 min-w-[120px] bg-transparent border-0 outline-none text-sm placeholder:text-muted-foreground\"\r\n />\r\n </div>\r\n <Button\r\n type=\"button\"\r\n size=\"sm\"\r\n onClick={handleAddTag}\r\n variant=\"outline\"\r\n className=\"shrink-0\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n </Button>\r\n </div>\r\n {/* Predefined Tags */}\r\n <div className=\"flex flex-wrap gap-1\">\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.predefinedTags' })}:\r\n </span>\r\n {predefinedTags.map((predefinedTag) => (\r\n <button\r\n key={predefinedTag}\r\n type=\"button\"\r\n onClick={() => {\r\n if (!config.tags.includes(predefinedTag)) {\r\n onUpdateTags([...config.tags, predefinedTag]);\r\n }\r\n }}\r\n disabled={config.tags.includes(predefinedTag)}\r\n className=\"text-xs px-2 py-0.5 rounded border border-border hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {predefinedTag}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Available Models Section */}\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.availableModels' })}\r\n </label>\r\n <div className=\"flex gap-2\">\r\n <div className=\"flex-1 flex flex-wrap gap-1.5 p-2 border border-input bg-background rounded-md min-h-[38px] focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2\">\r\n {(config.availableModels || []).map((model) => (\r\n <span\r\n key={model}\r\n className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-primary/10 text-primary rounded text-xs h-6\"\r\n >\r\n {model}\r\n <button\r\n type=\"button\"\r\n onClick={() => handleRemoveModel(model)}\r\n className=\"hover:text-destructive transition-colors\"\r\n >\r\n <X className=\"w-3 h-3\" />\r\n </button>\r\n </span>\r\n ))}\r\n <input\r\n type=\"text\"\r\n value={modelInput}\r\n onChange={(e) => setModelInput(e.target.value)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n handleAddModel();\r\n }\r\n }}\r\n placeholder={(config.availableModels || []).length === 0 ? formatMessage({ id: 'apiSettings.cliSettings.availableModelsPlaceholder' }) : ''}\r\n className=\"flex-1 min-w-[120px] bg-transparent border-0 outline-none text-sm placeholder:text-muted-foreground\"\r\n />\r\n </div>\r\n <Button\r\n type=\"button\"\r\n size=\"sm\"\r\n onClick={handleAddModel}\r\n variant=\"outline\"\r\n className=\"shrink-0\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.availableModelsHint' })}\r\n </p>\r\n </div>\r\n\r\n {/* Env File - for gemini/qwen/opencode */}\r\n {configFileType === 'envFile' && (\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.cliTools.envFile' })}\r\n </label>\r\n <FilePathInput\r\n value={config.envFile || ''}\r\n onChange={(v) => onUpdateEnvFile(v || undefined)}\r\n placeholder={formatMessage({ id: 'settings.cliTools.envFilePlaceholder' })}\r\n />\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.cliTools.envFileHint' })}\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Settings File - for claude only */}\r\n {configFileType === 'settingsFile' && (\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.settingsFile' })}\r\n </label>\r\n <FilePathInput\r\n value={config.settingsFile || ''}\r\n onChange={(v) => onUpdateSettingsFile(v || undefined)}\r\n placeholder={formatMessage({ id: 'apiSettings.cliSettings.settingsFilePlaceholder' })}\r\n />\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.settingsFileHint' })}\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Effort Level - for claude only */}\r\n {configFileType === 'settingsFile' && (\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.cliTools.effort' })}\r\n </label>\r\n <div className=\"flex gap-2\">\r\n {(['low', 'medium', 'high'] as const).map((level) => {\r\n const effectiveEffort = config.effort || 'high';\r\n const labelId = `settings.cliTools.effort${level.charAt(0).toUpperCase() + level.slice(1)}` as const;\r\n return (\r\n <button\r\n key={level}\r\n type=\"button\"\r\n onClick={() => onUpdateEffort(level === 'high' && !config.effort ? undefined : level)}\r\n className={cn(\r\n 'px-3 py-1.5 rounded-md text-sm border transition-colors',\r\n effectiveEffort === level\r\n ? 'bg-primary text-primary-foreground border-primary'\r\n : 'border-border hover:bg-muted'\r\n )}\r\n >\r\n {formatMessage({ id: labelId })}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.cliTools.effortHint' })}\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center gap-2\">\r\n {!isDefault && config.enabled && (\r\n <Button variant=\"outline\" size=\"sm\" onClick={onSetDefault}>\r\n {formatMessage({ id: 'settings.cliTools.setDefault' })}\r\n </Button>\r\n )}\r\n <Button\r\n variant=\"default\"\r\n size=\"sm\"\r\n onClick={onSaveToBackend}\r\n disabled={isSaving}\r\n >\r\n <Save className=\"w-4 h-4 mr-1\" />\r\n {isSaving\r\n ? formatMessage({ id: 'settings.cliTools.saving' })\r\n : formatMessage({ id: 'settings.cliTools.saveToConfig' })}\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n </Card>\r\n );\r\n}\r\n\r\n// ========== Response Language Section ==========\r\n\r\nfunction ResponseLanguageSection() {\r\n const { formatMessage } = useIntl();\r\n const { data: chineseStatus, isLoading: chineseLoading } = useChineseResponseStatus();\r\n const { toggle: toggleChinese, isPending: chineseToggling } = useToggleChineseResponse();\r\n const { data: windowsStatus, isLoading: windowsLoading } = useWindowsPlatformStatus();\r\n const { toggle: toggleWindows, isPending: windowsToggling } = useToggleWindowsPlatform();\r\n const { data: cliEnhStatus, isLoading: cliEnhLoading } = useCodexCliEnhancementStatus();\r\n const { toggle: toggleCliEnh, isPending: cliEnhToggling } = useToggleCodexCliEnhancement();\r\n const { refresh: refreshCliEnh, isPending: refreshing } = useRefreshCodexCliEnhancement();\r\n const { exportSettings: doExport, isPending: exporting } = useExportSettings();\r\n const { importSettings: doImport, isPending: importing } = useImportSettings();\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n\r\n const handleExport = useCallback(async () => {\r\n try {\r\n const data = await doExport();\r\n const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement('a');\r\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);\r\n a.href = url;\r\n a.download = `ccw-settings-${timestamp}.json`;\r\n document.body.appendChild(a);\r\n a.click();\r\n document.body.removeChild(a);\r\n URL.revokeObjectURL(url);\r\n toast.success(formatMessage({ id: 'settings.responseLanguage.exportSuccess' }));\r\n } catch (error) {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.exportError' }));\r\n }\r\n }, [doExport, formatMessage]);\r\n\r\n const handleFileImport = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const file = e.target.files?.[0];\r\n if (!file) return;\r\n\r\n // Reset file input so the same file can be re-selected\r\n e.target.value = '';\r\n\r\n // Validate file type\r\n if (!file.name.endsWith('.json') && file.type !== 'application/json') {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importInvalidFile' }));\r\n return;\r\n }\r\n\r\n try {\r\n const text = await file.text();\r\n const data = JSON.parse(text) as ExportedSettings;\r\n\r\n // Validate basic structure\r\n if (!data.version || !data.settings) {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importInvalidStructure' }));\r\n return;\r\n }\r\n\r\n const result = await doImport(data);\r\n\r\n if (result.success) {\r\n toast.success(\r\n formatMessage(\r\n { id: 'settings.responseLanguage.importSuccess' },\r\n { imported: result.imported, skipped: result.skipped }\r\n )\r\n );\r\n } else {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importError' }));\r\n }\r\n } catch (error) {\r\n if (error instanceof SyntaxError) {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importInvalidJson' }));\r\n } else {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importError' }));\r\n }\r\n }\r\n }, [doImport, formatMessage]);\r\n\r\n return (\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <MessageSquareText className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.sections.responseLanguage' })}\r\n </h2>\r\n <div className=\"grid gap-4 md:grid-cols-2\">\r\n {/* Chinese Response - Claude */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.responseLanguage.chineseClaude' })}</span>\r\n <Badge variant=\"default\" className=\"text-xs\">Claude</Badge>\r\n </div>\r\n <Button\r\n variant={chineseStatus?.claudeEnabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={chineseLoading || chineseToggling}\r\n onClick={() => toggleChinese(!chineseStatus?.claudeEnabled, 'claude')}\r\n >\r\n {chineseStatus?.claudeEnabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.chineseClaudeDesc' })}\r\n </p>\r\n </div>\r\n\r\n {/* Chinese Response - Codex */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.responseLanguage.chineseCodex' })}</span>\r\n <Badge variant=\"secondary\" className=\"text-xs\">Codex</Badge>\r\n </div>\r\n <Button\r\n variant={chineseStatus?.codexEnabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={chineseLoading || chineseToggling}\r\n onClick={() => toggleChinese(!chineseStatus?.codexEnabled, 'codex')}\r\n >\r\n {chineseStatus?.codexEnabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.chineseCodexDesc' })}\r\n </p>\r\n {chineseStatus?.codexNeedsMigration && (\r\n <p className=\"text-xs text-yellow-500\">\r\n <AlertTriangle className=\"w-3 h-3 inline mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.migrationWarning' })}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {/* Windows Platform */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <Monitor className=\"w-4 h-4 text-muted-foreground\" />\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.responseLanguage.windowsPlatform' })}</span>\r\n </div>\r\n <Button\r\n variant={windowsStatus?.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={windowsLoading || windowsToggling}\r\n onClick={() => toggleWindows(!windowsStatus?.enabled)}\r\n >\r\n {windowsStatus?.enabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.windowsPlatformDesc' })}\r\n </p>\r\n </div>\r\n\r\n {/* CLI Enhancement - Codex */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <Terminal className=\"w-4 h-4 text-muted-foreground\" />\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.responseLanguage.cliEnhancement' })}</span>\r\n <Badge variant=\"secondary\" className=\"text-xs\">Codex</Badge>\r\n </div>\r\n <div className=\"flex items-center gap-1\">\r\n {cliEnhStatus?.enabled && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className=\"h-7 w-7 p-0\"\r\n disabled={cliEnhLoading || refreshing}\r\n onClick={() => refreshCliEnh()}\r\n title={formatMessage({ id: 'settings.responseLanguage.refreshConfig' })}\r\n >\r\n <RefreshCw className={cn('w-3.5 h-3.5', refreshing && 'animate-spin')} />\r\n </Button>\r\n )}\r\n <Button\r\n variant={cliEnhStatus?.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={cliEnhLoading || cliEnhToggling}\r\n onClick={() => toggleCliEnh(!cliEnhStatus?.enabled)}\r\n >\r\n {cliEnhStatus?.enabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.cliEnhancementDesc' })}\r\n </p>\r\n {cliEnhStatus?.enabled && (\r\n <p className=\"text-xs text-muted-foreground/70\">\r\n {formatMessage({ id: 'settings.responseLanguage.cliEnhancementHint' })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Export/Import Actions */}\r\n <div className=\"mt-4 pt-4 border-t border-border\">\r\n <div className=\"flex items-center justify-between\">\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.exportImportHint' })}\r\n </p>\r\n <div className=\"flex items-center gap-2\">\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept=\".json,application/json\"\r\n onChange={handleFileImport}\r\n className=\"hidden\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={importing}\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n {importing ? (\r\n <>\r\n <div className=\"w-3.5 h-3.5 border-2 border-border border-t-accent rounded-full animate-spin mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.importing' })}\r\n </>\r\n ) : (\r\n <>\r\n <Upload className=\"w-3.5 h-3.5 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.import' })}\r\n </>\r\n )}\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={exporting}\r\n onClick={handleExport}\r\n >\r\n {exporting ? (\r\n <>\r\n <div className=\"w-3.5 h-3.5 border-2 border-border border-t-accent rounded-full animate-spin mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.exporting' })}\r\n </>\r\n ) : (\r\n <>\r\n <Download className=\"w-3.5 h-3.5 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.export' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n </div>\r\n </Card>\r\n );\r\n}\r\n\r\n// ========== Version Check Section ==========\r\n\r\ninterface VersionData {\r\n currentVersion: string;\r\n latestVersion: string;\r\n hasUpdate: boolean;\r\n packageName: string;\r\n updateCommand: string;\r\n checkedAt: string;\r\n}\r\n\r\nfunction VersionCheckSection() {\r\n const { formatMessage } = useIntl();\r\n const [versionData, setVersionData] = useState<VersionData | null>(null);\r\n const [checking, setChecking] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [lastChecked, setLastChecked] = useState<Date | null>(null);\r\n const [autoCheck, setAutoCheck] = useState(() => {\r\n try {\r\n const saved = localStorage.getItem('ccw.autoUpdate');\r\n return saved === null ? true : JSON.parse(saved);\r\n } catch {\r\n return true;\r\n }\r\n });\r\n\r\n const checkVersion = async (silent = false) => {\r\n if (!silent) setChecking(true);\r\n setError(null);\r\n try {\r\n const response = await fetch('/api/version-check');\r\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\r\n\r\n const data: VersionData = await response.json();\r\n if (!data.currentVersion) throw new Error('Invalid response');\r\n\r\n setVersionData(data);\r\n setLastChecked(new Date());\r\n } catch (err) {\r\n if (!silent) setError(err instanceof Error ? err.message : 'Unknown error');\r\n } finally {\r\n setChecking(false);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n // Initial check\r\n checkVersion(true);\r\n\r\n if (!autoCheck) return;\r\n const interval = setInterval(() => checkVersion(true), 60 * 60 * 1000);\r\n return () => clearInterval(interval);\r\n }, [autoCheck]);\r\n\r\n const toggleAutoCheck = (enabled: boolean) => {\r\n setAutoCheck(enabled);\r\n localStorage.setItem('ccw.autoUpdate', JSON.stringify(enabled));\r\n };\r\n\r\n return (\r\n <Card className=\"p-6\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2\">\r\n <ArrowUpCircle className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.versionCheck.title' })}\r\n </h2>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n disabled={checking}\r\n onClick={() => checkVersion()}\r\n >\r\n <RefreshCw className={cn('w-3.5 h-3.5 mr-1.5', checking && 'animate-spin')} />\r\n {checking\r\n ? formatMessage({ id: 'settings.versionCheck.checking' })\r\n : formatMessage({ id: 'settings.versionCheck.checkNow' })}\r\n </Button>\r\n </div>\r\n\r\n <div className=\"space-y-4\">\r\n {/* Version info */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-3\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.versionCheck.currentVersion' })}\r\n </span>\r\n <Badge variant=\"secondary\" className=\"font-mono text-xs\">\r\n {versionData?.currentVersion ?? '...'}\r\n </Badge>\r\n </div>\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.versionCheck.latestVersion' })}\r\n </span>\r\n <Badge\r\n variant={versionData?.hasUpdate ? 'default' : 'secondary'}\r\n className=\"font-mono text-xs\"\r\n >\r\n {versionData?.latestVersion ?? '...'}\r\n </Badge>\r\n </div>\r\n\r\n {/* Status */}\r\n {versionData && (\r\n <div className=\"flex items-center justify-between pt-2 border-t border-border\">\r\n <span className=\"text-sm font-medium\">\r\n {versionData.hasUpdate\r\n ? formatMessage({ id: 'settings.versionCheck.updateAvailable' })\r\n : formatMessage({ id: 'settings.versionCheck.upToDate' })}\r\n </span>\r\n <span className={cn(\r\n 'inline-block w-2.5 h-2.5 rounded-full',\r\n versionData.hasUpdate ? 'bg-orange-500' : 'bg-green-500'\r\n )} />\r\n </div>\r\n )}\r\n\r\n {error && (\r\n <div className=\"flex items-center gap-2 pt-2 border-t border-border\">\r\n <AlertTriangle className=\"w-4 h-4 text-destructive flex-shrink-0\" />\r\n <span className=\"text-sm text-destructive\">\r\n {formatMessage({ id: 'settings.versionCheck.checkFailed' })}: {error}\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Update action */}\r\n {versionData?.hasUpdate && (\r\n <div className=\"rounded-lg border border-orange-500/30 bg-orange-500/5 p-4 space-y-3\">\r\n <div>\r\n <p className=\"text-sm font-medium text-foreground mb-1\">\r\n {formatMessage({ id: 'settings.versionCheck.updateCommand' })}\r\n </p>\r\n <code className=\"text-xs font-mono bg-muted px-3 py-1.5 rounded block\">\r\n {versionData.updateCommand}\r\n </code>\r\n </div>\r\n <Button variant=\"outline\" size=\"sm\" asChild>\r\n <a\r\n href=\"https://github.com/dyw0830/ccw/releases\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"inline-flex items-center gap-1.5\"\r\n >\r\n {formatMessage({ id: 'settings.versionCheck.viewRelease' })}\r\n </a>\r\n </Button>\r\n </div>\r\n )}\r\n\r\n {/* Auto check toggle + last checked */}\r\n <div className=\"flex items-center justify-between\">\r\n <label className=\"flex items-center gap-2 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={autoCheck}\r\n onChange={(e) => toggleAutoCheck(e.target.checked)}\r\n className=\"rounded border-input\"\r\n />\r\n <div>\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.versionCheck.autoCheck' })}</span>\r\n <p className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'settings.versionCheck.autoCheckDesc' })}</p>\r\n </div>\r\n </label>\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.versionCheck.lastChecked' })}:{' '}\r\n {lastChecked ? lastChecked.toLocaleTimeString() : formatMessage({ id: 'settings.versionCheck.never' })}\r\n </span>\r\n </div>\r\n </div>\r\n </Card>\r\n );\r\n}\r\n\r\n// ========== System Status Section ==========\r\n\r\nfunction SystemStatusSection() {\r\n const { formatMessage } = useIntl();\r\n const { installations, isLoading, refetch } = useCcwInstallations();\r\n const { upgrade, isPending: upgrading } = useUpgradeCcwInstallation();\r\n const { data: ccwInstall } = useCcwInstallStatus();\r\n\r\n return (\r\n <Card className=\"p-6\">\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2\">\r\n <Package className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.systemStatus.title' })}\r\n {!isLoading && (\r\n <span className=\"text-sm font-normal text-muted-foreground\">\r\n {installations.length} {formatMessage({ id: 'settings.systemStatus.installations' })}\r\n </span>\r\n )}\r\n </h2>\r\n <div className=\"flex items-center gap-1\">\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className=\"h-7 w-7 p-0\"\r\n onClick={() => refetch()}\r\n title={formatMessage({ id: 'settings.systemStatus.refresh' })}\r\n >\r\n <RefreshCw className={cn('w-3.5 h-3.5', isLoading && 'animate-spin')} />\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Installation cards */}\r\n {isLoading ? (\r\n <div className=\"text-sm text-muted-foreground py-4 text-center\">\r\n {formatMessage({ id: 'settings.systemStatus.checking' })}\r\n </div>\r\n ) : installations.length === 0 ? (\r\n <div className=\"text-center py-6 space-y-2\">\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.systemStatus.noInstallations' })}\r\n </p>\r\n <div className=\"bg-muted/50 rounded-md p-3 inline-block\">\r\n <code className=\"text-xs font-mono\">ccw install</code>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"space-y-3\">\r\n {installations.map((inst) => {\r\n const isGlobal = inst.installation_mode === 'Global';\r\n const installDate = new Date(inst.installation_date).toLocaleDateString();\r\n const version = inst.application_version !== 'unknown' ? inst.application_version : inst.installer_version;\r\n\r\n return (\r\n <div\r\n key={inst.manifest_id}\r\n className=\"rounded-lg border border-border p-4 space-y-2\"\r\n >\r\n {/* Mode + Version + Upgrade */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className={cn(\r\n 'inline-flex items-center justify-center w-8 h-8 rounded-lg',\r\n isGlobal ? 'bg-primary/10 text-primary' : 'bg-orange-500/10 text-orange-500'\r\n )}>\r\n {isGlobal ? <Home className=\"w-4 h-4\" /> : <Folder className=\"w-4 h-4\" />}\r\n </span>\r\n <span className=\"text-sm font-medium\">\r\n {isGlobal\r\n ? formatMessage({ id: 'settings.systemStatus.global' })\r\n : formatMessage({ id: 'settings.systemStatus.path' })}\r\n </span>\r\n <Badge variant=\"secondary\" className=\"text-xs font-mono\">\r\n v{version}\r\n </Badge>\r\n </div>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={upgrading}\r\n onClick={() => upgrade(inst.installation_path)}\r\n >\r\n <ArrowUpCircle className={cn('w-3.5 h-3.5 mr-1', upgrading && 'animate-spin')} />\r\n {upgrading\r\n ? formatMessage({ id: 'settings.systemStatus.upgrading' })\r\n : formatMessage({ id: 'settings.systemStatus.upgrade' })}\r\n </Button>\r\n </div>\r\n\r\n {/* Path */}\r\n <div className=\"text-xs text-muted-foreground bg-muted/50 rounded px-2 py-1 font-mono truncate\" title={inst.installation_path}>\r\n {inst.installation_path}\r\n </div>\r\n\r\n {/* Date + Files */}\r\n <div className=\"flex items-center gap-4 text-xs text-muted-foreground\">\r\n <span className=\"inline-flex items-center gap-1\">\r\n <Calendar className=\"w-3 h-3\" />\r\n {installDate}\r\n </span>\r\n <span className=\"inline-flex items-center gap-1\">\r\n <File className=\"w-3 h-3\" />\r\n {inst.files_count} {formatMessage({ id: 'settings.systemStatus.files' })}\r\n </span>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n\r\n {/* Missing files warning */}\r\n {ccwInstall && !ccwInstall.installed && ccwInstall.missingFiles.length > 0 && (\r\n <div className=\"rounded-lg border border-yellow-500/50 bg-yellow-500/5 p-4 space-y-2\">\r\n <div className=\"flex items-center gap-2 text-sm font-medium text-yellow-600 dark:text-yellow-500\">\r\n <AlertTriangle className=\"w-4 h-4\" />\r\n {formatMessage({ id: 'settings.systemStatus.incomplete' })} &mdash; {ccwInstall.missingFiles.length} {formatMessage({ id: 'settings.systemStatus.missingFiles' }).toLowerCase()}\r\n </div>\r\n <ul className=\"text-xs text-muted-foreground list-disc list-inside\">\r\n {ccwInstall.missingFiles.slice(0, 4).map((f) => (\r\n <li key={f}>{f}</li>\r\n ))}\r\n {ccwInstall.missingFiles.length > 4 && (\r\n <li>+{ccwInstall.missingFiles.length - 4} more...</li>\r\n )}\r\n </ul>\r\n <div className=\"bg-muted/50 rounded-md p-2\">\r\n <p className=\"text-xs font-medium mb-1\">{formatMessage({ id: 'settings.systemStatus.runToFix' })}:</p>\r\n <code className=\"text-xs font-mono bg-background px-2 py-1 rounded block\">ccw install</code>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </Card>\r\n );\r\n}\r\n\r\n// ========== CLI Tools with Status Enhancement ==========\r\n\r\ninterface CliToolsWithStatusProps {\r\n cliTools: Record<string, CliToolConfig>;\r\n defaultCliTool: string;\r\n expandedTools: Set<string>;\r\n savingTools: Set<string>;\r\n onToggleExpand: (toolId: string) => void;\r\n onToggleEnabled: (toolId: string) => void;\r\n onSetDefault: (toolId: string) => void;\r\n onUpdateModel: (toolId: string, field: 'primaryModel' | 'secondaryModel', value: string) => void;\r\n onUpdateTags: (toolId: string, tags: string[]) => void;\r\n onUpdateAvailableModels: (toolId: string, models: string[]) => void;\r\n onUpdateEnvFile: (toolId: string, envFile: string | undefined) => void;\r\n onUpdateSettingsFile: (toolId: string, settingsFile: string | undefined) => void;\r\n onUpdateEffort: (toolId: string, effort: string | undefined) => void;\r\n onSaveToBackend: (toolId: string) => void;\r\n formatMessage: ReturnType<typeof useIntl>['formatMessage'];\r\n}\r\n\r\nfunction CliToolsWithStatus({\r\n cliTools,\r\n defaultCliTool,\r\n expandedTools,\r\n savingTools,\r\n onToggleExpand,\r\n onToggleEnabled,\r\n onSetDefault,\r\n onUpdateModel,\r\n onUpdateTags,\r\n onUpdateAvailableModels,\r\n onUpdateEnvFile,\r\n onUpdateSettingsFile,\r\n onUpdateEffort,\r\n onSaveToBackend,\r\n formatMessage,\r\n}: CliToolsWithStatusProps) {\r\n const { data: toolStatus } = useCliToolStatus();\r\n\r\n return (\r\n <>\r\n <p className=\"text-sm text-muted-foreground mb-4\">\r\n {formatMessage({ id: 'settings.cliTools.description' })} <strong className=\"text-foreground\">{defaultCliTool}</strong>\r\n </p>\r\n <div className=\"space-y-3\">\r\n {Object.entries(cliTools).map(([toolId, config]) => {\r\n const status = toolStatus?.[toolId];\r\n return (\r\n <CliToolCard\r\n key={toolId}\r\n toolId={toolId}\r\n config={config}\r\n isDefault={toolId === defaultCliTool}\r\n isExpanded={expandedTools.has(toolId)}\r\n toolAvailable={status?.available}\r\n isSaving={savingTools.has(toolId)}\r\n onToggleExpand={() => onToggleExpand(toolId)}\r\n onToggleEnabled={() => onToggleEnabled(toolId)}\r\n onSetDefault={() => onSetDefault(toolId)}\r\n onUpdateModel={(field, value) => onUpdateModel(toolId, field, value)}\r\n onUpdateTags={(tags) => onUpdateTags(toolId, tags)}\r\n onUpdateAvailableModels={(models) => onUpdateAvailableModels(toolId, models)}\r\n onUpdateEnvFile={(envFile) => onUpdateEnvFile(toolId, envFile)}\r\n onUpdateSettingsFile={(settingsFile) => onUpdateSettingsFile(toolId, settingsFile)}\r\n onUpdateEffort={(effort) => onUpdateEffort(toolId, effort)}\r\n onSaveToBackend={() => onSaveToBackend(toolId)}\r\n />\r\n );\r\n })}\r\n </div>\r\n </>\r\n );\r\n}\r\n\r\n// ========== Main Page Component ==========\r\n\r\nexport function SettingsPage() {\r\n const { formatMessage } = useIntl();\r\n const { theme, setTheme } = useTheme();\r\n const cliTools = useConfigStore(selectCliTools);\r\n const defaultCliTool = useConfigStore(selectDefaultCliTool);\r\n const userPreferences = useConfigStore(selectUserPreferences);\r\n const { updateCliTool, setDefaultCliTool, setUserPreferences, resetUserPreferences } = useConfigStore();\r\n\r\n const [expandedTools, setExpandedTools] = useState<Set<string>>(new Set());\r\n const [savingTools, setSavingTools] = useState<Set<string>>(new Set());\r\n\r\n const toggleToolExpand = (toolId: string) => {\r\n setExpandedTools((prev) => {\r\n const next = new Set(prev);\r\n if (next.has(toolId)) {\r\n next.delete(toolId);\r\n } else {\r\n next.add(toolId);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const handleToggleToolEnabled = (toolId: string) => {\r\n updateCliTool(toolId, { enabled: !cliTools[toolId].enabled });\r\n };\r\n\r\n const handleSetDefaultTool = (toolId: string) => {\r\n setDefaultCliTool(toolId);\r\n };\r\n\r\n const handleUpdateModel = (toolId: string, field: 'primaryModel' | 'secondaryModel', value: string) => {\r\n updateCliTool(toolId, { [field]: value });\r\n };\r\n\r\n const handleUpdateTags = (toolId: string, tags: string[]) => {\r\n updateCliTool(toolId, { tags });\r\n };\r\n\r\n const handleUpdateAvailableModels = (toolId: string, availableModels: string[]) => {\r\n updateCliTool(toolId, { availableModels });\r\n };\r\n\r\n const handleUpdateEnvFile = (toolId: string, envFile: string | undefined) => {\r\n updateCliTool(toolId, { envFile });\r\n };\r\n\r\n const handleUpdateSettingsFile = (toolId: string, settingsFile: string | undefined) => {\r\n updateCliTool(toolId, { settingsFile });\r\n };\r\n\r\n const handleUpdateEffort = (toolId: string, effort: string | undefined) => {\r\n updateCliTool(toolId, { effort });\r\n };\r\n\r\n // Save tool config to backend (~/.claude/cli-tools.json)\r\n const handleSaveToBackend = useCallback(async (toolId: string) => {\r\n const config = cliTools[toolId];\r\n if (!config) return;\r\n\r\n setSavingTools((prev) => new Set(prev).add(toolId));\r\n try {\r\n const body: Record<string, unknown> = {\r\n enabled: config.enabled,\r\n primaryModel: config.primaryModel,\r\n secondaryModel: config.secondaryModel,\r\n tags: config.tags,\r\n availableModels: config.availableModels,\r\n };\r\n\r\n // Only include the relevant config file field\r\n const configFileType = getConfigFileType(toolId);\r\n if (configFileType === 'envFile') {\r\n body.envFile = config.envFile || null;\r\n } else if (configFileType === 'settingsFile') {\r\n body.settingsFile = config.settingsFile || null;\r\n body.effort = config.effort || null;\r\n }\r\n\r\n const csrfToken = getCsrfToken();\r\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\r\n if (csrfToken) {\r\n headers['X-CSRF-Token'] = csrfToken;\r\n }\r\n\r\n const res = await fetch(`/api/cli/config/${toolId}`, {\r\n method: 'PUT',\r\n headers,\r\n body: JSON.stringify(body),\r\n credentials: 'same-origin',\r\n });\r\n\r\n if (!res.ok) {\r\n throw new Error(`HTTP ${res.status}`);\r\n }\r\n\r\n toast.success(formatMessage({ id: 'settings.cliTools.configSaved' }), {\r\n description: toolId,\r\n });\r\n } catch {\r\n toast.error(formatMessage({ id: 'settings.cliTools.configSaveError' }), {\r\n description: toolId,\r\n });\r\n } finally {\r\n setSavingTools((prev) => {\r\n const next = new Set(prev);\r\n next.delete(toolId);\r\n return next;\r\n });\r\n }\r\n }, [cliTools, formatMessage]);\r\n\r\n const handlePreferenceChange = (key: keyof UserPreferences, value: unknown) => {\r\n setUserPreferences({ [key]: value });\r\n };\r\n\r\n return (\r\n <div className=\"max-w-4xl mx-auto space-y-8\">\r\n {/* Page Header */}\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-foreground flex items-center gap-2\">\r\n <Settings className=\"w-6 h-6 text-primary\" />\r\n {formatMessage({ id: 'settings.title' })}\r\n </h1>\r\n <p className=\"text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.description' })}\r\n </p>\r\n </div>\r\n\r\n {/* Appearance Settings */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <Moon className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.sections.appearance' })}\r\n </h2>\r\n <div className=\"space-y-6\">\r\n {/* Multi-Theme Selector */}\r\n <div>\r\n <p className=\"font-medium text-foreground mb-1\">\r\n {formatMessage({ id: 'settings.appearance.theme' })}\r\n </p>\r\n <p className=\"text-sm text-muted-foreground mb-4\">\r\n {formatMessage({ id: 'settings.appearance.description' })}\r\n </p>\r\n <ThemeSelector />\r\n </div>\r\n\r\n {/* System Theme Toggle (Backward Compatibility) */}\r\n <div className=\"flex items-center justify-between pt-4 border-t border-border\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.appearance.systemFollow' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.appearance.systemFollowDesc' })}\r\n </p>\r\n </div>\r\n <Button\r\n variant={theme === 'system' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setTheme('system')}\r\n >\r\n {formatMessage({ id: 'settings.appearance.themeOptions.system' })}\r\n </Button>\r\n </div>\r\n </div>\r\n </Card>\r\n\r\n {/* Language Settings */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <Languages className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.sections.language' })}\r\n </h2>\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.language.displayLanguage' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.language.chooseLanguage' })}\r\n </p>\r\n </div>\r\n <LanguageSwitcher />\r\n </div>\r\n </div>\r\n </Card>\r\n\r\n {/* Response Language Settings */}\r\n <ResponseLanguageSection />\r\n\r\n {/* A2UI Preferences */}\r\n <A2UIPreferencesSection />\r\n\r\n {/* System Status */}\r\n <SystemStatusSection />\r\n\r\n {/* Version Check */}\r\n <VersionCheckSection />\r\n\r\n {/* CLI Tools Configuration */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <Cpu className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.sections.cliTools' })}\r\n </h2>\r\n <CliToolsWithStatus\r\n cliTools={cliTools}\r\n defaultCliTool={defaultCliTool}\r\n expandedTools={expandedTools}\r\n savingTools={savingTools}\r\n onToggleExpand={toggleToolExpand}\r\n onToggleEnabled={handleToggleToolEnabled}\r\n onSetDefault={handleSetDefaultTool}\r\n onUpdateModel={handleUpdateModel}\r\n onUpdateTags={handleUpdateTags}\r\n onUpdateAvailableModels={handleUpdateAvailableModels}\r\n onUpdateEnvFile={handleUpdateEnvFile}\r\n onUpdateSettingsFile={handleUpdateSettingsFile}\r\n onUpdateEffort={handleUpdateEffort}\r\n onSaveToBackend={handleSaveToBackend}\r\n formatMessage={formatMessage}\r\n />\r\n </Card>\r\n\r\n {/* Data Refresh Settings */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <RefreshCw className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.dataRefresh.title' })}\r\n </h2>\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.dataRefresh.autoRefresh' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.dataRefresh.autoRefreshDesc' })}\r\n </p>\r\n </div>\r\n <Button\r\n variant={userPreferences.autoRefresh ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => handlePreferenceChange('autoRefresh', !userPreferences.autoRefresh)}\r\n >\r\n {userPreferences.autoRefresh ? formatMessage({ id: 'settings.dataRefresh.enabled' }) : formatMessage({ id: 'settings.dataRefresh.disabled' })}\r\n </Button>\r\n </div>\r\n\r\n {userPreferences.autoRefresh && (\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.dataRefresh.refreshInterval' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.dataRefresh.refreshIntervalDesc' })}\r\n </p>\r\n </div>\r\n <div className=\"flex gap-2\">\r\n {[15000, 30000, 60000, 120000].map((interval) => (\r\n <Button\r\n key={interval}\r\n variant={userPreferences.refreshInterval === interval ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => handlePreferenceChange('refreshInterval', interval)}\r\n >\r\n {interval / 1000}s\r\n </Button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </Card>\r\n\r\n {/* Notifications */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <Bell className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.notifications.title' })}\r\n </h2>\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.notifications.enableNotifications' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.notifications.enableNotificationsDesc' })}\r\n </p>\r\n </div>\r\n <Button\r\n variant={userPreferences.notificationsEnabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => handlePreferenceChange('notificationsEnabled', !userPreferences.notificationsEnabled)}\r\n >\r\n {userPreferences.notificationsEnabled ? formatMessage({ id: 'settings.dataRefresh.enabled' }) : formatMessage({ id: 'settings.dataRefresh.disabled' })}\r\n </Button>\r\n </div>\r\n\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.notifications.soundEffects' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.notifications.soundEffectsDesc' })}\r\n </p>\r\n </div>\r\n <Button\r\n variant={userPreferences.soundEnabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => handlePreferenceChange('soundEnabled', !userPreferences.soundEnabled)}\r\n >\r\n {userPreferences.soundEnabled ? formatMessage({ id: 'settings.notifications.on' }) : formatMessage({ id: 'settings.notifications.off' })}\r\n </Button>\r\n </div>\r\n </div>\r\n </Card>\r\n\r\n {/* Remote Notifications */}\r\n <RemoteNotificationSection />\r\n\r\n {/* Reset Settings */}\r\n <Card className=\"p-6 border-destructive/50\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <RotateCcw className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'common.actions.reset' })}\r\n </h2>\r\n <p className=\"text-sm text-muted-foreground mb-4\">\r\n {formatMessage({ id: 'settings.reset.description' })}\r\n </p>\r\n <Button\r\n variant=\"destructive\"\r\n onClick={() => {\r\n if (confirm(formatMessage({ id: 'settings.reset.confirm' }))) {\r\n resetUserPreferences();\r\n }\r\n }}\r\n >\r\n <RotateCcw className=\"w-4 h-4 mr-2\" />\r\n {formatMessage({ id: 'common.actions.resetToDefaults' })}\r\n </Button>\r\n </Card>\r\n </div>\r\n );\r\n}\r\n\r\nexport default SettingsPage;\r\n"],"file":"assets/SettingsPage-ComW7EZS.js"}
1
+ {"version":3,"mappings":"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","names":["BellOff","createLucideIcon","CircleArrowUp","Languages","LayoutPanelLeft","MessageSquareText","Volume2","getCsrfToken","match","searchUnsplash","query","page","perPage","params","response","body","uploadBackgroundImage","file","headers","csrfToken","triggerUnsplashDownload","downloadLocation","useUnsplashSearch","debouncedQuery","setDebouncedQuery","useState","useEffect","timer","useQuery","MODES","BackgroundImagePicker","formatMessage","useIntl","backgroundConfig","setBackgroundMode","setBackgroundImage","updateBackgroundEffect","useTheme","searchQuery","setSearchQuery","setPage","customUrl","setCustomUrl","isUploading","setIsUploading","uploadError","setUploadError","fileInputRef","useRef","data","isLoading","isError","error","showImageControls","handlePhotoSelect","useCallback","photo","handleCustomUrlApply","handleRemoveImage","handleFileUpload","e","_a","result","err","jsxs","jsx","value","labelId","Fragment","p","ThemeSelector","colorScheme","resolvedTheme","customHue","isCustomTheme","gradientLevel","enableHoverGlow","enableBackgroundAnimation","motionPreference","setColorScheme","setTheme","setCustomHue","setGradientLevel","setEnableHoverGlow","setEnableBackgroundAnimation","setMotionPreference","styleTier","setStyleTier","themeSlots","activeSlotId","canAddSlot","setActiveSlot","copySlot","renameSlot","deleteSlot","undoDeleteSlot","exportThemeCode","importThemeCode","setBackgroundConfig","addToast","removeToast","useNotifications","previewHue","setPreviewHue","contrastWarnings","setContrastWarnings","contrastFixes","setContrastFixes","showContrastWarning","setShowContrastWarning","renamingSlotId","setRenamingSlotId","renameValue","setRenameValue","pendingDeleteSlot","setPendingDeleteSlot","renameInputRef","undoToastIdRef","showImportPanel","setShowImportPanel","importCode","setImportCode","importPreview","setImportPreview","importWarning","setImportWarning","importError","setImportError","copyFeedback","setCopyFeedback","mode","getPreviewColor","variable","hslValue","generateThemeFromHue","STYLE_TIERS","getTierPreviewColors","tier","baseVars","tieredVars","applyStyleTier","handleSchemeSelect","scheme","handleCustomSelect","handleHueSave","vars","failures","checkThemeContrast","r","fixes","failure","key","generateContrastFix","handleHueReset","handleModeSelect","newMode","handleKeyDown","nextIndex","COLOR_SCHEMES","s","handleSlotSelect","slotId","handleCopySlot","handleStartRename","currentName","handleConfirmRename","handleCancelRename","handleRenameKeyDown","handleConfirmDelete","toastId","handleCancelDelete","handleCopyThemeCode","code","handleOpenImport","handleCloseImport","handleImportCodeChange","handleApplyImport","DEFAULT_BACKGROUND_CONFIG","getImportPreviewColors","payload","hue","getShareErrorMessageId","errorKey","THEME_SLOT_LIMIT","slot","isActive","isRenaming","preview","isSelected","level","pref","w","fix","i","THEME_MODES","modeOption","getThemeName","previewColors","AlertDialog","AlertDialogContent","AlertDialogHeader","AlertDialogTitle","AlertDialogDescription","AlertDialogFooter","AlertDialogCancel","AlertDialogAction","LANGUAGE_OPTIONS","LanguageSwitcher","compact","className","locale","setLocale","useLocale","Select","SelectTrigger","cn","SelectValue","SelectContent","option","SelectItem","PLATFORM_INFO","EVENT_INFO","getDefaultConfig","PlatformConfigCards","config","expandedPlatform","testing","onToggleExpand","onUpdateConfig","onTest","onSave","saving","platforms","getPlatformIcon","platform","MessageCircle","Send","MessageSquare","Bell","Users","Mail","Link","getPlatformConfig","isConfigured","platformConfig","emailConfig","info","configured","expanded","Card","Badge","Check","Button","X","ChevronUp","ChevronDown","DiscordConfigForm","updates","TelegramConfigForm","FeishuConfigForm","DingTalkConfigForm","WeComConfigForm","EmailConfigForm","WebhookConfigForm","TestTube","onUpdate","showUrl","setShowUrl","Input","EyeOff","Eye","showToken","setShowToken","k","m","showPassword","setShowPassword","t","RemoteNotificationSection","setConfig","loading","setLoading","setSaving","setTesting","setExpandedPlatform","expandedEvent","setExpandedEvent","loadConfig","saveConfig","newConfig","toast","testPlatform","toggleEnabled","updatePlatformConfig","updateEventConfig","eventIndex","newEvents","toggleEventPlatform","eventConfig","allPlatforms","resetConfig","RefreshCw","index","isExpanded","platformInfo","Plus","Save","StyleOption","label","description","selected","onClick","icons","DurationSlider","onChange","disabled","presets","seconds","A2UIPreferencesSection","preferences","updatePreference","resetPreferences","useDialogStyleContext","styleOptions","Label","Sparkles","Clock","v","FilePathInput","placeholder","isValidating","setIsValidating","pathError","setPathError","debouncedValue","useDebounce","timeoutId","handleBrowse","selectFile","__vitePreload","n","initialDir","Loader2","FolderOpen","ENV_FILE_TOOLS","SETTINGS_FILE_TOOLS","getConfigFileType","toolId","CliToolCard","isDefault","toolAvailable","isSaving","onToggleEnabled","onSetDefault","onUpdateModel","onUpdateTags","onUpdateAvailableModels","onUpdateEnvFile","onUpdateSettingsFile","onUpdateEffort","onSaveToBackend","tagInput","setTagInput","modelInput","setModelInput","handleAddTag","newTag","handleRemoveTag","tagToRemove","handleAddModel","newModel","currentModels","handleRemoveModel","modelToRemove","predefinedTags","configFileType","Cpu","tag","predefinedTag","model","effectiveEffort","ResponseLanguageSection","chineseStatus","chineseLoading","useChineseResponseStatus","toggleChinese","chineseToggling","useToggleChineseResponse","windowsStatus","windowsLoading","useWindowsPlatformStatus","toggleWindows","windowsToggling","useToggleWindowsPlatform","cliEnhStatus","cliEnhLoading","useCodexCliEnhancementStatus","toggleCliEnh","cliEnhToggling","useToggleCodexCliEnhancement","refreshCliEnh","refreshing","useRefreshCodexCliEnhancement","doExport","exporting","useExportSettings","doImport","importing","useImportSettings","handleExport","blob","url","a","timestamp","handleFileImport","text","AlertTriangle","Monitor","Terminal","Upload","Download","VersionCheckSection","versionData","setVersionData","checking","setChecking","setError","lastChecked","setLastChecked","autoCheck","setAutoCheck","saved","checkVersion","silent","interval","toggleAutoCheck","enabled","ArrowUpCircle","SystemStatusSection","installations","refetch","useCcwInstallations","upgrade","upgrading","useUpgradeCcwInstallation","ccwInstall","useCcwInstallStatus","Package","inst","isGlobal","installDate","version","Home","Folder","Calendar","File","f","CliToolsWithStatus","cliTools","defaultCliTool","expandedTools","savingTools","toolStatus","useCliToolStatus","status","field","tags","models","envFile","settingsFile","effort","SettingsPage","theme","useConfigStore","selectCliTools","selectDefaultCliTool","userPreferences","selectUserPreferences","updateCliTool","setDefaultCliTool","setUserPreferences","resetUserPreferences","setExpandedTools","setSavingTools","toggleToolExpand","prev","next","handleToggleToolEnabled","handleSetDefaultTool","handleUpdateModel","handleUpdateTags","handleUpdateAvailableModels","availableModels","handleUpdateEnvFile","handleUpdateSettingsFile","handleUpdateEffort","handleSaveToBackend","res","handlePreferenceChange","Settings","Moon","RotateCcw"],"ignoreList":[0,1,2,3,4,5],"sources":["../../../../node_modules/lucide-react/dist/esm/icons/bell-off.js","../../../../node_modules/lucide-react/dist/esm/icons/circle-arrow-up.js","../../../../node_modules/lucide-react/dist/esm/icons/languages.js","../../../../node_modules/lucide-react/dist/esm/icons/layout-panel-left.js","../../../../node_modules/lucide-react/dist/esm/icons/message-square-text.js","../../../../node_modules/lucide-react/dist/esm/icons/volume-2.js","../../src/lib/unsplash.ts","../../src/hooks/useUnsplashSearch.ts","../../src/components/shared/BackgroundImagePicker.tsx","../../src/components/shared/ThemeSelector.tsx","../../src/components/layout/LanguageSwitcher.tsx","../../src/types/remote-notification.ts","../../src/components/settings/PlatformConfigCards.tsx","../../src/components/settings/RemoteNotificationSection.tsx","../../src/components/settings/A2UIPreferencesSection.tsx","../../src/pages/SettingsPage.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst BellOff = createLucideIcon(\"BellOff\", [\n [\"path\", { d: \"M8.7 3A6 6 0 0 1 18 8a21.3 21.3 0 0 0 .6 5\", key: \"o7mx20\" }],\n [\"path\", { d: \"M17 17H3s3-2 3-9a4.67 4.67 0 0 1 .3-1.7\", key: \"16f1lm\" }],\n [\"path\", { d: \"M10.3 21a1.94 1.94 0 0 0 3.4 0\", key: \"qgo35s\" }],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n]);\n\nexport { BellOff as default };\n//# sourceMappingURL=bell-off.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleArrowUp = createLucideIcon(\"CircleArrowUp\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m16 12-4-4-4 4\", key: \"177agl\" }],\n [\"path\", { d: \"M12 16V8\", key: \"1sbj14\" }]\n]);\n\nexport { CircleArrowUp as default };\n//# sourceMappingURL=circle-arrow-up.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Languages = createLucideIcon(\"Languages\", [\n [\"path\", { d: \"m5 8 6 6\", key: \"1wu5hv\" }],\n [\"path\", { d: \"m4 14 6-6 2-3\", key: \"1k1g8d\" }],\n [\"path\", { d: \"M2 5h12\", key: \"or177f\" }],\n [\"path\", { d: \"M7 2h1\", key: \"1t2jsx\" }],\n [\"path\", { d: \"m22 22-5-10-5 10\", key: \"don7ne\" }],\n [\"path\", { d: \"M14 18h6\", key: \"1m8k6r\" }]\n]);\n\nexport { Languages as default };\n//# sourceMappingURL=languages.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutPanelLeft = createLucideIcon(\"LayoutPanelLeft\", [\n [\"rect\", { width: \"7\", height: \"18\", x: \"3\", y: \"3\", rx: \"1\", key: \"2obqm\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"3\", rx: \"1\", key: \"6d4xhi\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"14\", rx: \"1\", key: \"nxv5o0\" }]\n]);\n\nexport { LayoutPanelLeft as default };\n//# sourceMappingURL=layout-panel-left.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst MessageSquareText = createLucideIcon(\"MessageSquareText\", [\n [\"path\", { d: \"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\", key: \"1lielz\" }],\n [\"path\", { d: \"M13 8H7\", key: \"14i4kc\" }],\n [\"path\", { d: \"M17 12H7\", key: \"16if0g\" }]\n]);\n\nexport { MessageSquareText as default };\n//# sourceMappingURL=message-square-text.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Volume2 = createLucideIcon(\"Volume2\", [\n [\n \"path\",\n {\n d: \"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\",\n key: \"uqj9uw\"\n }\n ],\n [\"path\", { d: \"M16 9a5 5 0 0 1 0 6\", key: \"1q6k2b\" }],\n [\"path\", { d: \"M19.364 18.364a9 9 0 0 0 0-12.728\", key: \"ijwkga\" }]\n]);\n\nexport { Volume2 as default };\n//# sourceMappingURL=volume-2.js.map\n","/**\n * Unsplash API Client\n * Frontend functions to search Unsplash via the backend proxy.\n */\n\nexport interface UnsplashPhoto {\n id: string;\n thumbUrl: string;\n smallUrl: string;\n regularUrl: string;\n photographer: string;\n photographerUrl: string;\n photoUrl: string;\n blurHash: string | null;\n downloadLocation: string;\n}\n\nexport interface UnsplashSearchResult {\n photos: UnsplashPhoto[];\n total: number;\n totalPages: number;\n}\n\nfunction getCsrfToken(): string | null {\n const match = document.cookie.match(/XSRF-TOKEN=([^;]+)/);\n return match ? decodeURIComponent(match[1]) : null;\n}\n\n/**\n * Search Unsplash photos via backend proxy.\n */\nexport async function searchUnsplash(\n query: string,\n page = 1,\n perPage = 20\n): Promise<UnsplashSearchResult> {\n const params = new URLSearchParams({\n query,\n page: String(page),\n per_page: String(perPage),\n });\n\n const response = await fetch(`/api/unsplash/search?${params}`, {\n credentials: 'same-origin',\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({}));\n throw new Error(body.error || `Unsplash search failed: ${response.status}`);\n }\n\n return response.json();\n}\n\n/**\n * Upload a local image as background.\n * Sends raw binary to avoid base64 overhead.\n */\nexport async function uploadBackgroundImage(file: File): Promise<{ url: string; filename: string }> {\n const headers: Record<string, string> = {\n 'Content-Type': file.type,\n 'X-Filename': encodeURIComponent(file.name),\n };\n const csrfToken = getCsrfToken();\n if (csrfToken) {\n headers['X-CSRF-Token'] = csrfToken;\n }\n\n const response = await fetch('/api/background/upload', {\n method: 'POST',\n headers,\n credentials: 'same-origin',\n body: file,\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({}));\n throw new Error(body.error || `Upload failed: ${response.status}`);\n }\n\n return response.json();\n}\n\n/**\n * Trigger Unsplash download event (required by API guidelines).\n */\nexport async function triggerUnsplashDownload(downloadLocation: string): Promise<void> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const csrfToken = getCsrfToken();\n if (csrfToken) {\n headers['X-CSRF-Token'] = csrfToken;\n }\n\n await fetch('/api/unsplash/download', {\n method: 'POST',\n headers,\n credentials: 'same-origin',\n body: JSON.stringify({ downloadLocation }),\n });\n}\n","/**\n * React Query hook for searching Unsplash photos with debounce.\n */\nimport { useState, useEffect } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { searchUnsplash } from '@/lib/unsplash';\nimport type { UnsplashSearchResult } from '@/lib/unsplash';\n\nexport function useUnsplashSearch(query: string, page = 1, perPage = 20) {\n const [debouncedQuery, setDebouncedQuery] = useState(query);\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setDebouncedQuery(query);\n }, 500);\n return () => clearTimeout(timer);\n }, [query]);\n\n return useQuery<UnsplashSearchResult>({\n queryKey: ['unsplash-search', debouncedQuery, page, perPage],\n queryFn: () => searchUnsplash(debouncedQuery, page, perPage),\n enabled: debouncedQuery.trim().length > 0,\n staleTime: 5 * 60 * 1000, // 5 minutes\n retry: 1,\n });\n}\n","import { useState, useCallback, useRef } from 'react';\nimport { useIntl } from 'react-intl';\nimport { useTheme } from '@/hooks/useTheme';\nimport { useUnsplashSearch } from '@/hooks/useUnsplashSearch';\nimport { triggerUnsplashDownload, uploadBackgroundImage } from '@/lib/unsplash';\nimport type { UnsplashPhoto } from '@/lib/unsplash';\nimport type { BackgroundMode } from '@/types/store';\n\nconst MODES: { value: BackgroundMode; labelId: string }[] = [\n { value: 'gradient-only', labelId: 'theme.background.mode.gradientOnly' },\n { value: 'image-only', labelId: 'theme.background.mode.imageOnly' },\n { value: 'image-gradient', labelId: 'theme.background.mode.imageGradient' },\n];\n\n/**\n * BackgroundImagePicker Component\n * Allows users to search Unsplash, pick a background image,\n * adjust visual effects, and switch between background modes.\n */\nexport function BackgroundImagePicker() {\n const { formatMessage } = useIntl();\n const {\n backgroundConfig,\n setBackgroundMode,\n setBackgroundImage,\n updateBackgroundEffect,\n } = useTheme();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [page, setPage] = useState(1);\n const [customUrl, setCustomUrl] = useState('');\n const [isUploading, setIsUploading] = useState(false);\n const [uploadError, setUploadError] = useState<string | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const { data, isLoading, isError, error } = useUnsplashSearch(searchQuery, page);\n\n const showImageControls = backgroundConfig.mode !== 'gradient-only';\n\n const handlePhotoSelect = useCallback(async (photo: UnsplashPhoto) => {\n setBackgroundImage(photo.regularUrl, {\n photographerName: photo.photographer,\n photographerUrl: photo.photographerUrl,\n photoUrl: photo.photoUrl,\n });\n // Trigger download event per Unsplash API guidelines\n triggerUnsplashDownload(photo.downloadLocation).catch(() => {});\n }, [setBackgroundImage]);\n\n const handleCustomUrlApply = useCallback(() => {\n if (customUrl.trim()) {\n setBackgroundImage(customUrl.trim(), null);\n setCustomUrl('');\n }\n }, [customUrl, setBackgroundImage]);\n\n const handleRemoveImage = useCallback(() => {\n setBackgroundImage(null, null);\n }, [setBackgroundImage]);\n\n const handleFileUpload = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n // Reset file input so the same file can be re-selected\n e.target.value = '';\n\n setUploadError(null);\n\n if (file.size > 10 * 1024 * 1024) {\n setUploadError(formatMessage({ id: 'theme.background.fileTooLarge' }));\n return;\n }\n\n if (!file.type.startsWith('image/') || !['image/jpeg', 'image/png', 'image/webp', 'image/gif'].includes(file.type)) {\n setUploadError(formatMessage({ id: 'theme.background.invalidType' }));\n return;\n }\n\n setIsUploading(true);\n try {\n const result = await uploadBackgroundImage(file);\n setBackgroundImage(result.url, null);\n } catch (err) {\n setUploadError((err as Error).message || formatMessage({ id: 'theme.background.uploadError' }));\n } finally {\n setIsUploading(false);\n }\n }, [formatMessage, setBackgroundImage]);\n\n return (\n <div className=\"space-y-4\">\n {/* Section title */}\n <h3 className=\"text-sm font-medium text-text\">\n {formatMessage({ id: 'theme.background.title' })}\n </h3>\n\n {/* Background mode selector */}\n <div\n className=\"flex gap-2\"\n role=\"radiogroup\"\n aria-label={formatMessage({ id: 'theme.background.title' })}\n >\n {MODES.map(({ value, labelId }) => (\n <button\n key={value}\n onClick={() => setBackgroundMode(value)}\n role=\"radio\"\n aria-checked={backgroundConfig.mode === value}\n className={`\n flex-1 px-3 py-2 rounded-lg text-xs font-medium\n transition-all duration-200 border-2\n ${backgroundConfig.mode === value\n ? 'border-accent bg-surface shadow-md'\n : 'border-border bg-bg hover:bg-surface'\n }\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\n `}\n >\n {formatMessage({ id: labelId })}\n </button>\n ))}\n </div>\n\n {/* Image selection area */}\n {showImageControls && (\n <div className=\"space-y-3\">\n {/* Current image preview */}\n {backgroundConfig.imageUrl && (\n <div className=\"relative rounded-lg overflow-hidden border border-border\">\n <img\n src={backgroundConfig.imageUrl}\n alt=\"Current background\"\n className=\"w-full h-32 object-cover\"\n />\n <button\n onClick={handleRemoveImage}\n className=\"absolute top-2 right-2 px-2 py-1 text-xs bg-black/60 text-white rounded hover:bg-black/80 transition-colors\"\n >\n {formatMessage({ id: 'theme.background.removeImage' })}\n </button>\n {/* Unsplash attribution */}\n {backgroundConfig.attribution && (\n <div className=\"absolute bottom-0 left-0 right-0 px-2 py-1 bg-black/50 text-white text-xs\">\n Photo by{' '}\n <a\n href={`${backgroundConfig.attribution.photographerUrl}?utm_source=ccw&utm_medium=referral`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline\"\n >\n {backgroundConfig.attribution.photographerName}\n </a>{' '}\n on{' '}\n <a\n href=\"https://unsplash.com/?utm_source=ccw&utm_medium=referral\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline\"\n >\n Unsplash\n </a>\n </div>\n )}\n </div>\n )}\n\n {/* Search box */}\n <input\n type=\"text\"\n value={searchQuery}\n onChange={(e) => { setSearchQuery(e.target.value); setPage(1); }}\n placeholder={formatMessage({ id: 'theme.background.searchPlaceholder' })}\n className=\"w-full px-3 py-2 text-sm rounded-lg border border-border bg-bg text-text\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1\"\n />\n\n {/* Photo grid */}\n {isLoading && (\n <div className=\"flex justify-center py-4\">\n <div className=\"w-5 h-5 border-2 border-border border-t-accent rounded-full animate-spin\" />\n </div>\n )}\n\n {isError && (\n <p className=\"text-xs text-destructive py-2\">\n {(error as Error)?.message || formatMessage({ id: 'theme.background.searchError' })}\n </p>\n )}\n\n {data && data.photos.length > 0 && (\n <>\n <div className=\"grid grid-cols-3 gap-2 max-h-60 overflow-y-auto\">\n {data.photos.map((photo) => (\n <button\n key={photo.id}\n onClick={() => handlePhotoSelect(photo)}\n className={`\n relative rounded overflow-hidden border-2 transition-all\n hover:border-accent focus:outline-none focus:ring-2 focus:ring-accent\n ${backgroundConfig.imageUrl === photo.regularUrl\n ? 'border-accent ring-2 ring-accent'\n : 'border-transparent'\n }\n `}\n >\n <img\n src={photo.thumbUrl}\n alt={`Photo by ${photo.photographer}`}\n className=\"w-full h-20 object-cover\"\n loading=\"lazy\"\n />\n </button>\n ))}\n </div>\n\n {/* Pagination */}\n {data.totalPages > 1 && (\n <div className=\"flex items-center justify-between\">\n <button\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n disabled={page <= 1}\n className=\"px-2 py-1 text-xs rounded border border-border disabled:opacity-50 hover:bg-surface\"\n >\n {formatMessage({ id: 'theme.background.prev' })}\n </button>\n <span className=\"text-xs text-text-secondary\">\n {page} / {data.totalPages}\n </span>\n <button\n onClick={() => setPage((p) => Math.min(data.totalPages, p + 1))}\n disabled={page >= data.totalPages}\n className=\"px-2 py-1 text-xs rounded border border-border disabled:opacity-50 hover:bg-surface\"\n >\n {formatMessage({ id: 'theme.background.next' })}\n </button>\n </div>\n )}\n </>\n )}\n\n {data && data.photos.length === 0 && searchQuery.trim() && (\n <p className=\"text-xs text-text-secondary py-2 text-center\">\n {formatMessage({ id: 'theme.background.noResults' })}\n </p>\n )}\n\n {/* Custom URL input */}\n <div className=\"flex gap-2\">\n <input\n type=\"url\"\n value={customUrl}\n onChange={(e) => setCustomUrl(e.target.value)}\n placeholder={formatMessage({ id: 'theme.background.customUrlPlaceholder' })}\n className=\"flex-1 px-3 py-2 text-xs rounded-lg border border-border bg-bg text-text\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1\"\n />\n <button\n onClick={handleCustomUrlApply}\n disabled={!customUrl.trim()}\n className=\"px-3 py-2 text-xs rounded-lg bg-accent text-white disabled:opacity-50 hover:opacity-90 transition-opacity\"\n >\n {formatMessage({ id: 'theme.background.apply' })}\n </button>\n </div>\n\n {/* Upload local image */}\n <div className=\"space-y-1\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/jpeg,image/png,image/webp,image/gif\"\n onChange={handleFileUpload}\n className=\"hidden\"\n />\n <button\n onClick={() => fileInputRef.current?.click()}\n disabled={isUploading}\n className=\"w-full px-3 py-2 text-xs rounded-lg border border-dashed border-border\n bg-bg text-text hover:bg-surface hover:border-accent\n disabled:opacity-50 transition-all flex items-center justify-center gap-2\"\n >\n {isUploading ? (\n <>\n <div className=\"w-3.5 h-3.5 border-2 border-border border-t-accent rounded-full animate-spin\" />\n {formatMessage({ id: 'theme.background.uploading' })}\n </>\n ) : (\n formatMessage({ id: 'theme.background.upload' })\n )}\n </button>\n {uploadError && (\n <p className=\"text-xs text-destructive\">{uploadError}</p>\n )}\n </div>\n </div>\n )}\n\n {/* Effects panel */}\n {showImageControls && (\n <div className=\"space-y-3 pt-2 border-t border-border\">\n <h4 className=\"text-xs font-medium text-text-secondary\">\n {formatMessage({ id: 'theme.background.effects' })}\n </h4>\n\n {/* Blur slider */}\n <div className=\"space-y-1\">\n <div className=\"flex justify-between\">\n <label className=\"text-xs text-text\">\n {formatMessage({ id: 'theme.background.blur' })}\n </label>\n <span className=\"text-xs text-text-secondary\">{backgroundConfig.effects.blur}px</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"20\"\n step=\"1\"\n value={backgroundConfig.effects.blur}\n onChange={(e) => updateBackgroundEffect('blur', Number(e.target.value))}\n className=\"w-full accent-[hsl(var(--accent))]\"\n />\n </div>\n\n {/* Darken slider */}\n <div className=\"space-y-1\">\n <div className=\"flex justify-between\">\n <label className=\"text-xs text-text\">\n {formatMessage({ id: 'theme.background.darken' })}\n </label>\n <span className=\"text-xs text-text-secondary\">{backgroundConfig.effects.darkenOpacity}%</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"80\"\n step=\"1\"\n value={backgroundConfig.effects.darkenOpacity}\n onChange={(e) => updateBackgroundEffect('darkenOpacity', Number(e.target.value))}\n className=\"w-full accent-[hsl(var(--accent))]\"\n />\n </div>\n\n {/* Saturation slider */}\n <div className=\"space-y-1\">\n <div className=\"flex justify-between\">\n <label className=\"text-xs text-text\">\n {formatMessage({ id: 'theme.background.saturation' })}\n </label>\n <span className=\"text-xs text-text-secondary\">{backgroundConfig.effects.saturation}%</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"200\"\n step=\"5\"\n value={backgroundConfig.effects.saturation}\n onChange={(e) => updateBackgroundEffect('saturation', Number(e.target.value))}\n className=\"w-full accent-[hsl(var(--accent))]\"\n />\n </div>\n\n {/* Frosted glass checkbox */}\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={backgroundConfig.effects.enableFrostedGlass}\n onChange={(e) => updateBackgroundEffect('enableFrostedGlass', e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-accent focus:ring-2 focus:ring-accent focus:ring-offset-2\"\n />\n <span className=\"text-sm text-text\">\n {formatMessage({ id: 'theme.background.frostedGlass' })}\n </span>\n </label>\n\n {/* Grain checkbox */}\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={backgroundConfig.effects.enableGrain}\n onChange={(e) => updateBackgroundEffect('enableGrain', e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-accent focus:ring-2 focus:ring-accent focus:ring-offset-2\"\n />\n <span className=\"text-sm text-text\">\n {formatMessage({ id: 'theme.background.grain' })}\n </span>\n </label>\n\n {/* Vignette checkbox */}\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={backgroundConfig.effects.enableVignette}\n onChange={(e) => updateBackgroundEffect('enableVignette', e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-accent focus:ring-2 focus:ring-accent focus:ring-offset-2\"\n />\n <span className=\"text-sm text-text\">\n {formatMessage({ id: 'theme.background.vignette' })}\n </span>\n </label>\n </div>\n )}\n </div>\n );\n}\n","import React, { useState, useEffect, useRef, useCallback } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport { useTheme } from '@/hooks/useTheme';\r\nimport { useNotifications } from '@/hooks/useNotifications';\r\nimport { COLOR_SCHEMES, THEME_MODES, getThemeName, THEME_SLOT_LIMIT, DEFAULT_BACKGROUND_CONFIG } from '@/lib/theme';\r\nimport type { ColorScheme, ThemeMode } from '@/lib/theme';\r\nimport type { ThemeSlotId, StyleTier } from '@/types/store';\r\nimport { generateThemeFromHue, applyStyleTier } from '@/lib/colorGenerator';\r\nimport { checkThemeContrast, generateContrastFix } from '@/lib/accessibility';\r\nimport type { ContrastResult, FixSuggestion } from '@/lib/accessibility';\r\nimport type { ThemeSharePayload } from '@/lib/themeShare';\r\nimport { BackgroundImagePicker } from './BackgroundImagePicker';\r\nimport {\r\n AlertDialog,\r\n AlertDialogContent,\r\n AlertDialogHeader,\r\n AlertDialogTitle,\r\n AlertDialogDescription,\r\n AlertDialogFooter,\r\n AlertDialogAction,\r\n AlertDialogCancel,\r\n} from '@/components/ui/AlertDialog';\r\n\r\n/**\r\n * Theme Selector Component\r\n * Allows users to select from 4 color schemes (blue/green/orange/purple)\r\n * and 2 theme modes (light/dark), plus custom hue customization\r\n *\r\n * Features:\r\n * - 8 preset theme combinations + custom hue support\r\n * - Keyboard navigation support (Arrow keys)\r\n * - ARIA labels for accessibility\r\n * - Visual feedback for selected theme\r\n * - System dark mode detection\r\n * - Custom hue slider (0-360) with real-time preview\r\n */\r\nexport function ThemeSelector() {\r\n const { formatMessage } = useIntl();\r\n const {\r\n colorScheme,\r\n resolvedTheme,\r\n customHue,\r\n isCustomTheme,\r\n gradientLevel,\r\n enableHoverGlow,\r\n enableBackgroundAnimation,\r\n motionPreference,\r\n setColorScheme,\r\n setTheme,\r\n setCustomHue,\r\n setGradientLevel,\r\n setEnableHoverGlow,\r\n setEnableBackgroundAnimation,\r\n setMotionPreference,\r\n styleTier,\r\n setStyleTier,\r\n themeSlots,\r\n activeSlotId,\r\n canAddSlot,\r\n setActiveSlot,\r\n copySlot,\r\n renameSlot,\r\n deleteSlot,\r\n undoDeleteSlot,\r\n exportThemeCode,\r\n importThemeCode,\r\n setBackgroundConfig,\r\n } = useTheme();\r\n const { addToast, removeToast } = useNotifications();\r\n\r\n // Local state for preview hue (uncommitted changes)\r\n const [previewHue, setPreviewHue] = useState<number | null>(customHue);\r\n\r\n // Contrast warning state (non-blocking)\r\n const [contrastWarnings, setContrastWarnings] = useState<ContrastResult[]>([]);\r\n const [contrastFixes, setContrastFixes] = useState<Record<string, FixSuggestion[]>>({});\r\n const [showContrastWarning, setShowContrastWarning] = useState(false);\r\n\r\n // Slot management state\r\n const [renamingSlotId, setRenamingSlotId] = useState<ThemeSlotId | null>(null);\r\n const [renameValue, setRenameValue] = useState('');\r\n const [pendingDeleteSlot, setPendingDeleteSlot] = useState<ThemeSlotId | null>(null);\r\n const renameInputRef = useRef<HTMLInputElement>(null);\r\n const undoToastIdRef = useRef<string | null>(null);\r\n\r\n // Share/import state (local to component, not in store)\r\n const [showImportPanel, setShowImportPanel] = useState(false);\r\n const [importCode, setImportCode] = useState('');\r\n const [importPreview, setImportPreview] = useState<ThemeSharePayload | null>(null);\r\n const [importWarning, setImportWarning] = useState<string | null>(null);\r\n const [importError, setImportError] = useState<string | null>(null);\r\n const [copyFeedback, setCopyFeedback] = useState(false);\r\n\r\n // Sync preview with customHue from store\r\n useEffect(() => {\r\n setPreviewHue(customHue);\r\n }, [customHue]);\r\n\r\n // Resolved mode is either 'light' or 'dark'\r\n const mode: ThemeMode = resolvedTheme;\r\n\r\n // Get preview colors for the custom theme swatches\r\n const getPreviewColor = (variable: string) => {\r\n const hue = previewHue ?? 180; // Default to cyan if null\r\n const colors = generateThemeFromHue(hue, mode);\r\n const hslValue = colors[variable];\r\n return hslValue ? `hsl(${hslValue})` : '#888';\r\n };\r\n\r\n // Style tier definitions for the selector UI\r\n const STYLE_TIERS: Array<{ id: StyleTier; nameKey: string; descKey: string }> = [\r\n { id: 'soft', nameKey: 'theme.styleTier.soft', descKey: 'theme.styleTier.softDesc' },\r\n { id: 'standard', nameKey: 'theme.styleTier.standard', descKey: 'theme.styleTier.standardDesc' },\r\n { id: 'high-contrast', nameKey: 'theme.styleTier.highContrast', descKey: 'theme.styleTier.highContrastDesc' },\r\n ];\r\n\r\n // Get tier preview swatch colors (bg, surface, accent for a sample tier)\r\n const getTierPreviewColors = (tier: StyleTier): { bg: string; surface: string; accent: string } => {\r\n const sampleHue = customHue ?? 220; // Use current hue or default blue\r\n const baseVars = generateThemeFromHue(sampleHue, mode);\r\n const tieredVars = tier === 'standard' ? baseVars : applyStyleTier(baseVars, tier, mode);\r\n return {\r\n bg: tieredVars['--bg'] ? `hsl(${tieredVars['--bg']})` : '#888',\r\n surface: tieredVars['--surface'] ? `hsl(${tieredVars['--surface']})` : '#888',\r\n accent: tieredVars['--accent'] ? `hsl(${tieredVars['--accent']})` : '#888',\r\n };\r\n };\r\n\r\n const handleSchemeSelect = (scheme: ColorScheme) => {\r\n // When selecting a preset scheme, reset custom hue\r\n if (isCustomTheme) {\r\n setCustomHue(null);\r\n }\r\n setColorScheme(scheme);\r\n };\r\n\r\n const handleCustomSelect = () => {\r\n // Set custom hue to a default value if null\r\n if (customHue === null) {\r\n setCustomHue(180); // Default cyan\r\n }\r\n };\r\n\r\n const handleHueSave = () => {\r\n if (previewHue !== null) {\r\n setCustomHue(previewHue);\r\n\r\n // Run contrast check on the new custom theme\r\n const mode: ThemeMode = resolvedTheme;\r\n const vars = generateThemeFromHue(previewHue, mode);\r\n const results = checkThemeContrast(vars);\r\n const failures = results.filter(r => !r.passed);\r\n\r\n if (failures.length > 0) {\r\n setContrastWarnings(failures);\r\n // Generate fixes for each failing pair\r\n const fixes: Record<string, FixSuggestion[]> = {};\r\n for (const failure of failures) {\r\n const key = `${failure.fgVar}|${failure.bgVar}`;\r\n fixes[key] = generateContrastFix(failure.fgVar, failure.bgVar, vars, failure.required);\r\n }\r\n setContrastFixes(fixes);\r\n setShowContrastWarning(true);\r\n } else {\r\n setContrastWarnings([]);\r\n setContrastFixes({});\r\n setShowContrastWarning(false);\r\n }\r\n }\r\n };\r\n\r\n const handleHueReset = () => {\r\n setCustomHue(null);\r\n setPreviewHue(null);\r\n };\r\n\r\n const handleModeSelect = (newMode: ThemeMode) => {\r\n setTheme(newMode);\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\r\n e.preventDefault();\r\n const currentIndex = COLOR_SCHEMES.findIndex(s => s.id === colorScheme);\r\n const nextIndex = (currentIndex + 1) % COLOR_SCHEMES.length;\r\n handleSchemeSelect(COLOR_SCHEMES[nextIndex].id);\r\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\r\n e.preventDefault();\r\n const currentIndex = COLOR_SCHEMES.findIndex(s => s.id === colorScheme);\r\n const nextIndex = (currentIndex - 1 + COLOR_SCHEMES.length) % COLOR_SCHEMES.length;\r\n handleSchemeSelect(COLOR_SCHEMES[nextIndex].id);\r\n }\r\n };\r\n\r\n // ========== Slot Management Handlers ==========\r\n\r\n const handleSlotSelect = useCallback((slotId: ThemeSlotId) => {\r\n if (slotId !== activeSlotId) {\r\n setActiveSlot(slotId);\r\n }\r\n }, [activeSlotId, setActiveSlot]);\r\n\r\n const handleCopySlot = useCallback(() => {\r\n if (!canAddSlot) return;\r\n copySlot();\r\n }, [canAddSlot, copySlot]);\r\n\r\n const handleStartRename = useCallback((slotId: ThemeSlotId, currentName: string) => {\r\n setRenamingSlotId(slotId);\r\n setRenameValue(currentName);\r\n // Focus input after render\r\n setTimeout(() => renameInputRef.current?.focus(), 0);\r\n }, []);\r\n\r\n const handleConfirmRename = useCallback(() => {\r\n if (renamingSlotId && renameValue.trim()) {\r\n renameSlot(renamingSlotId, renameValue.trim());\r\n }\r\n setRenamingSlotId(null);\r\n setRenameValue('');\r\n }, [renamingSlotId, renameValue, renameSlot]);\r\n\r\n const handleCancelRename = useCallback(() => {\r\n setRenamingSlotId(null);\r\n setRenameValue('');\r\n }, []);\r\n\r\n const handleRenameKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n handleConfirmRename();\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n handleCancelRename();\r\n }\r\n }, [handleConfirmRename, handleCancelRename]);\r\n\r\n const handleConfirmDelete = useCallback(() => {\r\n if (!pendingDeleteSlot) return;\r\n\r\n deleteSlot(pendingDeleteSlot);\r\n setPendingDeleteSlot(null);\r\n\r\n // Remove previous undo toast if exists\r\n if (undoToastIdRef.current) {\r\n removeToast(undoToastIdRef.current);\r\n }\r\n\r\n // Show undo toast with 10-second duration\r\n const toastId = addToast('info',\r\n formatMessage({ id: 'theme.slot.undoDelete' }),\r\n undefined,\r\n {\r\n duration: 10000,\r\n dismissible: true,\r\n action: {\r\n label: formatMessage({ id: 'theme.slot.undo' }),\r\n onClick: () => {\r\n undoDeleteSlot();\r\n removeToast(toastId);\r\n undoToastIdRef.current = null;\r\n },\r\n },\r\n }\r\n );\r\n undoToastIdRef.current = toastId;\r\n }, [pendingDeleteSlot, deleteSlot, addToast, removeToast, undoDeleteSlot, formatMessage]);\r\n\r\n const handleCancelDelete = useCallback(() => {\r\n setPendingDeleteSlot(null);\r\n }, []);\r\n\r\n // ========== Share/Import Handlers ==========\r\n\r\n const handleCopyThemeCode = useCallback(async () => {\r\n try {\r\n const code = exportThemeCode();\r\n await navigator.clipboard.writeText(code);\r\n setCopyFeedback(true);\r\n setTimeout(() => setCopyFeedback(false), 2000);\r\n } catch {\r\n // Clipboard API may not be available\r\n addToast('error', 'Failed to copy to clipboard');\r\n }\r\n }, [exportThemeCode, addToast]);\r\n\r\n const handleOpenImport = useCallback(() => {\r\n setShowImportPanel(true);\r\n setImportCode('');\r\n setImportPreview(null);\r\n setImportWarning(null);\r\n setImportError(null);\r\n }, []);\r\n\r\n const handleCloseImport = useCallback(() => {\r\n setShowImportPanel(false);\r\n setImportCode('');\r\n setImportPreview(null);\r\n setImportWarning(null);\r\n setImportError(null);\r\n }, []);\r\n\r\n const handleImportCodeChange = useCallback((value: string) => {\r\n setImportCode(value);\r\n setImportError(null);\r\n setImportWarning(null);\r\n setImportPreview(null);\r\n\r\n if (!value.trim()) return;\r\n\r\n const result = importThemeCode(value);\r\n if (result.ok) {\r\n setImportPreview(result.payload);\r\n if (result.warning) {\r\n setImportWarning(result.warning);\r\n }\r\n } else {\r\n setImportError(result.error);\r\n }\r\n }, [importThemeCode]);\r\n\r\n const handleApplyImport = useCallback(() => {\r\n if (!importPreview) return;\r\n\r\n // Check if we can add a slot or overwrite current\r\n if (!canAddSlot && activeSlotId === 'default') {\r\n // Apply to the default slot directly via individual setters\r\n if (importPreview.customHue !== null) {\r\n setCustomHue(importPreview.customHue);\r\n } else {\r\n setCustomHue(null);\r\n setColorScheme(importPreview.colorScheme);\r\n }\r\n setGradientLevel(importPreview.gradientLevel);\r\n setEnableHoverGlow(importPreview.enableHoverGlow);\r\n setEnableBackgroundAnimation(importPreview.enableBackgroundAnimation);\r\n setStyleTier(importPreview.styleTier);\r\n } else if (canAddSlot) {\r\n // Create a new slot via copySlot then apply settings\r\n copySlot();\r\n // After copySlot, the new slot is active. Apply imported settings.\r\n if (importPreview.customHue !== null) {\r\n setCustomHue(importPreview.customHue);\r\n } else {\r\n setCustomHue(null);\r\n setColorScheme(importPreview.colorScheme);\r\n }\r\n setGradientLevel(importPreview.gradientLevel);\r\n setEnableHoverGlow(importPreview.enableHoverGlow);\r\n setEnableBackgroundAnimation(importPreview.enableBackgroundAnimation);\r\n setStyleTier(importPreview.styleTier);\r\n } else {\r\n // Apply to current active slot via individual setters\r\n if (importPreview.customHue !== null) {\r\n setCustomHue(importPreview.customHue);\r\n } else {\r\n setCustomHue(null);\r\n setColorScheme(importPreview.colorScheme);\r\n }\r\n setGradientLevel(importPreview.gradientLevel);\r\n setEnableHoverGlow(importPreview.enableHoverGlow);\r\n setEnableBackgroundAnimation(importPreview.enableBackgroundAnimation);\r\n setStyleTier(importPreview.styleTier);\r\n }\r\n\r\n // Apply background config from import (v2+ feature)\r\n setBackgroundConfig(importPreview.backgroundConfig ?? DEFAULT_BACKGROUND_CONFIG);\r\n\r\n addToast('success', formatMessage({ id: 'theme.share.importSuccess' }));\r\n handleCloseImport();\r\n }, [\r\n importPreview, canAddSlot, activeSlotId, copySlot,\r\n setCustomHue, setColorScheme, setGradientLevel,\r\n setEnableHoverGlow, setEnableBackgroundAnimation, setStyleTier,\r\n setBackgroundConfig,\r\n addToast, formatMessage, handleCloseImport,\r\n ]);\r\n\r\n /** Generate preview swatch colors from an import payload */\r\n const getImportPreviewColors = useCallback((payload: ThemeSharePayload) => {\r\n const hue = payload.customHue ?? 220;\r\n const baseVars = generateThemeFromHue(hue, mode);\r\n const tieredVars = payload.styleTier === 'standard'\r\n ? baseVars\r\n : applyStyleTier(baseVars, payload.styleTier, mode);\r\n return {\r\n bg: tieredVars['--bg'] ? `hsl(${tieredVars['--bg']})` : '#888',\r\n surface: tieredVars['--surface'] ? `hsl(${tieredVars['--surface']})` : '#888',\r\n accent: tieredVars['--accent'] ? `hsl(${tieredVars['--accent']})` : '#888',\r\n text: tieredVars['--text'] ? `hsl(${tieredVars['--text']})` : '#888',\r\n };\r\n }, [mode]);\r\n\r\n /** Map error keys to i18n message IDs */\r\n const getShareErrorMessageId = (errorKey: string): string => {\r\n switch (errorKey) {\r\n case 'incompatible_version':\r\n return 'theme.share.incompatibleVersion';\r\n default:\r\n return 'theme.share.invalidCode';\r\n }\r\n };\r\n\r\n // Focus rename input when entering rename mode\r\n useEffect(() => {\r\n if (renamingSlotId && renameInputRef.current) {\r\n renameInputRef.current.focus();\r\n renameInputRef.current.select();\r\n }\r\n }, [renamingSlotId]);\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Theme Slot Switcher */}\r\n <div>\r\n <div className=\"flex items-center justify-between mb-3\">\r\n <h3 className=\"text-sm font-medium text-text\">\r\n {formatMessage({ id: 'theme.slot.title' })}\r\n </h3>\r\n <button\r\n onClick={handleCopySlot}\r\n disabled={!canAddSlot}\r\n title={\r\n canAddSlot\r\n ? formatMessage({ id: 'theme.slot.copy' })\r\n : formatMessage({ id: 'theme.slot.limitReached' }, { limit: THEME_SLOT_LIMIT })\r\n }\r\n className={`\r\n px-2 py-1 rounded text-xs font-medium\r\n transition-all duration-200\r\n ${canAddSlot\r\n ? 'bg-accent text-white hover:bg-accent-hover focus:ring-2 focus:ring-accent focus:ring-offset-1'\r\n : 'bg-muted text-muted-text cursor-not-allowed'\r\n }\r\n focus:outline-none\r\n `}\r\n >\r\n + {formatMessage({ id: 'theme.slot.copy' })}\r\n </button>\r\n </div>\r\n\r\n <div className=\"flex gap-2\" role=\"tablist\" aria-label={formatMessage({ id: 'theme.slot.title' })}>\r\n {themeSlots.map((slot) => {\r\n const isActive = slot.id === activeSlotId;\r\n const isRenaming = slot.id === renamingSlotId;\r\n\r\n return (\r\n <div\r\n key={slot.id}\r\n role=\"tab\"\r\n aria-selected={isActive}\r\n tabIndex={isActive ? 0 : -1}\r\n onClick={() => handleSlotSelect(slot.id)}\r\n className={`\r\n relative flex-1 min-w-0 p-2.5 rounded-lg cursor-pointer\r\n transition-all duration-200 border-2 group\r\n ${isActive\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1\r\n `}\r\n >\r\n {/* Active indicator */}\r\n {isActive && (\r\n <span className=\"absolute -top-1 -right-1 w-2.5 h-2.5 rounded-full bg-accent border-2 border-bg\" />\r\n )}\r\n\r\n {/* Slot name - inline rename or display */}\r\n <div className=\"flex items-center gap-1 min-w-0\">\r\n {isRenaming ? (\r\n <input\r\n ref={renameInputRef}\r\n type=\"text\"\r\n value={renameValue}\r\n onChange={(e) => setRenameValue(e.target.value)}\r\n onKeyDown={handleRenameKeyDown}\r\n onBlur={handleConfirmRename}\r\n onClick={(e) => e.stopPropagation()}\r\n className=\"\r\n w-full px-1 py-0.5 text-xs font-medium text-text\r\n bg-bg border border-accent rounded\r\n focus:outline-none focus:ring-1 focus:ring-accent\r\n \"\r\n maxLength={20}\r\n />\r\n ) : (\r\n <span\r\n className=\"text-xs font-medium text-text truncate\"\r\n title={slot.name}\r\n onDoubleClick={(e) => {\r\n e.stopPropagation();\r\n if (!slot.isDefault) {\r\n handleStartRename(slot.id, slot.name);\r\n }\r\n }}\r\n >\r\n {slot.name}\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* Active label */}\r\n {isActive && !isRenaming && (\r\n <span className=\"text-[10px] text-accent font-medium mt-0.5 block\">\r\n {formatMessage({ id: 'theme.slot.active' })}\r\n </span>\r\n )}\r\n\r\n {/* Action buttons - show on hover for non-default slots */}\r\n {!slot.isDefault && !isRenaming && (\r\n <div className=\"\r\n absolute top-1 right-1 flex gap-0.5\r\n opacity-0 group-hover:opacity-100 transition-opacity duration-150\r\n \">\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleStartRename(slot.id, slot.name);\r\n }}\r\n title={formatMessage({ id: 'theme.slot.rename' })}\r\n className=\"\r\n p-0.5 rounded text-text-tertiary hover:text-text hover:bg-surface-hover\r\n transition-colors duration-150 focus:outline-none\r\n \"\r\n >\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M11.5 1.5L14.5 4.5L5 14H2V11L11.5 1.5Z\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n setPendingDeleteSlot(slot.id);\r\n }}\r\n title={formatMessage({ id: 'theme.slot.delete' })}\r\n className=\"\r\n p-0.5 rounded text-text-tertiary hover:text-error hover:bg-error-light\r\n transition-colors duration-150 focus:outline-none\r\n \"\r\n >\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M4 4L12 12M12 4L4 12\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Default slot: show disabled delete tooltip */}\r\n {slot.isDefault && (\r\n <div className=\"\r\n absolute top-1 right-1 flex gap-0.5\r\n opacity-0 group-hover:opacity-100 transition-opacity duration-150\r\n \">\r\n <button\r\n disabled\r\n title={formatMessage({ id: 'theme.slot.cannotDeleteDefault' })}\r\n className=\"p-0.5 rounded text-muted-text cursor-not-allowed\"\r\n >\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M4 4L12 12M12 4L4 12\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Color Scheme Selection */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.title.colorScheme' })}\r\n </h3>\r\n <div\r\n className=\"grid grid-cols-5 gap-3\"\r\n role=\"group\"\r\n aria-label=\"Color scheme selection\"\r\n onKeyDown={handleKeyDown}\r\n >\r\n {COLOR_SCHEMES.map((scheme) => (\r\n <button\r\n key={scheme.id}\r\n onClick={() => handleSchemeSelect(scheme.id)}\r\n aria-label={formatMessage({ id: 'theme.select.colorScheme' }, { name: formatMessage({ id: `theme.colorScheme.${scheme.id}` }) })}\r\n aria-selected={colorScheme === scheme.id && !isCustomTheme}\r\n role=\"radio\"\r\n className={`\r\n flex flex-col items-center gap-2 p-3 rounded-lg\r\n transition-all duration-200 border-2\r\n ${colorScheme === scheme.id && !isCustomTheme\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {/* Color swatch */}\r\n <div\r\n className=\"w-8 h-8 rounded-full border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: scheme.accentColor }}\r\n aria-hidden=\"true\"\r\n />\r\n {/* Label */}\r\n <span className=\"text-xs font-medium text-text text-center\">\r\n {formatMessage({ id: `theme.colorScheme.${scheme.id}` })}\r\n </span>\r\n </button>\r\n ))}\r\n\r\n {/* Custom Color Option */}\r\n <button\r\n onClick={handleCustomSelect}\r\n aria-label={formatMessage({ id: 'theme.select.colorScheme' }, { name: formatMessage({ id: 'theme.colorScheme.custom' }) })}\r\n aria-selected={isCustomTheme}\r\n role=\"radio\"\r\n className={`\r\n flex flex-col items-center gap-2 p-3 rounded-lg\r\n transition-all duration-200 border-2\r\n ${isCustomTheme\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {/* Gradient swatch showing current custom hue */}\r\n <div\r\n className=\"w-8 h-8 rounded-full border-2 border-border shadow-sm\"\r\n style={{\r\n background: `linear-gradient(135deg, ${getPreviewColor('--accent')}, ${getPreviewColor('--primary')})`\r\n }}\r\n aria-hidden=\"true\"\r\n />\r\n {/* Label */}\r\n <span className=\"text-xs font-medium text-text text-center\">\r\n {formatMessage({ id: 'theme.colorScheme.custom' })}\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Custom Hue Selection - Only shown when custom theme is active */}\r\n {isCustomTheme && (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.title.customHue' })}\r\n </h3>\r\n\r\n {/* Hue Slider */}\r\n <div className=\"space-y-3\">\r\n <div className=\"flex items-center justify-between\">\r\n <label htmlFor=\"hue-slider\" className=\"text-xs text-text-secondary\">\r\n {formatMessage({ id: 'theme.hueValue' }, { value: previewHue ?? 180 })}\r\n </label>\r\n </div>\r\n <input\r\n id=\"hue-slider\"\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"360\"\r\n step=\"1\"\r\n value={previewHue ?? 180}\r\n onChange={(e) => setPreviewHue(Number(e.target.value))}\r\n className=\"w-full h-2 rounded-lg appearance-none cursor-pointer\"\r\n style={{\r\n background: `linear-gradient(to right,\r\n hsl(0, 70%, 60%), hsl(60, 70%, 60%), hsl(120, 70%, 60%),\r\n hsl(180, 70%, 60%), hsl(240, 70%, 60%), hsl(300, 70%, 60%), hsl(360, 70%, 60%))`\r\n }}\r\n aria-label={formatMessage({ id: 'theme.title.customHue' })}\r\n />\r\n\r\n {/* Preview Swatches */}\r\n <div className=\"flex gap-3 items-end\">\r\n <span className=\"text-xs text-text-secondary pb-1\">\r\n {formatMessage({ id: 'theme.preview' })}:\r\n </span>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: getPreviewColor('--bg') }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">{formatMessage({ id: 'theme.preview.background' })}</span>\r\n </div>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: getPreviewColor('--surface') }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">{formatMessage({ id: 'theme.preview.surface' })}</span>\r\n </div>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: getPreviewColor('--accent') }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">{formatMessage({ id: 'theme.preview.accent' })}</span>\r\n </div>\r\n </div>\r\n\r\n {/* Save and Reset Buttons */}\r\n <div className=\"flex gap-2 pt-2\">\r\n <button\r\n onClick={handleHueSave}\r\n disabled={previewHue === customHue}\r\n className={`\r\n flex-1 px-4 py-2 rounded-lg text-sm font-medium\r\n transition-all duration-200\r\n ${previewHue === customHue\r\n ? 'bg-muted text-muted-text cursor-not-allowed'\r\n : 'bg-accent text-white hover:bg-accent-hover focus:ring-2 focus:ring-accent focus:ring-offset-2'\r\n }\r\n `}\r\n >\r\n {formatMessage({ id: 'theme.save' })}\r\n </button>\r\n <button\r\n onClick={handleHueReset}\r\n className=\"\r\n px-4 py-2 rounded-lg text-sm font-medium\r\n border-2 border-border bg-bg text-text\r\n hover:bg-surface transition-all duration-200\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n >\r\n {formatMessage({ id: 'theme.reset' })}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Style Tier Selection */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.styleTier.label' })}\r\n </h3>\r\n <div\r\n className=\"grid grid-cols-3 gap-3\"\r\n role=\"radiogroup\"\r\n aria-label={formatMessage({ id: 'theme.styleTier.label' })}\r\n >\r\n {STYLE_TIERS.map((tier) => {\r\n const preview = getTierPreviewColors(tier.id);\r\n const isSelected = styleTier === tier.id;\r\n return (\r\n <button\r\n key={tier.id}\r\n onClick={() => setStyleTier(tier.id)}\r\n role=\"radio\"\r\n aria-checked={isSelected}\r\n className={`\r\n flex flex-col items-center gap-2 p-3 rounded-lg\r\n transition-all duration-200 border-2\r\n ${isSelected\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {/* Preview swatches */}\r\n <div className=\"flex gap-1\" aria-hidden=\"true\">\r\n <div\r\n className=\"w-5 h-5 rounded-sm border border-border\"\r\n style={{ backgroundColor: preview.bg }}\r\n />\r\n <div\r\n className=\"w-5 h-5 rounded-sm border border-border\"\r\n style={{ backgroundColor: preview.surface }}\r\n />\r\n <div\r\n className=\"w-5 h-5 rounded-sm border border-border\"\r\n style={{ backgroundColor: preview.accent }}\r\n />\r\n </div>\r\n {/* Tier name */}\r\n <span className=\"text-xs font-medium text-text text-center\">\r\n {formatMessage({ id: tier.nameKey })}\r\n </span>\r\n {/* Description */}\r\n <span className=\"text-[10px] text-text-tertiary text-center leading-tight\">\r\n {formatMessage({ id: tier.descKey })}\r\n </span>\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Gradient Effects Settings */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.gradient.title' })}\r\n </h3>\r\n\r\n {/* Gradient Level Selection */}\r\n <div className=\"space-y-4\">\r\n <div\r\n className=\"flex gap-2\"\r\n role=\"radiogroup\"\r\n aria-label={formatMessage({ id: 'theme.gradient.title' })}\r\n >\r\n {(['off', 'standard', 'enhanced'] as const).map((level) => (\r\n <button\r\n key={level}\r\n onClick={() => setGradientLevel(level)}\r\n role=\"radio\"\r\n aria-checked={gradientLevel === level}\r\n className={`\r\n flex-1 px-3 py-2 rounded-lg text-sm font-medium\r\n transition-all duration-200 border-2\r\n ${gradientLevel === level\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {formatMessage({ id: `theme.gradient.${level}` })}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Hover Glow Checkbox */}\r\n <label className=\"flex items-center gap-3 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={enableHoverGlow}\r\n onChange={(e) => setEnableHoverGlow(e.target.checked)}\r\n className=\"\r\n w-4 h-4 rounded border-border text-accent\r\n focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n />\r\n <span className=\"text-sm text-text\">\r\n {formatMessage({ id: 'theme.gradient.hoverGlow' })}\r\n </span>\r\n </label>\r\n\r\n {/* Background Animation Checkbox */}\r\n <label className=\"flex items-center gap-3 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={enableBackgroundAnimation}\r\n onChange={(e) => setEnableBackgroundAnimation(e.target.checked)}\r\n className=\"\r\n w-4 h-4 rounded border-border text-accent\r\n focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n />\r\n <span className=\"text-sm text-text\">\r\n {formatMessage({ id: 'theme.gradient.bgAnimation' })}\r\n </span>\r\n </label>\r\n </div>\r\n </div>\r\n\r\n {/* Background Image */}\r\n <BackgroundImagePicker />\r\n\r\n {/* Motion Preference */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.motion.label' })}\r\n </h3>\r\n <div\r\n className=\"flex gap-2\"\r\n role=\"radiogroup\"\r\n aria-label={formatMessage({ id: 'theme.motion.label' })}\r\n >\r\n {(['system', 'reduce', 'enable'] as const).map((pref) => (\r\n <button\r\n key={pref}\r\n onClick={() => setMotionPreference(pref)}\r\n role=\"radio\"\r\n aria-checked={motionPreference === pref}\r\n className={`\r\n flex-1 px-3 py-2 rounded-lg text-sm font-medium\r\n transition-all duration-200 border-2\r\n ${motionPreference === pref\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {formatMessage({ id: `theme.motion.${pref}` })}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Contrast Warning Banner (non-blocking) */}\r\n {showContrastWarning && contrastWarnings.length > 0 && (\r\n <div className=\"p-3 rounded-lg bg-warning-light border border-warning text-warning-text space-y-2\">\r\n <p className=\"text-xs font-medium\">\r\n {formatMessage({ id: 'theme.accessibility.contrastWarning' })}\r\n </p>\r\n <ul className=\"text-xs space-y-1\">\r\n {contrastWarnings.map((w) => {\r\n const key = `${w.fgVar}|${w.bgVar}`;\r\n const fixes = contrastFixes[key] || [];\r\n return (\r\n <li key={key} className=\"space-y-1\">\r\n <span>\r\n {w.fgVar} / {w.bgVar}: {w.ratio}:1 (min {w.required}:1)\r\n </span>\r\n {fixes.length > 0 && (\r\n <div className=\"ml-2 text-[10px]\">\r\n {fixes.slice(0, 1).map((fix, i) => (\r\n <span key={i} className=\"block\">\r\n {formatMessage(\r\n { id: 'theme.accessibility.fixSuggestion' },\r\n {\r\n target: fix.target === 'fg' ? w.fgVar : w.bgVar,\r\n original: fix.original,\r\n suggested: fix.suggested,\r\n ratio: fix.resultRatio,\r\n }\r\n )}\r\n </span>\r\n ))}\r\n </div>\r\n )}\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n <button\r\n onClick={() => setShowContrastWarning(false)}\r\n className=\"text-xs font-medium underline\"\r\n >\r\n {formatMessage({ id: 'theme.accessibility.dismiss' })}\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Theme Mode Selection */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.title.themeMode' })}\r\n </h3>\r\n <div\r\n className=\"grid grid-cols-2 gap-3\"\r\n role=\"group\"\r\n aria-label=\"Theme mode selection\"\r\n >\r\n {THEME_MODES.map((modeOption) => (\r\n <button\r\n key={modeOption.id}\r\n onClick={() => handleModeSelect(modeOption.id)}\r\n aria-label={formatMessage({ id: 'theme.select.themeMode' }, { name: formatMessage({ id: `theme.themeMode.${modeOption.id}` }) })}\r\n aria-selected={mode === modeOption.id}\r\n role=\"radio\"\r\n className={`\r\n flex items-center justify-center gap-2 p-3 rounded-lg\r\n transition-all duration-200 border-2\r\n ${mode === modeOption.id\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {/* Icon */}\r\n <span className=\"text-lg\" aria-hidden=\"true\">\r\n {modeOption.id === 'light' ? '☀️' : '🌙'}\r\n </span>\r\n {/* Label */}\r\n <span className=\"text-sm font-medium text-text\">\r\n {formatMessage({ id: `theme.themeMode.${modeOption.id}` })}\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Current Theme Display */}\r\n <div className=\"p-3 rounded-lg bg-surface border border-border\">\r\n <p className=\"text-xs text-text-secondary\">\r\n {formatMessage({ id: 'theme.current' }, { name: getThemeName(colorScheme, mode) })}\r\n </p>\r\n </div>\r\n\r\n {/* Theme Sharing Section */}\r\n <div>\r\n <h3 className=\"text-sm font-medium text-text mb-3\">\r\n {formatMessage({ id: 'theme.share.label' })}\r\n </h3>\r\n\r\n <div className=\"flex gap-2\">\r\n {/* Copy Theme Code button */}\r\n <button\r\n onClick={handleCopyThemeCode}\r\n className=\"\r\n flex-1 px-3 py-2 rounded-lg text-sm font-medium\r\n border-2 border-border bg-bg text-text\r\n hover:bg-surface transition-all duration-200\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n >\r\n {copyFeedback\r\n ? formatMessage({ id: 'theme.share.copied' })\r\n : formatMessage({ id: 'theme.share.copyCode' })\r\n }\r\n </button>\r\n\r\n {/* Import Theme button */}\r\n <button\r\n onClick={showImportPanel ? handleCloseImport : handleOpenImport}\r\n className={`\r\n flex-1 px-3 py-2 rounded-lg text-sm font-medium\r\n transition-all duration-200 border-2\r\n ${showImportPanel\r\n ? 'border-accent bg-surface shadow-md'\r\n : 'border-border bg-bg text-text hover:bg-surface'\r\n }\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n `}\r\n >\r\n {formatMessage({ id: 'theme.share.import' })}\r\n </button>\r\n </div>\r\n\r\n {/* Import Panel */}\r\n {showImportPanel && (\r\n <div className=\"mt-3 space-y-3\">\r\n {/* Paste textarea */}\r\n <textarea\r\n value={importCode}\r\n onChange={(e) => handleImportCodeChange(e.target.value)}\r\n placeholder={formatMessage({ id: 'theme.share.paste' })}\r\n rows={3}\r\n className=\"\r\n w-full px-3 py-2 rounded-lg text-sm font-mono\r\n bg-bg border-2 border-border text-text\r\n placeholder-text-tertiary resize-none\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:border-accent\r\n \"\r\n />\r\n\r\n {/* Error message */}\r\n {importError && (\r\n <div className=\"p-2 rounded-lg bg-error-light border border-error text-error-text text-xs\">\r\n {formatMessage({ id: getShareErrorMessageId(importError) })}\r\n </div>\r\n )}\r\n\r\n {/* Version warning */}\r\n {importWarning && !importError && (\r\n <div className=\"p-2 rounded-lg bg-warning-light border border-warning text-warning-text text-xs\">\r\n {formatMessage({ id: 'theme.share.versionWarning' })}\r\n </div>\r\n )}\r\n\r\n {/* Import Preview Card */}\r\n {importPreview && !importError && (\r\n <div className=\"p-3 rounded-lg bg-surface border border-border space-y-3\">\r\n <p className=\"text-xs font-medium text-text\">\r\n {formatMessage({ id: 'theme.share.preview' })}\r\n </p>\r\n\r\n {/* Preview swatches */}\r\n <div className=\"flex gap-3 items-end\">\r\n {(() => {\r\n const previewColors = getImportPreviewColors(importPreview);\r\n return (\r\n <>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: previewColors.bg }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">\r\n {formatMessage({ id: 'theme.preview.background' })}\r\n </span>\r\n </div>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: previewColors.surface }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">\r\n {formatMessage({ id: 'theme.preview.surface' })}\r\n </span>\r\n </div>\r\n <div className=\"flex flex-col items-center gap-1\">\r\n <div\r\n className=\"w-10 h-10 rounded border-2 border-border shadow-sm\"\r\n style={{ backgroundColor: previewColors.accent }}\r\n />\r\n <span className=\"text-[10px] text-text-tertiary\">\r\n {formatMessage({ id: 'theme.preview.accent' })}\r\n </span>\r\n </div>\r\n </>\r\n );\r\n })()}\r\n </div>\r\n\r\n {/* Settings summary */}\r\n <div className=\"text-xs text-text-secondary space-y-1\">\r\n <p>\r\n {formatMessage({ id: 'theme.styleTier.label' })}: {formatMessage({ id: `theme.styleTier.${importPreview.styleTier === 'high-contrast' ? 'highContrast' : importPreview.styleTier}` })}\r\n </p>\r\n <p>\r\n {formatMessage({ id: 'theme.gradient.title' })}: {formatMessage({ id: `theme.gradient.${importPreview.gradientLevel}` })}\r\n </p>\r\n {importPreview.customHue !== null && (\r\n <p>\r\n {formatMessage({ id: 'theme.hueValue' }, { value: importPreview.customHue })}\r\n </p>\r\n )}\r\n {importPreview.customHue === null && (\r\n <p>\r\n {formatMessage({ id: 'theme.title.colorScheme' })}: {formatMessage({ id: `theme.colorScheme.${importPreview.colorScheme}` })}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {/* Apply / Cancel buttons */}\r\n <div className=\"flex gap-2 pt-1\">\r\n <button\r\n onClick={handleApplyImport}\r\n className=\"\r\n flex-1 px-4 py-2 rounded-lg text-sm font-medium\r\n bg-accent text-white hover:bg-accent-hover\r\n transition-all duration-200\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n >\r\n {formatMessage({ id: 'theme.share.apply' })}\r\n </button>\r\n <button\r\n onClick={handleCloseImport}\r\n className=\"\r\n px-4 py-2 rounded-lg text-sm font-medium\r\n border-2 border-border bg-bg text-text\r\n hover:bg-surface transition-all duration-200\r\n focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2\r\n \"\r\n >\r\n {formatMessage({ id: 'theme.share.cancel' })}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Delete Confirmation Dialog */}\r\n <AlertDialog open={pendingDeleteSlot !== null} onOpenChange={handleCancelDelete}>\r\n <AlertDialogContent>\r\n <AlertDialogHeader>\r\n <AlertDialogTitle>Delete Theme Slot?</AlertDialogTitle>\r\n <AlertDialogDescription>\r\n This action cannot be undone. The theme slot will be permanently deleted.\r\n </AlertDialogDescription>\r\n </AlertDialogHeader>\r\n <AlertDialogFooter>\r\n <AlertDialogCancel onClick={handleCancelDelete}>Cancel</AlertDialogCancel>\r\n <AlertDialogAction onClick={handleConfirmDelete}>Delete</AlertDialogAction>\r\n </AlertDialogFooter>\r\n </AlertDialogContent>\r\n </AlertDialog>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","// ========================================\r\n// Language Switcher Component\r\n// ========================================\r\n// Language selection dropdown with flag icons\r\n\r\nimport { Languages } from 'lucide-react';\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '@/components/ui/Select';\r\nimport { useLocale } from '@/hooks/useLocale';\r\nimport { cn } from '@/lib/utils';\r\n\r\nexport interface LanguageSwitcherProps {\r\n /** Compact variant for header (smaller, icon-only trigger) */\r\n compact?: boolean;\r\n /** Additional CSS classes */\r\n className?: string;\r\n}\r\n\r\n// Language options with flag emojis and labels\r\nconst LANGUAGE_OPTIONS = [\r\n { value: 'en' as const, label: 'English', flag: '🇺🇸' },\r\n { value: 'zh' as const, label: '中文', flag: '🇨🇳' },\r\n] as const;\r\n\r\n/**\r\n * Language switcher component\r\n * Allows users to switch between English and Chinese\r\n */\r\nexport function LanguageSwitcher({ compact = false, className }: LanguageSwitcherProps) {\r\n const { locale, setLocale } = useLocale();\r\n\r\n return (\r\n <Select value={locale} onValueChange={setLocale}>\r\n <SelectTrigger\r\n className={cn(\r\n compact ? 'w-[110px]' : 'w-[160px]',\r\n 'gap-2',\r\n className\r\n )}\r\n aria-label=\"Select language\"\r\n >\r\n {compact ? (\r\n <>\r\n <Languages className=\"w-4 h-4\" />\r\n <SelectValue />\r\n </>\r\n ) : (\r\n <SelectValue />\r\n )}\r\n </SelectTrigger>\r\n <SelectContent>\r\n {LANGUAGE_OPTIONS.map((option) => (\r\n <SelectItem key={option.value} value={option.value}>\r\n <span className=\"flex items-center gap-2\">\r\n <span className=\"text-base\">{option.flag}</span>\r\n <span>{option.label}</span>\r\n </span>\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n );\r\n}\r\n\r\nexport default LanguageSwitcher;\r\n","// ========================================\r\n// Remote Notification Types (Frontend)\r\n// ========================================\r\n// Type definitions for remote notification system UI\r\n// Mirrors backend types with UI-specific additions\r\n\r\n/**\r\n * Supported notification platforms\r\n */\r\nexport type NotificationPlatform = 'discord' | 'telegram' | 'feishu' | 'dingtalk' | 'wecom' | 'email' | 'webhook';\r\n\r\n/**\r\n * Event types that can trigger notifications\r\n */\r\nexport type NotificationEventType =\r\n | 'ask-user-question'\r\n | 'session-start'\r\n | 'session-end'\r\n | 'task-completed'\r\n | 'task-failed';\r\n\r\n/**\r\n * Discord platform configuration\r\n */\r\nexport interface DiscordConfig {\r\n enabled: boolean;\r\n webhookUrl: string;\r\n username?: string;\r\n avatarUrl?: string;\r\n}\r\n\r\n/**\r\n * Telegram platform configuration\r\n */\r\nexport interface TelegramConfig {\r\n enabled: boolean;\r\n botToken: string;\r\n chatId: string;\r\n parseMode?: 'HTML' | 'Markdown' | 'MarkdownV2';\r\n}\r\n\r\n/**\r\n * Feishu (Lark) platform configuration\r\n */\r\nexport interface FeishuConfig {\r\n enabled: boolean;\r\n webhookUrl: string;\r\n useCard?: boolean;\r\n title?: string;\r\n}\r\n\r\n/**\r\n * DingTalk platform configuration\r\n */\r\nexport interface DingTalkConfig {\r\n enabled: boolean;\r\n webhookUrl: string;\r\n keywords?: string[];\r\n}\r\n\r\n/**\r\n * WeCom (WeChat Work) platform configuration\r\n */\r\nexport interface WeComConfig {\r\n enabled: boolean;\r\n webhookUrl: string;\r\n mentionedList?: string[];\r\n}\r\n\r\n/**\r\n * Email SMTP platform configuration\r\n */\r\nexport interface EmailConfig {\r\n enabled: boolean;\r\n host: string;\r\n port: number;\r\n secure?: boolean;\r\n username: string;\r\n password: string;\r\n from: string;\r\n to: string[];\r\n}\r\n\r\n/**\r\n * Generic Webhook platform configuration\r\n */\r\nexport interface WebhookConfig {\r\n enabled: boolean;\r\n url: string;\r\n method: 'POST' | 'PUT';\r\n headers?: Record<string, string>;\r\n timeout?: number;\r\n}\r\n\r\n/**\r\n * Event configuration\r\n */\r\nexport interface EventConfig {\r\n event: NotificationEventType;\r\n platforms: NotificationPlatform[];\r\n enabled: boolean;\r\n}\r\n\r\n/**\r\n * Full remote notification configuration\r\n */\r\nexport interface RemoteNotificationConfig {\r\n enabled: boolean;\r\n platforms: {\r\n discord?: DiscordConfig;\r\n telegram?: TelegramConfig;\r\n feishu?: FeishuConfig;\r\n dingtalk?: DingTalkConfig;\r\n wecom?: WeComConfig;\r\n email?: EmailConfig;\r\n webhook?: WebhookConfig;\r\n };\r\n events: EventConfig[];\r\n timeout: number;\r\n}\r\n\r\n/**\r\n * Test notification request\r\n */\r\nexport interface TestNotificationRequest {\r\n platform: NotificationPlatform;\r\n config: DiscordConfig | TelegramConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig | WebhookConfig;\r\n}\r\n\r\n/**\r\n * Test notification result\r\n */\r\nexport interface TestNotificationResult {\r\n success: boolean;\r\n error?: string;\r\n responseTime?: number;\r\n}\r\n\r\n/**\r\n * Platform display info\r\n */\r\nexport interface PlatformInfo {\r\n id: NotificationPlatform;\r\n name: string;\r\n icon: string;\r\n description: string;\r\n requiredFields: string[];\r\n}\r\n\r\n/**\r\n * Event display info\r\n */\r\nexport interface EventInfo {\r\n id: NotificationEventType;\r\n name: string;\r\n description: string;\r\n icon: string;\r\n}\r\n\r\n/**\r\n * Predefined platform information\r\n */\r\nexport const PLATFORM_INFO: Record<NotificationPlatform, PlatformInfo> = {\r\n discord: {\r\n id: 'discord',\r\n name: 'Discord',\r\n icon: 'message-circle',\r\n description: 'Send notifications to Discord channels via webhook',\r\n requiredFields: ['webhookUrl'],\r\n },\r\n telegram: {\r\n id: 'telegram',\r\n name: 'Telegram',\r\n icon: 'send',\r\n description: 'Send notifications to Telegram chats via bot',\r\n requiredFields: ['botToken', 'chatId'],\r\n },\r\n feishu: {\r\n id: 'feishu',\r\n name: 'Feishu',\r\n icon: 'message-square',\r\n description: 'Send notifications to Feishu (Lark) via webhook with rich card support',\r\n requiredFields: ['webhookUrl'],\r\n },\r\n dingtalk: {\r\n id: 'dingtalk',\r\n name: 'DingTalk',\r\n icon: 'bell',\r\n description: 'Send notifications to DingTalk via webhook',\r\n requiredFields: ['webhookUrl'],\r\n },\r\n wecom: {\r\n id: 'wecom',\r\n name: 'WeCom',\r\n icon: 'users',\r\n description: 'Send notifications to WeCom (WeChat Work) via webhook',\r\n requiredFields: ['webhookUrl'],\r\n },\r\n email: {\r\n id: 'email',\r\n name: 'Email',\r\n icon: 'mail',\r\n description: 'Send notifications via SMTP email',\r\n requiredFields: ['host', 'username', 'password', 'from', 'to'],\r\n },\r\n webhook: {\r\n id: 'webhook',\r\n name: 'Custom Webhook',\r\n icon: 'link',\r\n description: 'Send notifications to a custom HTTP endpoint',\r\n requiredFields: ['url'],\r\n },\r\n};\r\n\r\n/**\r\n * Predefined event information\r\n */\r\nexport const EVENT_INFO: Record<NotificationEventType, EventInfo> = {\r\n 'ask-user-question': {\r\n id: 'ask-user-question',\r\n name: 'Ask User Question',\r\n description: 'Notification when Claude asks a question via AskUserQuestion',\r\n icon: 'help-circle',\r\n },\r\n 'session-start': {\r\n id: 'session-start',\r\n name: 'Session Start',\r\n description: 'Notification when a CLI session starts',\r\n icon: 'play',\r\n },\r\n 'session-end': {\r\n id: 'session-end',\r\n name: 'Session End',\r\n description: 'Notification when a CLI session ends',\r\n icon: 'square',\r\n },\r\n 'task-completed': {\r\n id: 'task-completed',\r\n name: 'Task Completed',\r\n description: 'Notification when a task completes successfully',\r\n icon: 'check-circle',\r\n },\r\n 'task-failed': {\r\n id: 'task-failed',\r\n name: 'Task Failed',\r\n description: 'Notification when a task fails',\r\n icon: 'alert-circle',\r\n },\r\n};\r\n\r\n/**\r\n * Default configuration for UI initialization\r\n */\r\nexport function getDefaultConfig(): RemoteNotificationConfig {\r\n return {\r\n enabled: false,\r\n platforms: {},\r\n events: [\r\n { event: 'ask-user-question', platforms: ['discord', 'telegram'], enabled: true },\r\n { event: 'session-start', platforms: [], enabled: false },\r\n { event: 'session-end', platforms: [], enabled: false },\r\n { event: 'task-completed', platforms: [], enabled: false },\r\n { event: 'task-failed', platforms: ['discord', 'telegram'], enabled: true },\r\n ],\r\n timeout: 10000,\r\n };\r\n}\r\n","// ========================================\r\n// Platform Configuration Cards\r\n// ========================================\r\n// Individual configuration cards for each notification platform\r\n\r\nimport { useState } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport {\r\n MessageCircle,\r\n Send,\r\n Link,\r\n Check,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n TestTube,\r\n Eye,\r\n EyeOff,\r\n MessageSquare,\r\n Bell,\r\n Users,\r\n Mail,\r\n} from 'lucide-react';\r\nimport { Card } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { cn } from '@/lib/utils';\r\nimport type {\r\n RemoteNotificationConfig,\r\n NotificationPlatform,\r\n DiscordConfig,\r\n TelegramConfig,\r\n WebhookConfig,\r\n FeishuConfig,\r\n DingTalkConfig,\r\n WeComConfig,\r\n EmailConfig,\r\n} from '@/types/remote-notification';\r\nimport { PLATFORM_INFO } from '@/types/remote-notification';\r\n\r\ninterface PlatformConfigCardsProps {\r\n config: RemoteNotificationConfig;\r\n expandedPlatform: NotificationPlatform | null;\r\n testing: NotificationPlatform | null;\r\n onToggleExpand: (platform: NotificationPlatform | null) => void;\r\n onUpdateConfig: (\r\n platform: NotificationPlatform,\r\n updates: Partial<DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig>\r\n ) => void;\r\n onTest: (\r\n platform: NotificationPlatform,\r\n config: DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig\r\n ) => void;\r\n onSave: () => void;\r\n saving: boolean;\r\n}\r\n\r\nexport function PlatformConfigCards({\r\n config,\r\n expandedPlatform,\r\n testing,\r\n onToggleExpand,\r\n onUpdateConfig,\r\n onTest,\r\n onSave,\r\n saving,\r\n}: PlatformConfigCardsProps) {\r\n const { formatMessage } = useIntl();\r\n\r\n const platforms: NotificationPlatform[] = ['discord', 'telegram', 'feishu', 'dingtalk', 'wecom', 'email', 'webhook'];\r\n\r\n const getPlatformIcon = (platform: NotificationPlatform) => {\r\n switch (platform) {\r\n case 'discord':\r\n return <MessageCircle className=\"w-4 h-4\" />;\r\n case 'telegram':\r\n return <Send className=\"w-4 h-4\" />;\r\n case 'feishu':\r\n return <MessageSquare className=\"w-4 h-4\" />;\r\n case 'dingtalk':\r\n return <Bell className=\"w-4 h-4\" />;\r\n case 'wecom':\r\n return <Users className=\"w-4 h-4\" />;\r\n case 'email':\r\n return <Mail className=\"w-4 h-4\" />;\r\n case 'webhook':\r\n return <Link className=\"w-4 h-4\" />;\r\n }\r\n };\r\n\r\n const getPlatformConfig = (\r\n platform: NotificationPlatform\r\n ): DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig => {\r\n switch (platform) {\r\n case 'discord':\r\n return config.platforms.discord || { enabled: false, webhookUrl: '' };\r\n case 'telegram':\r\n return config.platforms.telegram || { enabled: false, botToken: '', chatId: '' };\r\n case 'feishu':\r\n return config.platforms.feishu || { enabled: false, webhookUrl: '' };\r\n case 'dingtalk':\r\n return config.platforms.dingtalk || { enabled: false, webhookUrl: '' };\r\n case 'wecom':\r\n return config.platforms.wecom || { enabled: false, webhookUrl: '' };\r\n case 'email':\r\n return config.platforms.email || { enabled: false, host: '', port: 587, username: '', password: '', from: '', to: [] };\r\n case 'webhook':\r\n return config.platforms.webhook || { enabled: false, url: '', method: 'POST' };\r\n }\r\n };\r\n\r\n const isConfigured = (platform: NotificationPlatform): boolean => {\r\n const platformConfig = getPlatformConfig(platform);\r\n switch (platform) {\r\n case 'discord':\r\n return !!(platformConfig as DiscordConfig).webhookUrl;\r\n case 'telegram':\r\n return !!(platformConfig as TelegramConfig).botToken && !!(platformConfig as TelegramConfig).chatId;\r\n case 'feishu':\r\n return !!(platformConfig as FeishuConfig).webhookUrl;\r\n case 'dingtalk':\r\n return !!(platformConfig as DingTalkConfig).webhookUrl;\r\n case 'wecom':\r\n return !!(platformConfig as WeComConfig).webhookUrl;\r\n case 'email':\r\n const emailConfig = platformConfig as EmailConfig;\r\n return !!(emailConfig.host && emailConfig.username && emailConfig.password && emailConfig.from && emailConfig.to?.length > 0);\r\n case 'webhook':\r\n return !!(platformConfig as WebhookConfig).url;\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"grid gap-3\">\r\n {platforms.map((platform) => {\r\n const info = PLATFORM_INFO[platform];\r\n const platformConfig = getPlatformConfig(platform);\r\n const configured = isConfigured(platform);\r\n const expanded = expandedPlatform === platform;\r\n\r\n return (\r\n <Card key={platform} className=\"overflow-hidden\">\r\n {/* Header */}\r\n <div\r\n className=\"p-4 cursor-pointer hover:bg-muted/50 transition-colors\"\r\n onClick={() => onToggleExpand(expanded ? null : platform)}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className={cn(\r\n 'p-2 rounded-lg',\r\n platformConfig.enabled && configured\r\n ? 'bg-primary/10 text-primary'\r\n : 'bg-muted text-muted-foreground'\r\n )}>\r\n {getPlatformIcon(platform)}\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium\">{info.name}</span>\r\n {configured && (\r\n <Badge variant=\"outline\" className=\"text-xs text-green-600 border-green-500/30\">\r\n <Check className=\"w-3 h-3 mr-1\" />\r\n {formatMessage({ id: 'settings.remoteNotifications.configured' })}\r\n </Badge>\r\n )}\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-0.5\">{info.description}</p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant={platformConfig.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onUpdateConfig(platform, { enabled: !platformConfig.enabled });\r\n }}\r\n >\r\n {platformConfig.enabled ? (\r\n <Check className=\"w-3.5 h-3.5\" />\r\n ) : (\r\n <X className=\"w-3.5 h-3.5\" />\r\n )}\r\n </Button>\r\n {expanded ? (\r\n <ChevronUp className=\"w-4 h-4 text-muted-foreground\" />\r\n ) : (\r\n <ChevronDown className=\"w-4 h-4 text-muted-foreground\" />\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Expanded Content */}\r\n {expanded && (\r\n <div className=\"border-t border-border p-4 space-y-4 bg-muted/30\">\r\n {platform === 'discord' && (\r\n <DiscordConfigForm\r\n config={platformConfig as DiscordConfig}\r\n onUpdate={(updates) => onUpdateConfig('discord', updates)}\r\n />\r\n )}\r\n {platform === 'telegram' && (\r\n <TelegramConfigForm\r\n config={platformConfig as TelegramConfig}\r\n onUpdate={(updates) => onUpdateConfig('telegram', updates)}\r\n />\r\n )}\r\n {platform === 'feishu' && (\r\n <FeishuConfigForm\r\n config={platformConfig as FeishuConfig}\r\n onUpdate={(updates) => onUpdateConfig('feishu', updates)}\r\n />\r\n )}\r\n {platform === 'dingtalk' && (\r\n <DingTalkConfigForm\r\n config={platformConfig as DingTalkConfig}\r\n onUpdate={(updates) => onUpdateConfig('dingtalk', updates)}\r\n />\r\n )}\r\n {platform === 'wecom' && (\r\n <WeComConfigForm\r\n config={platformConfig as WeComConfig}\r\n onUpdate={(updates) => onUpdateConfig('wecom', updates)}\r\n />\r\n )}\r\n {platform === 'email' && (\r\n <EmailConfigForm\r\n config={platformConfig as EmailConfig}\r\n onUpdate={(updates) => onUpdateConfig('email', updates)}\r\n />\r\n )}\r\n {platform === 'webhook' && (\r\n <WebhookConfigForm\r\n config={platformConfig as WebhookConfig}\r\n onUpdate={(updates) => onUpdateConfig('webhook', updates)}\r\n />\r\n )}\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center gap-2 pt-2\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => onTest(platform, platformConfig)}\r\n disabled={testing === platform || !configured}\r\n >\r\n <TestTube className={cn('w-3.5 h-3.5 mr-1', testing === platform && 'animate-pulse')} />\r\n {formatMessage({ id: 'settings.remoteNotifications.testConnection' })}\r\n </Button>\r\n <Button\r\n variant=\"default\"\r\n size=\"sm\"\r\n onClick={onSave}\r\n disabled={saving}\r\n >\r\n {formatMessage({ id: 'settings.remoteNotifications.save' })}\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n </Card>\r\n );\r\n })}\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Discord Config Form ==========\r\n\r\nfunction DiscordConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: DiscordConfig;\r\n onUpdate: (updates: Partial<DiscordConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showUrl, setShowUrl] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.discord.webhookUrl' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showUrl ? 'text' : 'password'}\r\n value={config.webhookUrl || ''}\r\n onChange={(e) => onUpdate({ webhookUrl: e.target.value })}\r\n placeholder=\"https://discord.com/api/webhooks/...\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowUrl(!showUrl)}\r\n >\r\n {showUrl ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.discord.webhookUrlHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.discord.username' })}\r\n </label>\r\n <Input\r\n value={config.username || ''}\r\n onChange={(e) => onUpdate({ username: e.target.value })}\r\n placeholder=\"CCW Notification\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Telegram Config Form ==========\r\n\r\nfunction TelegramConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: TelegramConfig;\r\n onUpdate: (updates: Partial<TelegramConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showToken, setShowToken] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.telegram.botToken' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showToken ? 'text' : 'password'}\r\n value={config.botToken || ''}\r\n onChange={(e) => onUpdate({ botToken: e.target.value })}\r\n placeholder=\"1234567890:ABCdefGHIjklMNOpqrsTUVwxyz\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowToken(!showToken)}\r\n >\r\n {showToken ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.telegram.botTokenHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.telegram.chatId' })}\r\n </label>\r\n <Input\r\n value={config.chatId || ''}\r\n onChange={(e) => onUpdate({ chatId: e.target.value })}\r\n placeholder=\"-1001234567890\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.telegram.chatIdHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Webhook Config Form ==========\r\n\r\nfunction WebhookConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: WebhookConfig;\r\n onUpdate: (updates: Partial<WebhookConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.webhook.url' })}\r\n </label>\r\n <Input\r\n value={config.url || ''}\r\n onChange={(e) => onUpdate({ url: e.target.value })}\r\n placeholder=\"https://your-server.com/webhook\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.webhook.method' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Button\r\n variant={config.method === 'POST' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => onUpdate({ method: 'POST' })}\r\n >\r\n POST\r\n </Button>\r\n <Button\r\n variant={config.method === 'PUT' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => onUpdate({ method: 'PUT' })}\r\n >\r\n PUT\r\n </Button>\r\n </div>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.webhook.headers' })}\r\n </label>\r\n <Input\r\n value={config.headers ? JSON.stringify(config.headers) : ''}\r\n onChange={(e) => {\r\n try {\r\n const headers = e.target.value ? JSON.parse(e.target.value) : undefined;\r\n onUpdate({ headers });\r\n } catch {\r\n // Invalid JSON, ignore\r\n }\r\n }}\r\n placeholder='{\"Authorization\": \"Bearer token\"}'\r\n className=\"mt-1 font-mono text-xs\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.webhook.headersHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Feishu Config Form ==========\r\n\r\nfunction FeishuConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: FeishuConfig;\r\n onUpdate: (updates: Partial<FeishuConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showUrl, setShowUrl] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.webhookUrl' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showUrl ? 'text' : 'password'}\r\n value={config.webhookUrl || ''}\r\n onChange={(e) => onUpdate({ webhookUrl: e.target.value })}\r\n placeholder=\"https://open.feishu.cn/open-apis/bot/v2/hook/...\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowUrl(!showUrl)}\r\n >\r\n {showUrl ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.webhookUrlHint' })}\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <input\r\n type=\"checkbox\"\r\n id=\"feishu-useCard\"\r\n checked={config.useCard || false}\r\n onChange={(e) => onUpdate({ useCard: e.target.checked })}\r\n className=\"rounded border-border\"\r\n />\r\n <label htmlFor=\"feishu-useCard\" className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.useCard' })}\r\n </label>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground -mt-2\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.useCardHint' })}\r\n </p>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.feishu.title' })}\r\n </label>\r\n <Input\r\n value={config.title || ''}\r\n onChange={(e) => onUpdate({ title: e.target.value })}\r\n placeholder=\"CCW Notification\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== DingTalk Config Form ==========\r\n\r\nfunction DingTalkConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: DingTalkConfig;\r\n onUpdate: (updates: Partial<DingTalkConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showUrl, setShowUrl] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.dingtalk.webhookUrl' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showUrl ? 'text' : 'password'}\r\n value={config.webhookUrl || ''}\r\n onChange={(e) => onUpdate({ webhookUrl: e.target.value })}\r\n placeholder=\"https://oapi.dingtalk.com/robot/send?access_token=...\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowUrl(!showUrl)}\r\n >\r\n {showUrl ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.dingtalk.webhookUrlHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.dingtalk.keywords' })}\r\n </label>\r\n <Input\r\n value={config.keywords?.join(', ') || ''}\r\n onChange={(e) => onUpdate({ keywords: e.target.value.split(',').map(k => k.trim()).filter(Boolean) })}\r\n placeholder=\"keyword1, keyword2\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.dingtalk.keywordsHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== WeCom Config Form ==========\r\n\r\nfunction WeComConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: WeComConfig;\r\n onUpdate: (updates: Partial<WeComConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showUrl, setShowUrl] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.wecom.webhookUrl' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showUrl ? 'text' : 'password'}\r\n value={config.webhookUrl || ''}\r\n onChange={(e) => onUpdate({ webhookUrl: e.target.value })}\r\n placeholder=\"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowUrl(!showUrl)}\r\n >\r\n {showUrl ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.wecom.webhookUrlHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.wecom.mentionedList' })}\r\n </label>\r\n <Input\r\n value={config.mentionedList?.join(', ') || ''}\r\n onChange={(e) => onUpdate({ mentionedList: e.target.value.split(',').map(m => m.trim()).filter(Boolean) })}\r\n placeholder=\"userid1, userid2, @all\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.wecom.mentionedListHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Email Config Form ==========\r\n\r\nfunction EmailConfigForm({\r\n config,\r\n onUpdate,\r\n}: {\r\n config: EmailConfig;\r\n onUpdate: (updates: Partial<EmailConfig>) => void;\r\n}) {\r\n const { formatMessage } = useIntl();\r\n const [showPassword, setShowPassword] = useState(false);\r\n\r\n return (\r\n <div className=\"space-y-3\">\r\n <div className=\"grid grid-cols-2 gap-3\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.host' })}\r\n </label>\r\n <Input\r\n value={config.host || ''}\r\n onChange={(e) => onUpdate({ host: e.target.value })}\r\n placeholder=\"smtp.gmail.com\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.hostHint' })}\r\n </p>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.port' })}\r\n </label>\r\n <Input\r\n type=\"number\"\r\n value={config.port || 587}\r\n onChange={(e) => onUpdate({ port: parseInt(e.target.value, 10) || 587 })}\r\n placeholder=\"587\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <input\r\n type=\"checkbox\"\r\n id=\"email-secure\"\r\n checked={config.secure || false}\r\n onChange={(e) => onUpdate({ secure: e.target.checked })}\r\n className=\"rounded border-border\"\r\n />\r\n <label htmlFor=\"email-secure\" className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.secure' })}\r\n </label>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.username' })}\r\n </label>\r\n <Input\r\n value={config.username || ''}\r\n onChange={(e) => onUpdate({ username: e.target.value })}\r\n placeholder=\"your-email@gmail.com\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.password' })}\r\n </label>\r\n <div className=\"flex gap-2 mt-1\">\r\n <Input\r\n type={showPassword ? 'text' : 'password'}\r\n value={config.password || ''}\r\n onChange={(e) => onUpdate({ password: e.target.value })}\r\n placeholder=\"********\"\r\n className=\"flex-1\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0\"\r\n onClick={() => setShowPassword(!showPassword)}\r\n >\r\n {showPassword ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </Button>\r\n </div>\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.from' })}\r\n </label>\r\n <Input\r\n value={config.from || ''}\r\n onChange={(e) => onUpdate({ from: e.target.value })}\r\n placeholder=\"noreply@example.com\"\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.to' })}\r\n </label>\r\n <Input\r\n value={config.to?.join(', ') || ''}\r\n onChange={(e) => onUpdate({ to: e.target.value.split(',').map(t => t.trim()).filter(Boolean) })}\r\n placeholder=\"user1@example.com, user2@example.com\"\r\n className=\"mt-1\"\r\n />\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.remoteNotifications.email.toHint' })}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default PlatformConfigCards;\r\n","// ========================================\r\n// Remote Notification Settings Section\r\n// ========================================\r\n// Configuration UI for remote notification platforms\r\n\r\nimport { useState, useEffect, useCallback } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport {\r\n Bell,\r\n BellOff,\r\n RefreshCw,\r\n Check,\r\n X,\r\n Save,\r\n ChevronDown,\r\n ChevronUp,\r\n Plus,\r\n} from 'lucide-react';\r\nimport { Card } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { cn } from '@/lib/utils';\r\nimport { toast } from 'sonner';\r\nimport type {\r\n RemoteNotificationConfig,\r\n NotificationPlatform,\r\n EventConfig,\r\n DiscordConfig,\r\n TelegramConfig,\r\n WebhookConfig,\r\n FeishuConfig,\r\n DingTalkConfig,\r\n WeComConfig,\r\n EmailConfig,\r\n} from '@/types/remote-notification';\r\nimport { PLATFORM_INFO, EVENT_INFO, getDefaultConfig } from '@/types/remote-notification';\r\nimport { PlatformConfigCards } from './PlatformConfigCards';\r\n\r\ninterface RemoteNotificationSectionProps {\r\n className?: string;\r\n}\r\n\r\nexport function RemoteNotificationSection({ className }: RemoteNotificationSectionProps) {\r\n const { formatMessage } = useIntl();\r\n const [config, setConfig] = useState<RemoteNotificationConfig | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [testing, setTesting] = useState<NotificationPlatform | null>(null);\r\n const [expandedPlatform, setExpandedPlatform] = useState<NotificationPlatform | null>(null);\r\n const [expandedEvent, setExpandedEvent] = useState<number | null>(null);\r\n\r\n // Load configuration\r\n const loadConfig = useCallback(async () => {\r\n setLoading(true);\r\n try {\r\n const response = await fetch('/api/notifications/remote/config');\r\n if (response.ok) {\r\n const data = await response.json();\r\n setConfig(data);\r\n } else {\r\n // Use default config if not found\r\n setConfig(getDefaultConfig());\r\n }\r\n } catch (error) {\r\n console.error('Failed to load remote notification config:', error);\r\n setConfig(getDefaultConfig());\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n loadConfig();\r\n }, [loadConfig]);\r\n\r\n // Save configuration\r\n const saveConfig = useCallback(async (newConfig: RemoteNotificationConfig) => {\r\n setSaving(true);\r\n try {\r\n const response = await fetch('/api/notifications/remote/config', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(newConfig),\r\n });\r\n\r\n if (response.ok) {\r\n const data = await response.json();\r\n setConfig(data.config);\r\n toast.success(formatMessage({ id: 'settings.remoteNotifications.saved' }));\r\n } else {\r\n throw new Error(`HTTP ${response.status}`);\r\n }\r\n } catch (error) {\r\n toast.error(formatMessage({ id: 'settings.remoteNotifications.saveError' }));\r\n } finally {\r\n setSaving(false);\r\n }\r\n }, [formatMessage]);\r\n\r\n // Test platform\r\n const testPlatform = useCallback(async (\r\n platform: NotificationPlatform,\r\n platformConfig: DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig\r\n ) => {\r\n setTesting(platform);\r\n try {\r\n const response = await fetch('/api/notifications/remote/test', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ platform, config: platformConfig }),\r\n });\r\n\r\n const result = await response.json();\r\n\r\n if (result.success) {\r\n toast.success(\r\n formatMessage({ id: 'settings.remoteNotifications.testSuccess' }),\r\n { description: `${result.responseTime}ms` }\r\n );\r\n } else {\r\n toast.error(\r\n formatMessage({ id: 'settings.remoteNotifications.testFailed' }),\r\n { description: result.error }\r\n );\r\n }\r\n } catch (error) {\r\n toast.error(formatMessage({ id: 'settings.remoteNotifications.testError' }));\r\n } finally {\r\n setTesting(null);\r\n }\r\n }, [formatMessage]);\r\n\r\n // Toggle master switch\r\n const toggleEnabled = () => {\r\n if (!config) return;\r\n saveConfig({ ...config, enabled: !config.enabled });\r\n };\r\n\r\n // Update platform config\r\n const updatePlatformConfig = (\r\n platform: NotificationPlatform,\r\n updates: Partial<DiscordConfig | TelegramConfig | WebhookConfig | FeishuConfig | DingTalkConfig | WeComConfig | EmailConfig>\r\n ) => {\r\n if (!config) return;\r\n const newConfig = {\r\n ...config,\r\n platforms: {\r\n ...config.platforms,\r\n [platform]: {\r\n ...config.platforms[platform as keyof typeof config.platforms],\r\n ...updates,\r\n },\r\n },\r\n };\r\n setConfig(newConfig);\r\n };\r\n\r\n // Update event config\r\n const updateEventConfig = (eventIndex: number, updates: Partial<EventConfig>) => {\r\n if (!config) return;\r\n const newEvents = [...config.events];\r\n newEvents[eventIndex] = { ...newEvents[eventIndex], ...updates };\r\n setConfig({ ...config, events: newEvents });\r\n };\r\n\r\n // Toggle platform for event\r\n const toggleEventPlatform = (eventIndex: number, platform: NotificationPlatform) => {\r\n if (!config) return;\r\n const eventConfig = config.events[eventIndex];\r\n const platforms = eventConfig.platforms.includes(platform)\r\n ? eventConfig.platforms.filter((p) => p !== platform)\r\n : [...eventConfig.platforms, platform];\r\n updateEventConfig(eventIndex, { platforms });\r\n };\r\n\r\n // All available platforms\r\n const allPlatforms: NotificationPlatform[] = ['discord', 'telegram', 'feishu', 'dingtalk', 'wecom', 'email', 'webhook'];\r\n\r\n // Reset to defaults\r\n const resetConfig = async () => {\r\n if (!confirm(formatMessage({ id: 'settings.remoteNotifications.resetConfirm' }))) {\r\n return;\r\n }\r\n try {\r\n const response = await fetch('/api/notifications/remote/reset', {\r\n method: 'POST',\r\n });\r\n if (response.ok) {\r\n const data = await response.json();\r\n setConfig(data.config);\r\n toast.success(formatMessage({ id: 'settings.remoteNotifications.resetSuccess' }));\r\n }\r\n } catch {\r\n toast.error(formatMessage({ id: 'settings.remoteNotifications.resetError' }));\r\n }\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <Card className={cn('p-6', className)}>\r\n <div className=\"flex items-center justify-center py-8\">\r\n <RefreshCw className=\"w-5 h-5 animate-spin text-muted-foreground\" />\r\n </div>\r\n </Card>\r\n );\r\n }\r\n\r\n if (!config) {\r\n return null;\r\n }\r\n\r\n return (\r\n <Card className={cn('p-6', className)}>\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between mb-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2\">\r\n {config.enabled ? (\r\n <Bell className=\"w-5 h-5 text-primary\" />\r\n ) : (\r\n <BellOff className=\"w-5 h-5 text-muted-foreground\" />\r\n )}\r\n {formatMessage({ id: 'settings.remoteNotifications.title' })}\r\n </h2>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={() => loadConfig()}\r\n disabled={loading}\r\n >\r\n <RefreshCw className={cn('w-3.5 h-3.5', loading && 'animate-spin')} />\r\n </Button>\r\n <Button\r\n variant={config.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={toggleEnabled}\r\n >\r\n {config.enabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.remoteNotifications.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.remoteNotifications.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Description */}\r\n <p className=\"text-sm text-muted-foreground mb-6\">\r\n {formatMessage({ id: 'settings.remoteNotifications.description' })}\r\n </p>\r\n\r\n {config.enabled && (\r\n <>\r\n {/* Platform Configuration */}\r\n <div className=\"space-y-4 mb-6\">\r\n <h3 className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.platforms' })}\r\n </h3>\r\n <PlatformConfigCards\r\n config={config}\r\n expandedPlatform={expandedPlatform}\r\n testing={testing}\r\n onToggleExpand={setExpandedPlatform}\r\n onUpdateConfig={updatePlatformConfig}\r\n onTest={testPlatform}\r\n onSave={() => saveConfig(config)}\r\n saving={saving}\r\n />\r\n </div>\r\n\r\n {/* Event Configuration */}\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.events' })}\r\n </h3>\r\n <div className=\"grid gap-3\">\r\n {config.events.map((eventConfig, index) => {\r\n const info = EVENT_INFO[eventConfig.event];\r\n const isExpanded = expandedEvent === index;\r\n return (\r\n <div\r\n key={eventConfig.event}\r\n className=\"rounded-lg border border-border bg-muted/30 overflow-hidden\"\r\n >\r\n {/* Event Header */}\r\n <div\r\n className=\"flex items-center justify-between p-3 cursor-pointer hover:bg-muted/50 transition-colors\"\r\n onClick={() => setExpandedEvent(isExpanded ? null : index)}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n <div className={cn(\r\n 'p-2 rounded-lg',\r\n eventConfig.enabled ? 'bg-primary/10 text-primary' : 'bg-muted text-muted-foreground'\r\n )}>\r\n <span className=\"text-sm\">{info.icon}</span>\r\n </div>\r\n <div>\r\n <p className=\"text-sm font-medium\">{info.name}</p>\r\n <p className=\"text-xs text-muted-foreground\">{info.description}</p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n {/* Platform badges */}\r\n <div className=\"flex gap-1 flex-wrap max-w-xs\">\r\n {eventConfig.platforms.slice(0, 3).map((platform) => (\r\n <Badge key={platform} variant=\"secondary\" className=\"text-xs\">\r\n {PLATFORM_INFO[platform].name}\r\n </Badge>\r\n ))}\r\n {eventConfig.platforms.length > 3 && (\r\n <Badge variant=\"secondary\" className=\"text-xs\">\r\n +{eventConfig.platforms.length - 3}\r\n </Badge>\r\n )}\r\n {eventConfig.platforms.length === 0 && (\r\n <Badge variant=\"outline\" className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.noPlatforms' })}\r\n </Badge>\r\n )}\r\n </div>\r\n {/* Toggle */}\r\n <Button\r\n variant={eventConfig.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n updateEventConfig(index, { enabled: !eventConfig.enabled });\r\n }}\r\n >\r\n {eventConfig.enabled ? (\r\n <Check className=\"w-3.5 h-3.5\" />\r\n ) : (\r\n <X className=\"w-3.5 h-3.5\" />\r\n )}\r\n </Button>\r\n {/* Expand icon */}\r\n {isExpanded ? (\r\n <ChevronUp className=\"w-4 h-4 text-muted-foreground\" />\r\n ) : (\r\n <ChevronDown className=\"w-4 h-4 text-muted-foreground\" />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Expanded Content - Platform Selection */}\r\n {isExpanded && (\r\n <div className=\"border-t border-border p-4 space-y-3 bg-muted/20\">\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.remoteNotifications.selectPlatforms' })}\r\n </p>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {allPlatforms.map((platform) => {\r\n const isSelected = eventConfig.platforms.includes(platform);\r\n const platformInfo = PLATFORM_INFO[platform];\r\n const platformConfig = config.platforms[platform];\r\n const isConfigured = platformConfig?.enabled;\r\n return (\r\n <Button\r\n key={platform}\r\n variant={isSelected ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className={cn(\r\n 'h-8',\r\n !isConfigured && !isSelected && 'opacity-50'\r\n )}\r\n onClick={() => toggleEventPlatform(index, platform)}\r\n >\r\n {isSelected && <Check className=\"w-3 h-3 mr-1\" />}\r\n {platformInfo.name}\r\n {!isConfigured && !isSelected && (\r\n <Plus className=\"w-3 h-3 ml-1 opacity-50\" />\r\n )}\r\n </Button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center justify-between mt-6 pt-4 border-t border-border\">\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n onClick={resetConfig}\r\n >\r\n {formatMessage({ id: 'settings.remoteNotifications.reset' })}\r\n </Button>\r\n <Button\r\n variant=\"default\"\r\n size=\"sm\"\r\n onClick={() => saveConfig(config)}\r\n disabled={saving}\r\n >\r\n <Save className=\"w-4 h-4 mr-1\" />\r\n {saving\r\n ? formatMessage({ id: 'settings.remoteNotifications.saving' })\r\n : formatMessage({ id: 'settings.remoteNotifications.save' })}\r\n </Button>\r\n </div>\r\n </>\r\n )}\r\n </Card>\r\n );\r\n}\r\n\r\nexport default RemoteNotificationSection;\r\n","// ========================================\n// A2UI Preferences Section\n// ========================================\n// Settings section for A2UI dialog style preferences\n\nimport { useIntl } from 'react-intl';\nimport { MessageSquare, Clock, Volume2, LayoutPanelLeft, Sparkles } from 'lucide-react';\nimport { Card } from '@/components/ui/Card';\nimport { Button } from '@/components/ui/Button';\nimport { Label } from '@/components/ui/Label';\nimport { cn } from '@/lib/utils';\nimport { useDialogStyleContext, type DialogStyle } from '@/contexts/DialogStyleContext';\n\n// ========== Style Option Button ==========\n\ninterface StyleOptionProps {\n value: DialogStyle;\n label: string;\n description: string;\n selected: boolean;\n onClick: () => void;\n}\n\nfunction StyleOption({ value, label, description, selected, onClick }: StyleOptionProps) {\n const icons: Record<DialogStyle, React.ReactNode> = {\n modal: (\n <div className=\"w-8 h-8 border-2 border-current rounded-lg flex items-center justify-center\">\n <div className=\"w-4 h-3 border border-current rounded-sm\" />\n </div>\n ),\n drawer: (\n <div className=\"w-8 h-8 border-2 border-current rounded-lg flex items-end justify-end p-0.5\">\n <div className=\"w-2 h-6 border border-current rounded-sm\" />\n </div>\n ),\n sheet: (\n <div className=\"w-8 h-8 border-2 border-current rounded-lg flex items-end justify-center p-0.5\">\n <div className=\"w-6 h-2 border border-current rounded-sm\" />\n </div>\n ),\n fullscreen: (\n <div className=\"w-8 h-8 border-2 border-current rounded-lg flex items-center justify-center\">\n <div className=\"w-5 h-4 border border-current rounded-sm\" />\n </div>\n ),\n };\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n 'flex flex-col items-center gap-2 p-3 rounded-lg border-2 transition-all',\n 'hover:bg-accent/50',\n selected\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border text-muted-foreground'\n )}\n >\n {icons[value]}\n <div className=\"text-center\">\n <div className={cn('text-sm font-medium', selected && 'text-primary')}>{label}</div>\n <div className=\"text-xs text-muted-foreground\">{description}</div>\n </div>\n </button>\n );\n}\n\n// ========== Duration Slider ==========\n\ninterface DurationSliderProps {\n value: number;\n onChange: (value: number) => void;\n disabled?: boolean;\n}\n\nfunction DurationSlider({ value, onChange, disabled }: DurationSliderProps) {\n const presets = [10, 20, 30, 45, 60, 90, 120];\n\n return (\n <div className=\"flex flex-wrap gap-2\">\n {presets.map((seconds) => (\n <Button\n key={seconds}\n type=\"button\"\n variant={value === seconds ? 'default' : 'outline'}\n size=\"sm\"\n disabled={disabled}\n onClick={() => onChange(seconds)}\n >\n {seconds}s\n </Button>\n ))}\n </div>\n );\n}\n\n// ========== Main Component ==========\n\nexport function A2UIPreferencesSection() {\n const { formatMessage } = useIntl();\n const { preferences, updatePreference, resetPreferences } = useDialogStyleContext();\n\n const styleOptions: Array<{ value: DialogStyle; label: string; description: string }> = [\n {\n value: 'modal',\n label: formatMessage({ id: 'settings.a2ui.styleModal', defaultMessage: 'Modal' }),\n description: formatMessage({ id: 'settings.a2ui.styleModalDesc', defaultMessage: 'Centered' }),\n },\n {\n value: 'drawer',\n label: formatMessage({ id: 'settings.a2ui.styleDrawer', defaultMessage: 'Drawer' }),\n description: formatMessage({ id: 'settings.a2ui.styleDrawerDesc', defaultMessage: 'Side panel' }),\n },\n {\n value: 'sheet',\n label: formatMessage({ id: 'settings.a2ui.styleSheet', defaultMessage: 'Sheet' }),\n description: formatMessage({ id: 'settings.a2ui.styleSheetDesc', defaultMessage: 'Bottom' }),\n },\n {\n value: 'fullscreen',\n label: formatMessage({ id: 'settings.a2ui.styleFullscreen', defaultMessage: 'Fullscreen' }),\n description: formatMessage({ id: 'settings.a2ui.styleFullscreenDesc', defaultMessage: 'Full screen' }),\n },\n ];\n\n return (\n <Card className=\"p-6\">\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\n <MessageSquare className=\"w-5 h-5\" />\n {formatMessage({ id: 'settings.sections.a2ui', defaultMessage: 'A2UI Preferences' })}\n </h2>\n\n <div className=\"space-y-6\">\n {/* Dialog Style Selection */}\n <div className=\"space-y-3\">\n <Label className=\"text-sm font-medium flex items-center gap-2\">\n <LayoutPanelLeft className=\"w-4 h-4\" />\n {formatMessage({ id: 'settings.a2ui.dialogStyle', defaultMessage: 'Dialog Style' })}\n </Label>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.dialogStyleDesc',\n defaultMessage: 'Choose how A2UI dialogs are displayed',\n })}\n </p>\n <div className=\"grid grid-cols-4 gap-2\">\n {styleOptions.map((option) => (\n <StyleOption\n key={option.value}\n value={option.value}\n label={option.label}\n description={option.description}\n selected={preferences.dialogStyle === option.value}\n onClick={() => updatePreference('dialogStyle', option.value)}\n />\n ))}\n </div>\n </div>\n\n {/* Smart Mode */}\n <div className=\"flex items-center justify-between py-2 border-t border-border\">\n <div className=\"flex items-center gap-2\">\n <Sparkles className=\"w-4 h-4 text-muted-foreground\" />\n <div>\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.smartMode', defaultMessage: 'Smart Mode' })}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.smartModeDesc',\n defaultMessage: 'Auto-select style based on question type',\n })}\n </p>\n </div>\n </div>\n <Button\n variant={preferences.smartModeEnabled ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => updatePreference('smartModeEnabled', !preferences.smartModeEnabled)}\n >\n {preferences.smartModeEnabled\n ? formatMessage({ id: 'common.enabled', defaultMessage: 'Enabled' })\n : formatMessage({ id: 'common.disabled', defaultMessage: 'Disabled' })}\n </Button>\n </div>\n\n {/* Auto Selection Duration */}\n <div className=\"space-y-3 py-2 border-t border-border\">\n <div className=\"flex items-center gap-2\">\n <Clock className=\"w-4 h-4 text-muted-foreground\" />\n <Label className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.autoSelectionDuration', defaultMessage: 'Auto-Selection Duration' })}\n </Label>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.autoSelectionDurationDesc',\n defaultMessage: 'Countdown before auto-selecting default option',\n })}\n </p>\n <DurationSlider\n value={preferences.autoSelectionDuration}\n onChange={(v) => updatePreference('autoSelectionDuration', v)}\n />\n </div>\n\n {/* Pause on Interaction */}\n <div className=\"flex items-center justify-between py-2 border-t border-border\">\n <div>\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.pauseOnInteraction', defaultMessage: 'Pause on Interaction' })}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.pauseOnInteractionDesc',\n defaultMessage: 'Pause countdown when you interact with the dialog',\n })}\n </p>\n </div>\n <Button\n variant={preferences.pauseOnInteraction ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => updatePreference('pauseOnInteraction', !preferences.pauseOnInteraction)}\n >\n {preferences.pauseOnInteraction\n ? formatMessage({ id: 'common.enabled', defaultMessage: 'Enabled' })\n : formatMessage({ id: 'common.disabled', defaultMessage: 'Disabled' })}\n </Button>\n </div>\n\n {/* Sound Notification */}\n <div className=\"flex items-center justify-between py-2 border-t border-border\">\n <div className=\"flex items-center gap-2\">\n <Volume2 className=\"w-4 h-4 text-muted-foreground\" />\n <div>\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.soundNotification', defaultMessage: 'Sound Notification' })}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.soundNotificationDesc',\n defaultMessage: 'Play sound before auto-submit (3 seconds before)',\n })}\n </p>\n </div>\n </div>\n <Button\n variant={preferences.autoSelectionSoundEnabled ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => updatePreference('autoSelectionSoundEnabled', !preferences.autoSelectionSoundEnabled)}\n >\n {preferences.autoSelectionSoundEnabled\n ? formatMessage({ id: 'common.enabled', defaultMessage: 'Enabled' })\n : formatMessage({ id: 'common.disabled', defaultMessage: 'Disabled' })}\n </Button>\n </div>\n\n {/* Show A2UI Button in Toolbar */}\n <div className=\"flex items-center justify-between py-2 border-t border-border\">\n <div>\n <p className=\"text-sm font-medium\">\n {formatMessage({ id: 'settings.a2ui.showToolbarButton', defaultMessage: 'Show Toolbar Button' })}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatMessage({\n id: 'settings.a2ui.showToolbarButtonDesc',\n defaultMessage: 'Show A2UI quick action button in the toolbar',\n })}\n </p>\n </div>\n <Button\n variant={preferences.showA2UIButtonInToolbar ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => updatePreference('showA2UIButtonInToolbar', !preferences.showA2UIButtonInToolbar)}\n >\n {preferences.showA2UIButtonInToolbar\n ? formatMessage({ id: 'common.enabled', defaultMessage: 'Enabled' })\n : formatMessage({ id: 'common.disabled', defaultMessage: 'Disabled' })}\n </Button>\n </div>\n\n {/* Reset Button */}\n <div className=\"flex justify-end pt-4 border-t border-border\">\n <Button variant=\"outline\" size=\"sm\" onClick={resetPreferences}>\n {formatMessage({ id: 'common.resetToDefaults', defaultMessage: 'Reset to Defaults' })}\n </Button>\n </div>\n </div>\n </Card>\n );\n}\n\nexport default A2UIPreferencesSection;\n","// ========================================\r\n// Settings Page\r\n// ========================================\r\n// Application settings and configuration with CLI tools management\r\n\r\nimport { useState, useCallback, useEffect, useRef } from 'react';\r\nimport { useIntl } from 'react-intl';\r\nimport {\r\n Settings,\r\n Moon,\r\n Bell,\r\n Cpu,\r\n RefreshCw,\r\n RotateCcw,\r\n Check,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n Languages,\r\n Plus,\r\n MessageSquareText,\r\n Monitor,\r\n Terminal,\r\n AlertTriangle,\r\n Package,\r\n Home,\r\n Folder,\r\n FolderOpen,\r\n Calendar,\r\n File,\r\n ArrowUpCircle,\r\n Save,\r\n Download,\r\n Upload,\r\n} from 'lucide-react';\r\nimport { Card } from '@/components/ui/Card';\r\nimport { Button } from '@/components/ui/Button';\r\nimport { Input } from '@/components/ui/Input';\r\nimport { Badge } from '@/components/ui/Badge';\r\nimport { ThemeSelector } from '@/components/shared/ThemeSelector';\r\nimport { useTheme } from '@/hooks';\r\nimport { toast } from 'sonner';\r\nimport { useConfigStore, selectCliTools, selectDefaultCliTool, selectUserPreferences } from '@/stores/configStore';\r\nimport type { CliToolConfig, UserPreferences } from '@/types/store';\r\nimport { cn } from '@/lib/utils';\r\nimport { LanguageSwitcher } from '@/components/layout/LanguageSwitcher';\r\nimport {\r\n useChineseResponseStatus,\r\n useToggleChineseResponse,\r\n useWindowsPlatformStatus,\r\n useToggleWindowsPlatform,\r\n useCodexCliEnhancementStatus,\r\n useToggleCodexCliEnhancement,\r\n useRefreshCodexCliEnhancement,\r\n useCcwInstallStatus,\r\n useCliToolStatus,\r\n useCcwInstallations,\r\n useUpgradeCcwInstallation,\r\n useExportSettings,\r\n useImportSettings,\r\n} from '@/hooks/useSystemSettings';\r\nimport type { ExportedSettings } from '@/lib/api';\r\nimport { RemoteNotificationSection } from '@/components/settings/RemoteNotificationSection';\r\nimport { A2UIPreferencesSection } from '@/components/settings/A2UIPreferencesSection';\r\n\r\n// ========== CSRF Token Helper ==========\r\nfunction getCsrfToken(): string | null {\r\n const match = document.cookie.match(/XSRF-TOKEN=([^;]+)/);\r\n return match ? decodeURIComponent(match[1]) : null;\r\n}\r\n\r\n// ========== File Path Input with Native File Picker ==========\r\n\r\nimport { useDebounce } from '@/hooks/useDebounce';\r\nimport { Loader2 } from 'lucide-react';\r\n\r\n// ...\r\n\r\ninterface FilePathInputProps {\r\n value: string;\r\n onChange: (value: string) => void;\r\n placeholder: string;\r\n}\r\n\r\nfunction FilePathInput({ value, onChange, placeholder }: FilePathInputProps) {\r\n const [isValidating, setIsValidating] = useState(false);\r\n const [pathError, setPathError] = useState<string | null>(null);\r\n const debouncedValue = useDebounce(value, 500);\r\n\r\n useEffect(() => {\r\n if (debouncedValue) {\r\n setIsValidating(true);\r\n setPathError(null);\r\n // Simulate async validation\r\n const timeoutId = setTimeout(() => {\r\n // Simple validation: check if path is not empty.\r\n // In a real scenario, this would check for path existence.\r\n if (debouncedValue.trim().length > 0) {\r\n setPathError(null);\r\n } else {\r\n setPathError('Path cannot be empty.');\r\n }\r\n setIsValidating(false);\r\n }, 1000);\r\n\r\n return () => clearTimeout(timeoutId);\r\n } else {\r\n setPathError(null);\r\n setIsValidating(false);\r\n }\r\n }, [debouncedValue]);\r\n\r\n const handleBrowse = async () => {\r\n const { selectFile } = await import('@/lib/nativeDialog');\r\n const initialDir = value ? value.replace(/[/\\\\][^/\\\\]*$/, '') : undefined;\r\n const result = await selectFile(initialDir);\r\n if (result.path && !result.cancelled && !result.error) {\r\n onChange(result.path);\r\n }\r\n };\r\n\r\n return (\r\n <div>\r\n <div className=\"flex gap-2 items-center\">\r\n <div className=\"relative flex-1\">\r\n <Input\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n placeholder={placeholder}\r\n className={cn(\r\n \"flex-1\",\r\n pathError && \"border-destructive\"\r\n )}\r\n />\r\n {isValidating && (\r\n <div className=\"absolute inset-y-0 right-0 flex items-center pr-3\">\r\n <Loader2 className=\"h-4 w-4 animate-spin text-muted-foreground\" />\r\n </div>\r\n )}\r\n </div>\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"shrink-0 h-9\"\r\n onClick={handleBrowse}\r\n title=\"Browse\"\r\n >\r\n <FolderOpen className=\"w-4 h-4\" />\r\n </Button>\r\n </div>\r\n {pathError && (\r\n <p className=\"text-xs text-destructive mt-1\">{pathError}</p>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// ========== Tool Config File Helpers ==========\r\n\r\n/** Tools that use .env file for environment variables */\r\nconst ENV_FILE_TOOLS = new Set(['gemini', 'qwen', 'opencode']);\r\n/** Tools that use --settings for Claude CLI settings file */\r\nconst SETTINGS_FILE_TOOLS = new Set(['claude']);\r\nfunction getConfigFileType(toolId: string): 'envFile' | 'settingsFile' | 'none' {\r\n if (ENV_FILE_TOOLS.has(toolId)) return 'envFile';\r\n if (SETTINGS_FILE_TOOLS.has(toolId)) return 'settingsFile';\r\n return 'none';\r\n}\r\n\r\n// ========== CLI Tool Card Component ==========\r\n\r\ninterface CliToolCardProps {\r\n toolId: string;\r\n config: CliToolConfig;\r\n isDefault: boolean;\r\n isExpanded: boolean;\r\n toolAvailable?: boolean;\r\n isSaving?: boolean;\r\n onToggleExpand: () => void;\r\n onToggleEnabled: () => void;\r\n onSetDefault: () => void;\r\n onUpdateModel: (field: 'primaryModel' | 'secondaryModel', value: string) => void;\r\n onUpdateTags: (tags: string[]) => void;\r\n onUpdateAvailableModels: (models: string[]) => void;\r\n onUpdateEnvFile: (envFile: string | undefined) => void;\r\n onUpdateSettingsFile: (settingsFile: string | undefined) => void;\r\n onUpdateEffort: (effort: string | undefined) => void;\r\n onSaveToBackend: () => void;\r\n}\r\n\r\nfunction CliToolCard({\r\n toolId,\r\n config,\r\n isDefault,\r\n isExpanded,\r\n toolAvailable,\r\n isSaving,\r\n onToggleExpand,\r\n onToggleEnabled,\r\n onSetDefault,\r\n onUpdateModel,\r\n onUpdateTags,\r\n onUpdateAvailableModels,\r\n onUpdateEnvFile,\r\n onUpdateSettingsFile,\r\n onUpdateEffort,\r\n onSaveToBackend,\r\n}: CliToolCardProps) {\r\n const { formatMessage } = useIntl();\r\n\r\n // Local state for tag and model input\r\n const [tagInput, setTagInput] = useState('');\r\n const [modelInput, setModelInput] = useState('');\r\n\r\n // Handler for adding tags\r\n const handleAddTag = () => {\r\n const newTag = tagInput.trim();\r\n if (newTag && !config.tags.includes(newTag)) {\r\n onUpdateTags([...config.tags, newTag]);\r\n setTagInput('');\r\n }\r\n };\r\n\r\n // Handler for removing tags\r\n const handleRemoveTag = (tagToRemove: string) => {\r\n onUpdateTags(config.tags.filter((t) => t !== tagToRemove));\r\n };\r\n\r\n // Handler for adding available models\r\n const handleAddModel = () => {\r\n const newModel = modelInput.trim();\r\n const currentModels = config.availableModels || [];\r\n if (newModel && !currentModels.includes(newModel)) {\r\n onUpdateAvailableModels([...currentModels, newModel]);\r\n setModelInput('');\r\n }\r\n };\r\n\r\n // Handler for removing available models\r\n const handleRemoveModel = (modelToRemove: string) => {\r\n const currentModels = config.availableModels || [];\r\n onUpdateAvailableModels(currentModels.filter((m) => m !== modelToRemove));\r\n };\r\n\r\n // Predefined tags\r\n const predefinedTags = ['分析', 'Debug', 'implementation', 'refactoring', 'testing'];\r\n\r\n const configFileType = getConfigFileType(toolId);\r\n\r\n return (\r\n <Card className={cn('overflow-hidden', !config.enabled && 'opacity-60')}>\r\n {/* Header */}\r\n <div\r\n className=\"p-4 cursor-pointer hover:bg-muted/50 transition-colors\"\r\n onClick={onToggleExpand}\r\n >\r\n <div className=\"flex items-center justify-between gap-2\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className={cn(\r\n 'p-2 rounded-lg',\r\n config.enabled ? 'bg-primary/10' : 'bg-muted'\r\n )}>\r\n <Cpu className={cn(\r\n 'w-5 h-5',\r\n config.enabled ? 'text-primary' : 'text-muted-foreground'\r\n )} />\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium text-foreground capitalize\">\r\n {toolId}\r\n </span>\r\n {isDefault && (\r\n <Badge variant=\"default\" className=\"text-xs\">{formatMessage({ id: 'settings.cliTools.default' })}</Badge>\r\n )}\r\n <Badge variant=\"outline\" className=\"text-xs\">{config.type}</Badge>\r\n {toolAvailable !== undefined && (\r\n <span className={cn(\r\n 'inline-block w-2 h-2 rounded-full',\r\n toolAvailable ? 'bg-green-500' : 'bg-red-400'\r\n )} title={toolAvailable ? 'Available' : 'Unavailable'} />\r\n )}\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-0.5\">\r\n {config.primaryModel}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant={config.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-8\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onToggleEnabled();\r\n }}\r\n >\r\n {config.enabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.cliTools.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.cliTools.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n {isExpanded ? (\r\n <ChevronUp className=\"w-5 h-5 text-muted-foreground\" />\r\n ) : (\r\n <ChevronDown className=\"w-5 h-5 text-muted-foreground\" />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Tags */}\r\n {config.tags && config.tags.length > 0 && (\r\n <div className=\"flex flex-wrap gap-1 mt-2\">\r\n {config.tags.map((tag) => (\r\n <Badge key={tag} variant=\"secondary\" className=\"text-xs\">\r\n {tag}\r\n </Badge>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Expanded Content */}\r\n {isExpanded && (\r\n <div className=\"border-t border-border p-4 space-y-4 bg-muted/30\">\r\n <div className=\"grid gap-4 md:grid-cols-2\">\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">{formatMessage({ id: 'settings.cliTools.primaryModel' })}</label>\r\n <Input\r\n value={config.primaryModel}\r\n onChange={(e) => onUpdateModel('primaryModel', e.target.value)}\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"text-sm font-medium text-foreground\">{formatMessage({ id: 'settings.cliTools.secondaryModel' })}</label>\r\n <Input\r\n value={config.secondaryModel}\r\n onChange={(e) => onUpdateModel('secondaryModel', e.target.value)}\r\n className=\"mt-1\"\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Tags Section */}\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.tags' })}\r\n </label>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.tagsDescription' })}\r\n </p>\r\n <div className=\"flex gap-2\">\r\n <div className=\"flex-1 flex flex-wrap gap-1.5 p-2 border border-input bg-background rounded-md min-h-[38px] focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2\">\r\n {config.tags.map((tag) => (\r\n <span\r\n key={tag}\r\n className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-primary/10 text-primary rounded text-xs h-6\"\r\n >\r\n {tag}\r\n <button\r\n type=\"button\"\r\n onClick={() => handleRemoveTag(tag)}\r\n className=\"hover:text-destructive transition-colors\"\r\n aria-label={formatMessage({ id: 'apiSettings.cliSettings.removeTag' })}\r\n >\r\n <X className=\"w-3 h-3\" />\r\n </button>\r\n </span>\r\n ))}\r\n <input\r\n type=\"text\"\r\n value={tagInput}\r\n onChange={(e) => setTagInput(e.target.value)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n handleAddTag();\r\n }\r\n }}\r\n placeholder={config.tags.length === 0 ? formatMessage({ id: 'apiSettings.cliSettings.tagInputPlaceholder' }) : ''}\r\n className=\"flex-1 min-w-[120px] bg-transparent border-0 outline-none text-sm placeholder:text-muted-foreground\"\r\n />\r\n </div>\r\n <Button\r\n type=\"button\"\r\n size=\"sm\"\r\n onClick={handleAddTag}\r\n variant=\"outline\"\r\n className=\"shrink-0\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n </Button>\r\n </div>\r\n {/* Predefined Tags */}\r\n <div className=\"flex flex-wrap gap-1\">\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.predefinedTags' })}:\r\n </span>\r\n {predefinedTags.map((predefinedTag) => (\r\n <button\r\n key={predefinedTag}\r\n type=\"button\"\r\n onClick={() => {\r\n if (!config.tags.includes(predefinedTag)) {\r\n onUpdateTags([...config.tags, predefinedTag]);\r\n }\r\n }}\r\n disabled={config.tags.includes(predefinedTag)}\r\n className=\"text-xs px-2 py-0.5 rounded border border-border hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {predefinedTag}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Available Models Section */}\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.availableModels' })}\r\n </label>\r\n <div className=\"flex gap-2\">\r\n <div className=\"flex-1 flex flex-wrap gap-1.5 p-2 border border-input bg-background rounded-md min-h-[38px] focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2\">\r\n {(config.availableModels || []).map((model) => (\r\n <span\r\n key={model}\r\n className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-primary/10 text-primary rounded text-xs h-6\"\r\n >\r\n {model}\r\n <button\r\n type=\"button\"\r\n onClick={() => handleRemoveModel(model)}\r\n className=\"hover:text-destructive transition-colors\"\r\n >\r\n <X className=\"w-3 h-3\" />\r\n </button>\r\n </span>\r\n ))}\r\n <input\r\n type=\"text\"\r\n value={modelInput}\r\n onChange={(e) => setModelInput(e.target.value)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n handleAddModel();\r\n }\r\n }}\r\n placeholder={(config.availableModels || []).length === 0 ? formatMessage({ id: 'apiSettings.cliSettings.availableModelsPlaceholder' }) : ''}\r\n className=\"flex-1 min-w-[120px] bg-transparent border-0 outline-none text-sm placeholder:text-muted-foreground\"\r\n />\r\n </div>\r\n <Button\r\n type=\"button\"\r\n size=\"sm\"\r\n onClick={handleAddModel}\r\n variant=\"outline\"\r\n className=\"shrink-0\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.availableModelsHint' })}\r\n </p>\r\n </div>\r\n\r\n {/* Env File - for gemini/qwen/opencode */}\r\n {configFileType === 'envFile' && (\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.cliTools.envFile' })}\r\n </label>\r\n <FilePathInput\r\n value={config.envFile || ''}\r\n onChange={(v) => onUpdateEnvFile(v || undefined)}\r\n placeholder={formatMessage({ id: 'settings.cliTools.envFilePlaceholder' })}\r\n />\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.cliTools.envFileHint' })}\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Settings File - for claude only */}\r\n {configFileType === 'settingsFile' && (\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.settingsFile' })}\r\n </label>\r\n <FilePathInput\r\n value={config.settingsFile || ''}\r\n onChange={(v) => onUpdateSettingsFile(v || undefined)}\r\n placeholder={formatMessage({ id: 'apiSettings.cliSettings.settingsFilePlaceholder' })}\r\n />\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'apiSettings.cliSettings.settingsFileHint' })}\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Effort Level - for claude only */}\r\n {configFileType === 'settingsFile' && (\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-foreground\">\r\n {formatMessage({ id: 'settings.cliTools.effort' })}\r\n </label>\r\n <div className=\"flex gap-2\">\r\n {(['low', 'medium', 'high'] as const).map((level) => {\r\n const effectiveEffort = config.effort || 'high';\r\n const labelId = `settings.cliTools.effort${level.charAt(0).toUpperCase() + level.slice(1)}` as const;\r\n return (\r\n <button\r\n key={level}\r\n type=\"button\"\r\n onClick={() => onUpdateEffort(level === 'high' && !config.effort ? undefined : level)}\r\n className={cn(\r\n 'px-3 py-1.5 rounded-md text-sm border transition-colors',\r\n effectiveEffort === level\r\n ? 'bg-primary text-primary-foreground border-primary'\r\n : 'border-border hover:bg-muted'\r\n )}\r\n >\r\n {formatMessage({ id: labelId })}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.cliTools.effortHint' })}\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center gap-2\">\r\n {!isDefault && config.enabled && (\r\n <Button variant=\"outline\" size=\"sm\" onClick={onSetDefault}>\r\n {formatMessage({ id: 'settings.cliTools.setDefault' })}\r\n </Button>\r\n )}\r\n <Button\r\n variant=\"default\"\r\n size=\"sm\"\r\n onClick={onSaveToBackend}\r\n disabled={isSaving}\r\n >\r\n <Save className=\"w-4 h-4 mr-1\" />\r\n {isSaving\r\n ? formatMessage({ id: 'settings.cliTools.saving' })\r\n : formatMessage({ id: 'settings.cliTools.saveToConfig' })}\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n </Card>\r\n );\r\n}\r\n\r\n// ========== Response Language Section ==========\r\n\r\nfunction ResponseLanguageSection() {\r\n const { formatMessage } = useIntl();\r\n const { data: chineseStatus, isLoading: chineseLoading } = useChineseResponseStatus();\r\n const { toggle: toggleChinese, isPending: chineseToggling } = useToggleChineseResponse();\r\n const { data: windowsStatus, isLoading: windowsLoading } = useWindowsPlatformStatus();\r\n const { toggle: toggleWindows, isPending: windowsToggling } = useToggleWindowsPlatform();\r\n const { data: cliEnhStatus, isLoading: cliEnhLoading } = useCodexCliEnhancementStatus();\r\n const { toggle: toggleCliEnh, isPending: cliEnhToggling } = useToggleCodexCliEnhancement();\r\n const { refresh: refreshCliEnh, isPending: refreshing } = useRefreshCodexCliEnhancement();\r\n const { exportSettings: doExport, isPending: exporting } = useExportSettings();\r\n const { importSettings: doImport, isPending: importing } = useImportSettings();\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n\r\n const handleExport = useCallback(async () => {\r\n try {\r\n const data = await doExport();\r\n const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement('a');\r\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);\r\n a.href = url;\r\n a.download = `ccw-settings-${timestamp}.json`;\r\n document.body.appendChild(a);\r\n a.click();\r\n document.body.removeChild(a);\r\n URL.revokeObjectURL(url);\r\n toast.success(formatMessage({ id: 'settings.responseLanguage.exportSuccess' }));\r\n } catch (error) {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.exportError' }));\r\n }\r\n }, [doExport, formatMessage]);\r\n\r\n const handleFileImport = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const file = e.target.files?.[0];\r\n if (!file) return;\r\n\r\n // Reset file input so the same file can be re-selected\r\n e.target.value = '';\r\n\r\n // Validate file type\r\n if (!file.name.endsWith('.json') && file.type !== 'application/json') {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importInvalidFile' }));\r\n return;\r\n }\r\n\r\n try {\r\n const text = await file.text();\r\n const data = JSON.parse(text) as ExportedSettings;\r\n\r\n // Validate basic structure\r\n if (!data.version || !data.endpoints) {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importInvalidStructure' }));\r\n return;\r\n }\r\n\r\n const result = await doImport(data);\r\n\r\n if (result.success) {\r\n toast.success(\r\n formatMessage(\r\n { id: 'settings.responseLanguage.importSuccess' },\r\n { imported: result.imported, skipped: result.skipped }\r\n )\r\n );\r\n } else {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importError' }));\r\n }\r\n } catch (error) {\r\n if (error instanceof SyntaxError) {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importInvalidJson' }));\r\n } else {\r\n toast.error(formatMessage({ id: 'settings.responseLanguage.importError' }));\r\n }\r\n }\r\n }, [doImport, formatMessage]);\r\n\r\n return (\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <MessageSquareText className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.sections.responseLanguage' })}\r\n </h2>\r\n <div className=\"grid gap-4 md:grid-cols-2\">\r\n {/* Chinese Response - Claude */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.responseLanguage.chineseClaude' })}</span>\r\n <Badge variant=\"default\" className=\"text-xs\">Claude</Badge>\r\n </div>\r\n <Button\r\n variant={chineseStatus?.claudeEnabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={chineseLoading || chineseToggling}\r\n onClick={() => toggleChinese(!chineseStatus?.claudeEnabled, 'claude')}\r\n >\r\n {chineseStatus?.claudeEnabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.chineseClaudeDesc' })}\r\n </p>\r\n </div>\r\n\r\n {/* Chinese Response - Codex */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.responseLanguage.chineseCodex' })}</span>\r\n <Badge variant=\"secondary\" className=\"text-xs\">Codex</Badge>\r\n </div>\r\n <Button\r\n variant={chineseStatus?.codexEnabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={chineseLoading || chineseToggling}\r\n onClick={() => toggleChinese(!chineseStatus?.codexEnabled, 'codex')}\r\n >\r\n {chineseStatus?.codexEnabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.chineseCodexDesc' })}\r\n </p>\r\n {chineseStatus?.codexNeedsMigration && (\r\n <p className=\"text-xs text-yellow-500\">\r\n <AlertTriangle className=\"w-3 h-3 inline mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.migrationWarning' })}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {/* Windows Platform */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <Monitor className=\"w-4 h-4 text-muted-foreground\" />\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.responseLanguage.windowsPlatform' })}</span>\r\n </div>\r\n <Button\r\n variant={windowsStatus?.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={windowsLoading || windowsToggling}\r\n onClick={() => toggleWindows(!windowsStatus?.enabled)}\r\n >\r\n {windowsStatus?.enabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.windowsPlatformDesc' })}\r\n </p>\r\n </div>\r\n\r\n {/* CLI Enhancement - Codex */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <Terminal className=\"w-4 h-4 text-muted-foreground\" />\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.responseLanguage.cliEnhancement' })}</span>\r\n <Badge variant=\"secondary\" className=\"text-xs\">Codex</Badge>\r\n </div>\r\n <div className=\"flex items-center gap-1\">\r\n {cliEnhStatus?.enabled && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className=\"h-7 w-7 p-0\"\r\n disabled={cliEnhLoading || refreshing}\r\n onClick={() => refreshCliEnh()}\r\n title={formatMessage({ id: 'settings.responseLanguage.refreshConfig' })}\r\n >\r\n <RefreshCw className={cn('w-3.5 h-3.5', refreshing && 'animate-spin')} />\r\n </Button>\r\n )}\r\n <Button\r\n variant={cliEnhStatus?.enabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={cliEnhLoading || cliEnhToggling}\r\n onClick={() => toggleCliEnh(!cliEnhStatus?.enabled)}\r\n >\r\n {cliEnhStatus?.enabled ? (\r\n <>\r\n <Check className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.enabled' })}\r\n </>\r\n ) : (\r\n <>\r\n <X className=\"w-4 h-4 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.disabled' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.cliEnhancementDesc' })}\r\n </p>\r\n {cliEnhStatus?.enabled && (\r\n <p className=\"text-xs text-muted-foreground/70\">\r\n {formatMessage({ id: 'settings.responseLanguage.cliEnhancementHint' })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Export/Import Actions */}\r\n <div className=\"mt-4 pt-4 border-t border-border\">\r\n <div className=\"flex items-center justify-between\">\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.responseLanguage.exportImportHint' })}\r\n </p>\r\n <div className=\"flex items-center gap-2\">\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept=\".json,application/json\"\r\n onChange={handleFileImport}\r\n className=\"hidden\"\r\n />\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={importing}\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n {importing ? (\r\n <>\r\n <div className=\"w-3.5 h-3.5 border-2 border-border border-t-accent rounded-full animate-spin mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.importing' })}\r\n </>\r\n ) : (\r\n <>\r\n <Upload className=\"w-3.5 h-3.5 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.import' })}\r\n </>\r\n )}\r\n </Button>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={exporting}\r\n onClick={handleExport}\r\n >\r\n {exporting ? (\r\n <>\r\n <div className=\"w-3.5 h-3.5 border-2 border-border border-t-accent rounded-full animate-spin mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.exporting' })}\r\n </>\r\n ) : (\r\n <>\r\n <Download className=\"w-3.5 h-3.5 mr-1\" />\r\n {formatMessage({ id: 'settings.responseLanguage.export' })}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n </div>\r\n </Card>\r\n );\r\n}\r\n\r\n// ========== Version Check Section ==========\r\n\r\ninterface VersionData {\r\n currentVersion: string;\r\n latestVersion: string;\r\n hasUpdate: boolean;\r\n packageName: string;\r\n updateCommand: string;\r\n checkedAt: string;\r\n}\r\n\r\nfunction VersionCheckSection() {\r\n const { formatMessage } = useIntl();\r\n const [versionData, setVersionData] = useState<VersionData | null>(null);\r\n const [checking, setChecking] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [lastChecked, setLastChecked] = useState<Date | null>(null);\r\n const [autoCheck, setAutoCheck] = useState(() => {\r\n try {\r\n const saved = localStorage.getItem('ccw.autoUpdate');\r\n return saved === null ? true : JSON.parse(saved);\r\n } catch {\r\n return true;\r\n }\r\n });\r\n\r\n const checkVersion = async (silent = false) => {\r\n if (!silent) setChecking(true);\r\n setError(null);\r\n try {\r\n const response = await fetch('/api/version-check');\r\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\r\n\r\n const data: VersionData = await response.json();\r\n if (!data.currentVersion) throw new Error('Invalid response');\r\n\r\n setVersionData(data);\r\n setLastChecked(new Date());\r\n } catch (err) {\r\n if (!silent) setError(err instanceof Error ? err.message : 'Unknown error');\r\n } finally {\r\n setChecking(false);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n // Initial check\r\n checkVersion(true);\r\n\r\n if (!autoCheck) return;\r\n const interval = setInterval(() => checkVersion(true), 60 * 60 * 1000);\r\n return () => clearInterval(interval);\r\n }, [autoCheck]);\r\n\r\n const toggleAutoCheck = (enabled: boolean) => {\r\n setAutoCheck(enabled);\r\n localStorage.setItem('ccw.autoUpdate', JSON.stringify(enabled));\r\n };\r\n\r\n return (\r\n <Card className=\"p-6\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2\">\r\n <ArrowUpCircle className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.versionCheck.title' })}\r\n </h2>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n disabled={checking}\r\n onClick={() => checkVersion()}\r\n >\r\n <RefreshCw className={cn('w-3.5 h-3.5 mr-1.5', checking && 'animate-spin')} />\r\n {checking\r\n ? formatMessage({ id: 'settings.versionCheck.checking' })\r\n : formatMessage({ id: 'settings.versionCheck.checkNow' })}\r\n </Button>\r\n </div>\r\n\r\n <div className=\"space-y-4\">\r\n {/* Version info */}\r\n <div className=\"rounded-lg border border-border p-4 space-y-3\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.versionCheck.currentVersion' })}\r\n </span>\r\n <Badge variant=\"secondary\" className=\"font-mono text-xs\">\r\n {versionData?.currentVersion ?? '...'}\r\n </Badge>\r\n </div>\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.versionCheck.latestVersion' })}\r\n </span>\r\n <Badge\r\n variant={versionData?.hasUpdate ? 'default' : 'secondary'}\r\n className=\"font-mono text-xs\"\r\n >\r\n {versionData?.latestVersion ?? '...'}\r\n </Badge>\r\n </div>\r\n\r\n {/* Status */}\r\n {versionData && (\r\n <div className=\"flex items-center justify-between pt-2 border-t border-border\">\r\n <span className=\"text-sm font-medium\">\r\n {versionData.hasUpdate\r\n ? formatMessage({ id: 'settings.versionCheck.updateAvailable' })\r\n : formatMessage({ id: 'settings.versionCheck.upToDate' })}\r\n </span>\r\n <span className={cn(\r\n 'inline-block w-2.5 h-2.5 rounded-full',\r\n versionData.hasUpdate ? 'bg-orange-500' : 'bg-green-500'\r\n )} />\r\n </div>\r\n )}\r\n\r\n {error && (\r\n <div className=\"flex items-center gap-2 pt-2 border-t border-border\">\r\n <AlertTriangle className=\"w-4 h-4 text-destructive flex-shrink-0\" />\r\n <span className=\"text-sm text-destructive\">\r\n {formatMessage({ id: 'settings.versionCheck.checkFailed' })}: {error}\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Update action */}\r\n {versionData?.hasUpdate && (\r\n <div className=\"rounded-lg border border-orange-500/30 bg-orange-500/5 p-4 space-y-3\">\r\n <div>\r\n <p className=\"text-sm font-medium text-foreground mb-1\">\r\n {formatMessage({ id: 'settings.versionCheck.updateCommand' })}\r\n </p>\r\n <code className=\"text-xs font-mono bg-muted px-3 py-1.5 rounded block\">\r\n {versionData.updateCommand}\r\n </code>\r\n </div>\r\n <Button variant=\"outline\" size=\"sm\" asChild>\r\n <a\r\n href=\"https://github.com/dyw0830/ccw/releases\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"inline-flex items-center gap-1.5\"\r\n >\r\n {formatMessage({ id: 'settings.versionCheck.viewRelease' })}\r\n </a>\r\n </Button>\r\n </div>\r\n )}\r\n\r\n {/* Auto check toggle + last checked */}\r\n <div className=\"flex items-center justify-between\">\r\n <label className=\"flex items-center gap-2 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={autoCheck}\r\n onChange={(e) => toggleAutoCheck(e.target.checked)}\r\n className=\"rounded border-input\"\r\n />\r\n <div>\r\n <span className=\"text-sm font-medium\">{formatMessage({ id: 'settings.versionCheck.autoCheck' })}</span>\r\n <p className=\"text-xs text-muted-foreground\">{formatMessage({ id: 'settings.versionCheck.autoCheckDesc' })}</p>\r\n </div>\r\n </label>\r\n <span className=\"text-xs text-muted-foreground\">\r\n {formatMessage({ id: 'settings.versionCheck.lastChecked' })}:{' '}\r\n {lastChecked ? lastChecked.toLocaleTimeString() : formatMessage({ id: 'settings.versionCheck.never' })}\r\n </span>\r\n </div>\r\n </div>\r\n </Card>\r\n );\r\n}\r\n\r\n// ========== System Status Section ==========\r\n\r\nfunction SystemStatusSection() {\r\n const { formatMessage } = useIntl();\r\n const { installations, isLoading, refetch } = useCcwInstallations();\r\n const { upgrade, isPending: upgrading } = useUpgradeCcwInstallation();\r\n const { data: ccwInstall } = useCcwInstallStatus();\r\n\r\n return (\r\n <Card className=\"p-6\">\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2\">\r\n <Package className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.systemStatus.title' })}\r\n {!isLoading && (\r\n <span className=\"text-sm font-normal text-muted-foreground\">\r\n {installations.length} {formatMessage({ id: 'settings.systemStatus.installations' })}\r\n </span>\r\n )}\r\n </h2>\r\n <div className=\"flex items-center gap-1\">\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className=\"h-7 w-7 p-0\"\r\n onClick={() => refetch()}\r\n title={formatMessage({ id: 'settings.systemStatus.refresh' })}\r\n >\r\n <RefreshCw className={cn('w-3.5 h-3.5', isLoading && 'animate-spin')} />\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Installation cards */}\r\n {isLoading ? (\r\n <div className=\"text-sm text-muted-foreground py-4 text-center\">\r\n {formatMessage({ id: 'settings.systemStatus.checking' })}\r\n </div>\r\n ) : installations.length === 0 ? (\r\n <div className=\"text-center py-6 space-y-2\">\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.systemStatus.noInstallations' })}\r\n </p>\r\n <div className=\"bg-muted/50 rounded-md p-3 inline-block\">\r\n <code className=\"text-xs font-mono\">ccw install</code>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"space-y-3\">\r\n {installations.map((inst) => {\r\n const isGlobal = inst.installation_mode === 'Global';\r\n const installDate = new Date(inst.installation_date).toLocaleDateString();\r\n const version = inst.application_version !== 'unknown' ? inst.application_version : inst.installer_version;\r\n\r\n return (\r\n <div\r\n key={inst.manifest_id}\r\n className=\"rounded-lg border border-border p-4 space-y-2\"\r\n >\r\n {/* Mode + Version + Upgrade */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className={cn(\r\n 'inline-flex items-center justify-center w-8 h-8 rounded-lg',\r\n isGlobal ? 'bg-primary/10 text-primary' : 'bg-orange-500/10 text-orange-500'\r\n )}>\r\n {isGlobal ? <Home className=\"w-4 h-4\" /> : <Folder className=\"w-4 h-4\" />}\r\n </span>\r\n <span className=\"text-sm font-medium\">\r\n {isGlobal\r\n ? formatMessage({ id: 'settings.systemStatus.global' })\r\n : formatMessage({ id: 'settings.systemStatus.path' })}\r\n </span>\r\n <Badge variant=\"secondary\" className=\"text-xs font-mono\">\r\n v{version}\r\n </Badge>\r\n </div>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n className=\"h-7\"\r\n disabled={upgrading}\r\n onClick={() => upgrade(inst.installation_path)}\r\n >\r\n <ArrowUpCircle className={cn('w-3.5 h-3.5 mr-1', upgrading && 'animate-spin')} />\r\n {upgrading\r\n ? formatMessage({ id: 'settings.systemStatus.upgrading' })\r\n : formatMessage({ id: 'settings.systemStatus.upgrade' })}\r\n </Button>\r\n </div>\r\n\r\n {/* Path */}\r\n <div className=\"text-xs text-muted-foreground bg-muted/50 rounded px-2 py-1 font-mono truncate\" title={inst.installation_path}>\r\n {inst.installation_path}\r\n </div>\r\n\r\n {/* Date + Files */}\r\n <div className=\"flex items-center gap-4 text-xs text-muted-foreground\">\r\n <span className=\"inline-flex items-center gap-1\">\r\n <Calendar className=\"w-3 h-3\" />\r\n {installDate}\r\n </span>\r\n <span className=\"inline-flex items-center gap-1\">\r\n <File className=\"w-3 h-3\" />\r\n {inst.files_count} {formatMessage({ id: 'settings.systemStatus.files' })}\r\n </span>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n\r\n {/* Missing files warning */}\r\n {ccwInstall && !ccwInstall.installed && ccwInstall.missingFiles.length > 0 && (\r\n <div className=\"rounded-lg border border-yellow-500/50 bg-yellow-500/5 p-4 space-y-2\">\r\n <div className=\"flex items-center gap-2 text-sm font-medium text-yellow-600 dark:text-yellow-500\">\r\n <AlertTriangle className=\"w-4 h-4\" />\r\n {formatMessage({ id: 'settings.systemStatus.incomplete' })} &mdash; {ccwInstall.missingFiles.length} {formatMessage({ id: 'settings.systemStatus.missingFiles' }).toLowerCase()}\r\n </div>\r\n <ul className=\"text-xs text-muted-foreground list-disc list-inside\">\r\n {ccwInstall.missingFiles.slice(0, 4).map((f) => (\r\n <li key={f}>{f}</li>\r\n ))}\r\n {ccwInstall.missingFiles.length > 4 && (\r\n <li>+{ccwInstall.missingFiles.length - 4} more...</li>\r\n )}\r\n </ul>\r\n <div className=\"bg-muted/50 rounded-md p-2\">\r\n <p className=\"text-xs font-medium mb-1\">{formatMessage({ id: 'settings.systemStatus.runToFix' })}:</p>\r\n <code className=\"text-xs font-mono bg-background px-2 py-1 rounded block\">ccw install</code>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </Card>\r\n );\r\n}\r\n\r\n// ========== CLI Tools with Status Enhancement ==========\r\n\r\ninterface CliToolsWithStatusProps {\r\n cliTools: Record<string, CliToolConfig>;\r\n defaultCliTool: string;\r\n expandedTools: Set<string>;\r\n savingTools: Set<string>;\r\n onToggleExpand: (toolId: string) => void;\r\n onToggleEnabled: (toolId: string) => void;\r\n onSetDefault: (toolId: string) => void;\r\n onUpdateModel: (toolId: string, field: 'primaryModel' | 'secondaryModel', value: string) => void;\r\n onUpdateTags: (toolId: string, tags: string[]) => void;\r\n onUpdateAvailableModels: (toolId: string, models: string[]) => void;\r\n onUpdateEnvFile: (toolId: string, envFile: string | undefined) => void;\r\n onUpdateSettingsFile: (toolId: string, settingsFile: string | undefined) => void;\r\n onUpdateEffort: (toolId: string, effort: string | undefined) => void;\r\n onSaveToBackend: (toolId: string) => void;\r\n formatMessage: ReturnType<typeof useIntl>['formatMessage'];\r\n}\r\n\r\nfunction CliToolsWithStatus({\r\n cliTools,\r\n defaultCliTool,\r\n expandedTools,\r\n savingTools,\r\n onToggleExpand,\r\n onToggleEnabled,\r\n onSetDefault,\r\n onUpdateModel,\r\n onUpdateTags,\r\n onUpdateAvailableModels,\r\n onUpdateEnvFile,\r\n onUpdateSettingsFile,\r\n onUpdateEffort,\r\n onSaveToBackend,\r\n formatMessage,\r\n}: CliToolsWithStatusProps) {\r\n const { data: toolStatus } = useCliToolStatus();\r\n\r\n return (\r\n <>\r\n <p className=\"text-sm text-muted-foreground mb-4\">\r\n {formatMessage({ id: 'settings.cliTools.description' })} <strong className=\"text-foreground\">{defaultCliTool}</strong>\r\n </p>\r\n <div className=\"space-y-3\">\r\n {Object.entries(cliTools).map(([toolId, config]) => {\r\n const status = toolStatus?.[toolId];\r\n return (\r\n <CliToolCard\r\n key={toolId}\r\n toolId={toolId}\r\n config={config}\r\n isDefault={toolId === defaultCliTool}\r\n isExpanded={expandedTools.has(toolId)}\r\n toolAvailable={status?.available}\r\n isSaving={savingTools.has(toolId)}\r\n onToggleExpand={() => onToggleExpand(toolId)}\r\n onToggleEnabled={() => onToggleEnabled(toolId)}\r\n onSetDefault={() => onSetDefault(toolId)}\r\n onUpdateModel={(field, value) => onUpdateModel(toolId, field, value)}\r\n onUpdateTags={(tags) => onUpdateTags(toolId, tags)}\r\n onUpdateAvailableModels={(models) => onUpdateAvailableModels(toolId, models)}\r\n onUpdateEnvFile={(envFile) => onUpdateEnvFile(toolId, envFile)}\r\n onUpdateSettingsFile={(settingsFile) => onUpdateSettingsFile(toolId, settingsFile)}\r\n onUpdateEffort={(effort) => onUpdateEffort(toolId, effort)}\r\n onSaveToBackend={() => onSaveToBackend(toolId)}\r\n />\r\n );\r\n })}\r\n </div>\r\n </>\r\n );\r\n}\r\n\r\n// ========== Main Page Component ==========\r\n\r\nexport function SettingsPage() {\r\n const { formatMessage } = useIntl();\r\n const { theme, setTheme } = useTheme();\r\n const cliTools = useConfigStore(selectCliTools);\r\n const defaultCliTool = useConfigStore(selectDefaultCliTool);\r\n const userPreferences = useConfigStore(selectUserPreferences);\r\n const { updateCliTool, setDefaultCliTool, setUserPreferences, resetUserPreferences } = useConfigStore();\r\n\r\n const [expandedTools, setExpandedTools] = useState<Set<string>>(new Set());\r\n const [savingTools, setSavingTools] = useState<Set<string>>(new Set());\r\n\r\n const toggleToolExpand = (toolId: string) => {\r\n setExpandedTools((prev) => {\r\n const next = new Set(prev);\r\n if (next.has(toolId)) {\r\n next.delete(toolId);\r\n } else {\r\n next.add(toolId);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const handleToggleToolEnabled = (toolId: string) => {\r\n updateCliTool(toolId, { enabled: !cliTools[toolId].enabled });\r\n };\r\n\r\n const handleSetDefaultTool = (toolId: string) => {\r\n setDefaultCliTool(toolId);\r\n };\r\n\r\n const handleUpdateModel = (toolId: string, field: 'primaryModel' | 'secondaryModel', value: string) => {\r\n updateCliTool(toolId, { [field]: value });\r\n };\r\n\r\n const handleUpdateTags = (toolId: string, tags: string[]) => {\r\n updateCliTool(toolId, { tags });\r\n };\r\n\r\n const handleUpdateAvailableModels = (toolId: string, availableModels: string[]) => {\r\n updateCliTool(toolId, { availableModels });\r\n };\r\n\r\n const handleUpdateEnvFile = (toolId: string, envFile: string | undefined) => {\r\n updateCliTool(toolId, { envFile });\r\n };\r\n\r\n const handleUpdateSettingsFile = (toolId: string, settingsFile: string | undefined) => {\r\n updateCliTool(toolId, { settingsFile });\r\n };\r\n\r\n const handleUpdateEffort = (toolId: string, effort: string | undefined) => {\r\n updateCliTool(toolId, { effort });\r\n };\r\n\r\n // Save tool config to backend (~/.claude/cli-tools.json)\r\n const handleSaveToBackend = useCallback(async (toolId: string) => {\r\n const config = cliTools[toolId];\r\n if (!config) return;\r\n\r\n setSavingTools((prev) => new Set(prev).add(toolId));\r\n try {\r\n const body: Record<string, unknown> = {\r\n enabled: config.enabled,\r\n primaryModel: config.primaryModel,\r\n secondaryModel: config.secondaryModel,\r\n tags: config.tags,\r\n availableModels: config.availableModels,\r\n };\r\n\r\n // Only include the relevant config file field\r\n const configFileType = getConfigFileType(toolId);\r\n if (configFileType === 'envFile') {\r\n body.envFile = config.envFile || null;\r\n } else if (configFileType === 'settingsFile') {\r\n body.settingsFile = config.settingsFile || null;\r\n body.effort = config.effort || null;\r\n }\r\n\r\n const csrfToken = getCsrfToken();\r\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\r\n if (csrfToken) {\r\n headers['X-CSRF-Token'] = csrfToken;\r\n }\r\n\r\n const res = await fetch(`/api/cli/config/${toolId}`, {\r\n method: 'PUT',\r\n headers,\r\n body: JSON.stringify(body),\r\n credentials: 'same-origin',\r\n });\r\n\r\n if (!res.ok) {\r\n throw new Error(`HTTP ${res.status}`);\r\n }\r\n\r\n toast.success(formatMessage({ id: 'settings.cliTools.configSaved' }), {\r\n description: toolId,\r\n });\r\n } catch {\r\n toast.error(formatMessage({ id: 'settings.cliTools.configSaveError' }), {\r\n description: toolId,\r\n });\r\n } finally {\r\n setSavingTools((prev) => {\r\n const next = new Set(prev);\r\n next.delete(toolId);\r\n return next;\r\n });\r\n }\r\n }, [cliTools, formatMessage]);\r\n\r\n const handlePreferenceChange = (key: keyof UserPreferences, value: unknown) => {\r\n setUserPreferences({ [key]: value });\r\n };\r\n\r\n return (\r\n <div className=\"max-w-4xl mx-auto space-y-8\">\r\n {/* Page Header */}\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-foreground flex items-center gap-2\">\r\n <Settings className=\"w-6 h-6 text-primary\" />\r\n {formatMessage({ id: 'settings.title' })}\r\n </h1>\r\n <p className=\"text-muted-foreground mt-1\">\r\n {formatMessage({ id: 'settings.description' })}\r\n </p>\r\n </div>\r\n\r\n {/* Appearance Settings */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <Moon className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.sections.appearance' })}\r\n </h2>\r\n <div className=\"space-y-6\">\r\n {/* Multi-Theme Selector */}\r\n <div>\r\n <p className=\"font-medium text-foreground mb-1\">\r\n {formatMessage({ id: 'settings.appearance.theme' })}\r\n </p>\r\n <p className=\"text-sm text-muted-foreground mb-4\">\r\n {formatMessage({ id: 'settings.appearance.description' })}\r\n </p>\r\n <ThemeSelector />\r\n </div>\r\n\r\n {/* System Theme Toggle (Backward Compatibility) */}\r\n <div className=\"flex items-center justify-between pt-4 border-t border-border\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.appearance.systemFollow' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.appearance.systemFollowDesc' })}\r\n </p>\r\n </div>\r\n <Button\r\n variant={theme === 'system' ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => setTheme('system')}\r\n >\r\n {formatMessage({ id: 'settings.appearance.themeOptions.system' })}\r\n </Button>\r\n </div>\r\n </div>\r\n </Card>\r\n\r\n {/* Language Settings */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <Languages className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.sections.language' })}\r\n </h2>\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.language.displayLanguage' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.language.chooseLanguage' })}\r\n </p>\r\n </div>\r\n <LanguageSwitcher />\r\n </div>\r\n </div>\r\n </Card>\r\n\r\n {/* Response Language Settings */}\r\n <ResponseLanguageSection />\r\n\r\n {/* A2UI Preferences */}\r\n <A2UIPreferencesSection />\r\n\r\n {/* System Status */}\r\n <SystemStatusSection />\r\n\r\n {/* Version Check */}\r\n <VersionCheckSection />\r\n\r\n {/* CLI Tools Configuration */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <Cpu className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.sections.cliTools' })}\r\n </h2>\r\n <CliToolsWithStatus\r\n cliTools={cliTools}\r\n defaultCliTool={defaultCliTool}\r\n expandedTools={expandedTools}\r\n savingTools={savingTools}\r\n onToggleExpand={toggleToolExpand}\r\n onToggleEnabled={handleToggleToolEnabled}\r\n onSetDefault={handleSetDefaultTool}\r\n onUpdateModel={handleUpdateModel}\r\n onUpdateTags={handleUpdateTags}\r\n onUpdateAvailableModels={handleUpdateAvailableModels}\r\n onUpdateEnvFile={handleUpdateEnvFile}\r\n onUpdateSettingsFile={handleUpdateSettingsFile}\r\n onUpdateEffort={handleUpdateEffort}\r\n onSaveToBackend={handleSaveToBackend}\r\n formatMessage={formatMessage}\r\n />\r\n </Card>\r\n\r\n {/* Data Refresh Settings */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <RefreshCw className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.dataRefresh.title' })}\r\n </h2>\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.dataRefresh.autoRefresh' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.dataRefresh.autoRefreshDesc' })}\r\n </p>\r\n </div>\r\n <Button\r\n variant={userPreferences.autoRefresh ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => handlePreferenceChange('autoRefresh', !userPreferences.autoRefresh)}\r\n >\r\n {userPreferences.autoRefresh ? formatMessage({ id: 'settings.dataRefresh.enabled' }) : formatMessage({ id: 'settings.dataRefresh.disabled' })}\r\n </Button>\r\n </div>\r\n\r\n {userPreferences.autoRefresh && (\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.dataRefresh.refreshInterval' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.dataRefresh.refreshIntervalDesc' })}\r\n </p>\r\n </div>\r\n <div className=\"flex gap-2\">\r\n {[15000, 30000, 60000, 120000].map((interval) => (\r\n <Button\r\n key={interval}\r\n variant={userPreferences.refreshInterval === interval ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => handlePreferenceChange('refreshInterval', interval)}\r\n >\r\n {interval / 1000}s\r\n </Button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </Card>\r\n\r\n {/* Notifications */}\r\n <Card className=\"p-6\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <Bell className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'settings.notifications.title' })}\r\n </h2>\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.notifications.enableNotifications' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.notifications.enableNotificationsDesc' })}\r\n </p>\r\n </div>\r\n <Button\r\n variant={userPreferences.notificationsEnabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => handlePreferenceChange('notificationsEnabled', !userPreferences.notificationsEnabled)}\r\n >\r\n {userPreferences.notificationsEnabled ? formatMessage({ id: 'settings.dataRefresh.enabled' }) : formatMessage({ id: 'settings.dataRefresh.disabled' })}\r\n </Button>\r\n </div>\r\n\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-medium text-foreground\">{formatMessage({ id: 'settings.notifications.soundEffects' })}</p>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {formatMessage({ id: 'settings.notifications.soundEffectsDesc' })}\r\n </p>\r\n </div>\r\n <Button\r\n variant={userPreferences.soundEnabled ? 'default' : 'outline'}\r\n size=\"sm\"\r\n onClick={() => handlePreferenceChange('soundEnabled', !userPreferences.soundEnabled)}\r\n >\r\n {userPreferences.soundEnabled ? formatMessage({ id: 'settings.notifications.on' }) : formatMessage({ id: 'settings.notifications.off' })}\r\n </Button>\r\n </div>\r\n </div>\r\n </Card>\r\n\r\n {/* Remote Notifications */}\r\n <RemoteNotificationSection />\r\n\r\n {/* Reset Settings */}\r\n <Card className=\"p-6 border-destructive/50\">\r\n <h2 className=\"text-lg font-semibold text-foreground flex items-center gap-2 mb-4\">\r\n <RotateCcw className=\"w-5 h-5\" />\r\n {formatMessage({ id: 'common.actions.reset' })}\r\n </h2>\r\n <p className=\"text-sm text-muted-foreground mb-4\">\r\n {formatMessage({ id: 'settings.reset.description' })}\r\n </p>\r\n <Button\r\n variant=\"destructive\"\r\n onClick={() => {\r\n if (confirm(formatMessage({ id: 'settings.reset.confirm' }))) {\r\n resetUserPreferences();\r\n }\r\n }}\r\n >\r\n <RotateCcw className=\"w-4 h-4 mr-2\" />\r\n {formatMessage({ id: 'common.actions.resetToDefaults' })}\r\n </Button>\r\n </Card>\r\n </div>\r\n );\r\n}\r\n\r\nexport default SettingsPage;\r\n"],"file":"assets/SettingsPage-BY3QiJhm.js"}