@weppy/roblox-mcp 2.10.4 → 2.11.0

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 (51) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dashboard/dist/assets/{AssetsPage-YhGnZEI3.js → AssetsPage-kz1FKCck.js} +10 -10
  3. package/dashboard/dist/assets/ChangelogDetailPage-DtMfQXpn.js +1 -0
  4. package/dashboard/dist/assets/ChangelogDetailPage-vGgnpq1q.css +1 -0
  5. package/dashboard/dist/assets/ChangelogPage-DBeldxYm.js +1 -0
  6. package/dashboard/dist/assets/{ConfirmModal-WlE0qUHf.js → ConfirmModal-Cxha5h-n.js} +1 -1
  7. package/dashboard/dist/assets/{ConnectionPage-7MGw5kBx.js → ConnectionPage-8_vdhL7O.js} +2 -2
  8. package/dashboard/dist/assets/ControlsPage-CZBhWyyn.js +1 -0
  9. package/dashboard/dist/assets/CurrentPlaceScope-BKwvaN7Z.js +1 -0
  10. package/dashboard/dist/assets/{GameChangeDetail-1QGJVFSx.js → GameChangeDetail-raYOxmZc.js} +1 -1
  11. package/dashboard/dist/assets/{InfoLabel-BkAQdbWd.js → InfoLabel-dwgFWAxs.js} +1 -1
  12. package/dashboard/dist/assets/OverviewPage-DI5xU7tr.js +1 -0
  13. package/dashboard/dist/assets/PageHeader-BfTFbEOK.js +6 -0
  14. package/dashboard/dist/assets/PageHeader-CV_rjuG8.css +1 -0
  15. package/dashboard/dist/assets/{PlaytestPage-DVo_oYz5.js → PlaytestPage-BXzNfelw.js} +2 -2
  16. package/dashboard/dist/assets/SettingsPage-BzmeWDML.js +1 -0
  17. package/dashboard/dist/assets/{StatusBadge-C2tcoGvy.js → StatusBadge-Cbf0AbKE.js} +1 -1
  18. package/dashboard/dist/assets/SyncPage-BnVXEQel.css +1 -0
  19. package/dashboard/dist/assets/SyncPage-ChaWvprV.js +4 -0
  20. package/dashboard/dist/assets/{Tabs-Bb6imtwV.js → Tabs-9EkdOGoe.js} +1 -1
  21. package/dashboard/dist/assets/ToolsPage-AYrVzepe.js +1 -0
  22. package/dashboard/dist/assets/{TooltipText-0HIROg6e.js → TooltipText-DLPk69aK.js} +1 -1
  23. package/dashboard/dist/assets/{PageHeader-CrhjZjgp.css → UiPrimitive-BMSNRGwI.css} +1 -1
  24. package/dashboard/dist/assets/UiPrimitive-jQZP77uI.js +1 -0
  25. package/dashboard/dist/assets/{UiStudioPage-BVuHR29W.js → UiStudioPage-De2Q3D5I.js} +2 -2
  26. package/dashboard/dist/assets/WhatsNewPage-CK-MRVXv.js +1 -0
  27. package/dashboard/dist/assets/WhatsNewPage-wF04BABp.css +1 -0
  28. package/dashboard/dist/assets/{copy-ozprzL33.js → copy-mg-q_vEk.js} +1 -1
  29. package/dashboard/dist/assets/index-C8kXDvHv.js +750 -0
  30. package/dashboard/dist/assets/sample-requests-7VK_Hj8C.js +1 -0
  31. package/dashboard/dist/assets/{useLiveUptime-DpvpGzTY.js → useLiveUptime-BzjLApne.js} +1 -1
  32. package/dashboard/dist/assets/{useSettings-D918ACY5.js → useSettings-C1r4pJQ4.js} +1 -1
  33. package/dashboard/dist/index.html +1 -1
  34. package/dist/index.js +92 -79
  35. package/package.json +1 -1
  36. package/roblox-plugin/WeppyRobloxMCP.rbxm +0 -0
  37. package/dashboard/dist/assets/ChangelogDetailPage-C78XiyDy.js +0 -1
  38. package/dashboard/dist/assets/ChangelogDetailPage-D6Tqz7ut.css +0 -1
  39. package/dashboard/dist/assets/ChangelogPage-BDUgixCt.js +0 -1
  40. package/dashboard/dist/assets/ControlsPage-BUtN2zIN.js +0 -1
  41. package/dashboard/dist/assets/CurrentPlaceScope-CF_xE8My.js +0 -1
  42. package/dashboard/dist/assets/OverviewPage-D1OcIXB0.js +0 -1
  43. package/dashboard/dist/assets/PageHeader-CD450myM.js +0 -6
  44. package/dashboard/dist/assets/SettingsPage-CU7CHyaG.js +0 -1
  45. package/dashboard/dist/assets/SyncPage-BYVYYvX1.js +0 -4
  46. package/dashboard/dist/assets/SyncPage-CIZWp8Ul.css +0 -1
  47. package/dashboard/dist/assets/ToolsPage-DuMKAsHP.js +0 -1
  48. package/dashboard/dist/assets/WhatsNewPage-BIYOEZg3.css +0 -1
  49. package/dashboard/dist/assets/WhatsNewPage-CfslOZQY.js +0 -1
  50. package/dashboard/dist/assets/index-T_F9Rs-N.js +0 -718
  51. package/dashboard/dist/assets/sample-requests-D5m4UOF0.js +0 -1
package/CHANGELOG.md CHANGED
@@ -18,6 +18,23 @@ All notable changes to this project will be documented in this file.
18
18
 
19
19
 
20
20
 
21
+
22
+ ## [2.11.0] - 2026-07-19
23
+
24
+ ### Features
25
+
26
+ - **Cleaner Project Sync files with a reviewed v3 update** — New Sync projects now use a canonical file format that avoids unnecessary Git diffs when the same Studio state is synced again. Existing v2 projects stay unchanged until you review the exact metadata additions, modifications, deletions, and blockers in the Dashboard Sync page and explicitly apply the update. WEPPY creates a runtime backup before applying it and does not modify Luau source files. After a place is updated to v3, opening that Sync data with an older MCP server is not supported; projects that remain on v2 continue to work normally.
27
+ - **Read-only Studio readiness checks before AI work** — AI agents can now use `system_info.preflight` to check the selected Studio connection, place identity, Edit or Play state, publish status, screenshot readiness, and security capabilities before starting a task. The check reports specific setup actions without changing Studio settings, the DataModel, or DataStore state.
28
+ - **Read-only Open Cloud upload checks** — Pro users can now verify the saved API key, Assets Read and Write permissions, Creator target, requested asset category, and local file format and size before uploading. Running `manage_open_cloud_assets.preflight` does not upload or update a Roblox asset and does not expose the raw API key.
29
+
30
+ ### Bug Fixes
31
+
32
+ - **No duplicate events in completed Playtest reports** — `manage_studio.run_test` no longer records the same logs and signals twice when a completed test reports them through both the final result and the live event stream. Timeout and cancellation reports still preserve the available partial stream evidence, including intentional repeated messages.
33
+
34
+ ### Stability
35
+
36
+ - **Less Sync metadata noise in Git and Dashboard history** — Runtime files such as session and timestamp state are ignored by WEPPY-managed Git rules and excluded from game-change history, while generated files can be distinguished from user source and canonical mirror changes. Existing user `.gitignore` rules and already tracked files are left in place.
37
+
21
38
  ## [2.10.4] - 2026-07-18
22
39
 
23
40
  ### Features
@@ -1,46 +1,46 @@
1
- import{i as ne,a as $,n as ve,u as me,j as t,P as pt,I as mt,r as c,o as ht,R as Ze,X as Ue,E as xt,p as Je,g as gt,e as bt,h as ft}from"./index-T_F9Rs-N.js";import{C as Qe}from"./ConfirmModal-WlE0qUHf.js";import{B as Ee,C as yt,D as Te,P as jt}from"./PageHeader-CD450myM.js";import{T as G}from"./TooltipText-0HIROg6e.js";import{C as et}from"./copy-ozprzL33.js";import"./ConfirmModal.module-D1aZY2bQ.js";/**
1
+ import{i as ne,a as $,o as ve,u as me,j as t,P as pt,I as mt,r as d,p as ht,R as Ze,X as Ue,E as xt,q as Je,g as gt,e as bt,h as ft}from"./index-C8kXDvHv.js";import{C as Qe}from"./ConfirmModal-Cxha5h-n.js";import{D as Ee,a as yt,P as jt}from"./PageHeader-BfTFbEOK.js";import{T as G}from"./TooltipText-DLPk69aK.js";import{B as Te,C as vt}from"./UiPrimitive-jQZP77uI.js";import{C as et}from"./copy-mg-q_vEk.js";import"./ConfirmModal.module-D1aZY2bQ.js";/**
2
2
  * @license lucide-react v1.8.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
- */const vt=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],Ct=ne("arrow-left",vt);/**
6
+ */const Ct=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],_t=ne("arrow-left",Ct);/**
7
7
  * @license lucide-react v1.8.0 - ISC
8
8
  *
9
9
  * This source code is licensed under the ISC license.
10
10
  * See the LICENSE file in the root directory of this source tree.
11
- */const _t=[["path",{d:"M2 10v3",key:"1fnikh"}],["path",{d:"M6 6v11",key:"11sgs0"}],["path",{d:"M10 3v18",key:"yhl04a"}],["path",{d:"M14 8v7",key:"3a1oy3"}],["path",{d:"M18 5v13",key:"123xd1"}],["path",{d:"M22 10v3",key:"154ddg"}]],St=ne("audio-lines",_t);/**
11
+ */const St=[["path",{d:"M2 10v3",key:"1fnikh"}],["path",{d:"M6 6v11",key:"11sgs0"}],["path",{d:"M10 3v18",key:"yhl04a"}],["path",{d:"M14 8v7",key:"3a1oy3"}],["path",{d:"M18 5v13",key:"123xd1"}],["path",{d:"M22 10v3",key:"154ddg"}]],It=ne("audio-lines",St);/**
12
12
  * @license lucide-react v1.8.0 - ISC
13
13
  *
14
14
  * This source code is licensed under the ISC license.
15
15
  * See the LICENSE file in the root directory of this source tree.
16
- */const It=[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z",key:"3c2336"}]],Nt=ne("badge",It);/**
16
+ */const Nt=[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z",key:"3c2336"}]],At=ne("badge",Nt);/**
17
17
  * @license lucide-react v1.8.0 - ISC
18
18
  *
19
19
  * This source code is licensed under the ISC license.
20
20
  * See the LICENSE file in the root directory of this source tree.
21
- */const At=[["path",{d:"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z",key:"hh9hay"}],["path",{d:"m3.3 7 8.7 5 8.7-5",key:"g66t2b"}],["path",{d:"M12 22V12",key:"d0xqtd"}]],Pt=ne("box",At);/**
21
+ */const Pt=[["path",{d:"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z",key:"hh9hay"}],["path",{d:"m3.3 7 8.7 5 8.7-5",key:"g66t2b"}],["path",{d:"M12 22V12",key:"d0xqtd"}]],kt=ne("box",Pt);/**
22
22
  * @license lucide-react v1.8.0 - ISC
23
23
  *
24
24
  * This source code is licensed under the ISC license.
25
25
  * See the LICENSE file in the root directory of this source tree.
26
- */const kt=[["path",{d:"m12.296 3.464 3.02 3.956",key:"qash78"}],["path",{d:"M20.2 6 3 11l-.9-2.4c-.3-1.1.3-2.2 1.3-2.5l13.5-4c1.1-.3 2.2.3 2.5 1.3z",key:"1h7j8b"}],["path",{d:"M3 11h18v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"4lm6w1"}],["path",{d:"m6.18 5.276 3.1 3.899",key:"zjj9t3"}]],Rt=ne("clapperboard",kt);/**
26
+ */const Rt=[["path",{d:"m12.296 3.464 3.02 3.956",key:"qash78"}],["path",{d:"M20.2 6 3 11l-.9-2.4c-.3-1.1.3-2.2 1.3-2.5l13.5-4c1.1-.3 2.2.3 2.5 1.3z",key:"1h7j8b"}],["path",{d:"M3 11h18v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"4lm6w1"}],["path",{d:"m6.18 5.276 3.1 3.899",key:"zjj9t3"}]],$t=ne("clapperboard",Rt);/**
27
27
  * @license lucide-react v1.8.0 - ISC
28
28
  *
29
29
  * This source code is licensed under the ISC license.
30
30
  * See the LICENSE file in the root directory of this source tree.
31
- */const $t=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M7 3v18",key:"bbkbws"}],["path",{d:"M3 7.5h4",key:"zfgn84"}],["path",{d:"M3 12h18",key:"1i2n21"}],["path",{d:"M3 16.5h4",key:"1230mu"}],["path",{d:"M17 3v18",key:"in4fa5"}],["path",{d:"M17 7.5h4",key:"myr1c1"}],["path",{d:"M17 16.5h4",key:"go4c1d"}]],wt=ne("film",$t);/**
31
+ */const wt=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M7 3v18",key:"bbkbws"}],["path",{d:"M3 7.5h4",key:"zfgn84"}],["path",{d:"M3 12h18",key:"1i2n21"}],["path",{d:"M3 16.5h4",key:"1230mu"}],["path",{d:"M17 3v18",key:"in4fa5"}],["path",{d:"M17 7.5h4",key:"myr1c1"}],["path",{d:"M17 16.5h4",key:"go4c1d"}]],Lt=ne("film",wt);/**
32
32
  * @license lucide-react v1.8.0 - ISC
33
33
  *
34
34
  * This source code is licensed under the ISC license.
35
35
  * See the LICENSE file in the root directory of this source tree.
36
- */const Lt=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],Bt=ne("search",Lt);/**
36
+ */const Bt=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],Ut=ne("search",Bt);/**
37
37
  * @license lucide-react v1.8.0 - ISC
38
38
  *
39
39
  * This source code is licensed under the ISC license.
40
40
  * See the LICENSE file in the root directory of this source tree.
41
- */const Ut=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],Dt=ne("trash-2",Ut);/**
41
+ */const Dt=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],Et=ne("trash-2",Dt);/**
42
42
  * @license lucide-react v1.8.0 - ISC
43
43
  *
44
44
  * This source code is licensed under the ISC license.
45
45
  * See the LICENSE file in the root directory of this source tree.
46
- */const Et=[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m17 8-5-5-5 5",key:"7q97r8"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}]],Tt=ne("upload",Et);function tt(e){if(e.scope==="place"&&typeof e.placeId=="number")return{placeId:String(e.placeId)}}function ae(e){const s=tt(e);return s?`?placeId=${encodeURIComponent(s.placeId)}`:""}function Ce(e){return`/api/assets/${encodeURIComponent(e.scope)}/${encodeURIComponent(e.category)}`}function ce(e,s){return`${Ce(e)}/${encodeURIComponent(s)}`}async function Ot(e){return $.get(Ce(e),tt(e))}async function Ft(e){return $.post(`${Ce(e)}/rescan${ae(e)}`,{})}async function Mt(e,s,i){return(await $.patch(`${ce(e,s)}${ae(e)}`,i)).asset}async function Ht(e,s){return $.delete(`${ce(e,s)}${ae(e)}`)}async function Kt(e,s,i){return(await $.post(`${ce(e,s)}/upload${ae(e)}`,i)).asset}async function Oe(e,s){return(await $.post(`${ce(e,s)}/status-refresh${ae(e)}`,{})).asset}async function Gt(e,s,i){const n={...e,placeId:i??e.placeId};return $.post(`${ce(e,s)}/usage-scan${ae(n)}`,{})}async function zt(e,s){return $.post(`${Ce(e)}/export-selection-rbxm${ae(e)}`,s)}async function Wt(e,s,i){return $.post(`${ce(e,s)}/import-rbxm${ae(e)}`,i)}async function Vt(e,s){return(await $.post(`${ce(e,s)}/thumbnail-generate${ae(e)}`,{})).asset}function st(e){return e.fileUrl?`${ve}${e.fileUrl}`:`${ve}/api/assets/${e.scope.kind}/${e.category}/${encodeURIComponent(e.id)}/file${ae({scope:e.scope.kind,placeId:e.scope.kind==="place"?e.scope.placeId:void 0})}`}function at(e){return e.previewUrl?`${ve}${e.previewUrl}`:`${ve}/api/assets/${e.scope.kind}/${e.category}/${encodeURIComponent(e.id)}/preview${ae({scope:e.scope.kind,placeId:e.scope.kind==="place"?e.scope.placeId:void 0})}`}const nt=["all","image","decal","rbxm"],Yt=new Set(nt),Fe=["model","animation"];function ye(e){return/\.(rbxm|rbxmx)$/i.test(e.file.original)}function Xt(e){return Yt.has(e)}function Le(e,s){return e==="all"?s("assets.category.all","All"):s(`assets.category.${e}`,e==="rbxm"?"RBXM":e)}function ie(e,s){return Le(ye(e)?"rbxm":e.category,s)}function Me(e){return e==="all"?["image","decal",...Fe]:e==="rbxm"?Fe:[e]}function qt(e,s){return s==="all"?e.category==="image"||e.category==="decal"||ye(e):s==="rbxm"?ye(e):(s==="model"||s==="animation")&&ye(e)?!1:e.category===s}function Zt(e){return[...e].sort((s,i)=>i.createdAt.localeCompare(s.createdAt)||i.id.localeCompare(s.id))}const Jt="_page_u8a6t_1",Qt="_experimentalBadge_u8a6t_9",es="_toolbarShell_u8a6t_23",ts="_toolbar_u8a6t_23",ss="_segmented_u8a6t_39",as="_placeSelectorLabel_u8a6t_43",ns="_listContextSummary_u8a6t_47",os="_toolbarActions_u8a6t_53",rs="_categoryControl_u8a6t_58",ls="_contextDivider_u8a6t_80",is="_categoryControlLabel_u8a6t_84",cs="_categoryRail_u8a6t_90",ds="_categoryButton_u8a6t_98",us="_categoryButtonActive_u8a6t_127",ps="_copyRow_u8a6t_140",ms="_buttonRow_u8a6t_141",hs="_segmentedActive_u8a6t_183",xs="_placeSelect_u8a6t_43",gs="_commandButton_u8a6t_231",bs="_primaryButton_u8a6t_232",fs="_iconButton_u8a6t_233",ys="_dangerButton_u8a6t_273",js="_iconButtonActive_u8a6t_294",vs="_grid_u8a6t_307",Cs="_assetCard_u8a6t_313",_s="_assetCardSelected_u8a6t_327",Ss="_thumbnailWrap_u8a6t_332",Is="_thumbnail_u8a6t_332",Ns="_thumbnailFallback_u8a6t_348",As="_assetCardBody_u8a6t_359",Ps="_assetName_u8a6t_366",ks="_assetMeta_u8a6t_374",Rs="_statusChip_u8a6t_381",$s="_categoryPill_u8a6t_382",ws="_assetId_u8a6t_387",Ls="_scopeText_u8a6t_388",Bs="_muted_u8a6t_389",Us="_emptyState_u8a6t_394",Ds="_notice_u8a6t_395",Es="_errorState_u8a6t_396",Ts="_messageState_u8a6t_397",Os="_proNotice_u8a6t_427",Fs="_rbxmGuide_u8a6t_443",Ms="_settingsInlinePanel_u8a6t_483",Hs="_settingsDrawer_u8a6t_503",Ks="_detailPopupLayer_u8a6t_519",Gs="_detailDialog_u8a6t_535",zs="_detailDialogHeader_u8a6t_552",Ws="_detailTitleBlock_u8a6t_563",Vs="_detailEyebrow_u8a6t_585",Ys="_detailHeaderActions_u8a6t_594",Xs="_detailDialogBody_u8a6t_602",qs="_detailPreviewPane_u8a6t_611",Zs="_detailPreview_u8a6t_611",Js="_detailPreviewFallback_u8a6t_623",Qs="_detailContentPane_u8a6t_659",ea="_formStack_u8a6t_665",ta="_drawerHeader_u8a6t_669",sa="_detailSection_u8a6t_720",aa="_noticeList_u8a6t_721",na="_settingsPanel_u8a6t_722",oa="_setupNotice_u8a6t_739",ra="_field_u8a6t_764",la="_fieldLabelRow_u8a6t_772",ia="_fieldHelp_u8a6t_796",ca="_twoColumn_u8a6t_801",da="_technicalDetails_u8a6t_812",ua="_detailGrid_u8a6t_829",pa="_metadataList_u8a6t_830",ma="_compactMeta_u8a6t_841",ha="_copyableValue_u8a6t_868",xa="_inlineCopyButton_u8a6t_879",ga="_hashText_u8a6t_900",ba="_usageList_u8a6t_904",fa="_usageItem_u8a6t_910",ya="_metadataItem_u8a6t_911",ja="_settingsSubsection_u8a6t_959",va="_settingsSectionHeader_u8a6t_964",Ca="_settingsDefinitionList_u8a6t_977",_a="_toggleRow_u8a6t_999",Sa="_inlineHelp_u8a6t_1013",a={page:Jt,experimentalBadge:Qt,toolbarShell:es,toolbar:ts,segmented:ss,placeSelectorLabel:as,listContextSummary:ns,toolbarActions:os,categoryControl:rs,contextDivider:ls,categoryControlLabel:is,categoryRail:cs,categoryButton:ds,categoryButtonActive:us,copyRow:ps,buttonRow:ms,segmentedActive:hs,placeSelect:xs,commandButton:gs,primaryButton:bs,iconButton:fs,dangerButton:ys,iconButtonActive:js,grid:vs,assetCard:Cs,assetCardSelected:_s,thumbnailWrap:Ss,thumbnail:Is,thumbnailFallback:Ns,assetCardBody:As,assetName:Ps,assetMeta:ks,statusChip:Rs,categoryPill:$s,assetId:ws,scopeText:Ls,muted:Bs,emptyState:Us,notice:Ds,errorState:Es,messageState:Ts,proNotice:Os,rbxmGuide:Fs,settingsInlinePanel:Ms,settingsDrawer:Hs,detailPopupLayer:Ks,detailDialog:Gs,detailDialogHeader:zs,detailTitleBlock:Ws,detailEyebrow:Vs,detailHeaderActions:Ys,detailDialogBody:Xs,detailPreviewPane:qs,detailPreview:Zs,detailPreviewFallback:Js,detailContentPane:Qs,formStack:ea,drawerHeader:ta,detailSection:sa,noticeList:aa,settingsPanel:na,setupNotice:oa,field:ra,fieldLabelRow:la,fieldHelp:ia,twoColumn:ca,technicalDetails:da,detailGrid:ua,metadataList:pa,compactMeta:ma,copyableValue:ha,inlineCopyButton:xa,hashText:ga,usageList:ba,usageItem:fa,metadataItem:ya,settingsSubsection:ja,settingsSectionHeader:va,settingsDefinitionList:Ca,toggleRow:_a,inlineHelp:Sa},Ia={image:mt,decal:Nt,audio:St,mesh:Pt,model:pt,video:wt,animation:Rt};function Be(e,s){return s(`assets.status.${e}`,e)}function Na(e){switch(e){case"uploaded":return"success";case"failed":return"error";case"processing":case"uploading":return"warning";case"localOnly":case"superseded":default:return"neutral"}}function Aa(e){return e.category==="image"||e.category==="decal"||!!e.file.preview}function Pa(e){return e.category==="decal"?e.roblox.creatorAssetId??e.roblox.assetId:e.roblox.assetId}function ot(e,s){var y;const i=((y=e.rbxm)==null?void 0:y.studioUploads)??[];if(i.length===0)return null;const n=i.filter(_=>_.status==="uploaded").length,l=i.filter(_=>_.status==="failed").length,N=[n>0?`${n} ${s("assets.detail.rbxmStudioUploadsUploaded","uploaded")}`:null,l>0?`${l} ${s("assets.detail.rbxmStudioUploadsFailed","failed")}`:null].filter(Boolean);return`${s("assets.detail.rbxmStudioUploadsLabel","Studio uploads")}: ${N.join(", ")}`}function ka({assets:e,selectedAssetId:s,onSelect:i}){const{t:n}=me();return e.length===0?t.jsxs("div",{className:a.emptyState,children:[t.jsx("p",{children:n("assets.empty.title","No assets yet")}),t.jsx("span",{children:n("assets.empty.body","Choose a scope and category, then rescan that inbox folder.")})]}):t.jsx("div",{className:a.grid,children:e.map(l=>{const N=Ia[l.category],y=Pa(l),_=ot(l,n);return t.jsxs("button",{type:"button",className:[a.assetCard,s===l.id?a.assetCardSelected:""].filter(Boolean).join(" "),onClick:()=>i(l.id),children:[t.jsx("span",{className:a.thumbnailWrap,children:Aa(l)?t.jsx("img",{className:a.thumbnail,src:at(l),alt:l.displayName,loading:"lazy"}):t.jsx("span",{className:a.thumbnailFallback,"aria-hidden":"true",children:t.jsx(N,{size:30})})}),t.jsxs("span",{className:a.assetCardBody,children:[t.jsx("span",{className:a.assetName,children:l.displayName}),t.jsxs("span",{className:a.assetMeta,children:[t.jsx(Ee,{variant:"neutral",className:a.categoryPill,children:ie(l,n)}),t.jsx(Ee,{variant:Na(l.status),className:a.statusChip,children:Be(l.status,n)})]}),t.jsxs("span",{className:a.assetMeta,children:[t.jsx("span",{className:a.scopeText,children:l.scope.kind==="shared"?n("assets.scope.shared","Shared"):n("assets.scope.place","Current Place")}),t.jsx("span",{className:a.assetId,children:y?`#${y}`:_??n("assets.status.localOnly","Local only")})]})]})]},l.id)})})}const Ra="https://create.roblox.com/dashboard/creations/store",$a=/^https:\/\/create\.roblox\.com\/store\/asset\/\d+(?:\/.*)?$/;function wa(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function je(e){const s=new Date(e);if(Number.isNaN(s.getTime()))return e;const i=s.getFullYear(),n=String(s.getMonth()+1).padStart(2,"0"),l=String(s.getDate()).padStart(2,"0"),N=String(s.getHours()).padStart(2,"0"),y=String(s.getMinutes()).padStart(2,"0");return`${i}-${n}-${l} ${N}:${y}`}function La(e){return e.category==="image"||e.category==="decal"||!!e.file.preview}function Ba(e){return e.file.preview?at(e):st(e)}function Ua(e){var i;const s=Object.entries(((i=e.rbxm)==null?void 0:i.classCounts)??{}).sort((n,l)=>l[1]-n[1]).slice(0,8);return s.length===0?"-":s.map(([n,l])=>`${n} ${l}`).join(", ")}function He(e){var l;const s=(l=e.rbxm)==null?void 0:l.thumbnail;if(!s)return"-";const i=s.source?` via ${s.source}`:"",n=s.message?` · ${s.message}`:"";return`${s.status}${i}${n}`}function Da(e){var l,N;const s=(N=(l=e.rbxm)==null?void 0:l.review)==null?void 0:N.summary;if(!s)return"-";const i=[["roots",s.rootCount],["parts",s.partCount],["mesh parts",s.meshPartCount],["scripts",s.scriptCount],["unanchored",s.unanchoredPartCount]].flatMap(([y,_])=>typeof _=="number"?[`${y} ${_}`]:[]),n=s.bounds;if(n&&typeof n=="object"&&"size"in n){const y=n.size;if(y&&typeof y=="object"){const{x:_,y:p,z:E}=y;typeof _=="number"&&typeof p=="number"&&typeof E=="number"&&i.push(`bounds ${_} x ${p} x ${E}`)}}return i.length>0?i.join(", "):"-"}function Ea(e){var i,n;const s=(i=e.rbxm)==null?void 0:i.generation;return s?s.schemaMode==="custom"&&((n=s.schemaGroups)!=null&&n.length)?`custom · ${s.schemaGroups.join(", ")}`:s.predefinedSchema?`${s.schemaMode??"predefined"} · ${s.predefinedSchema}`:s.schemaMode??"-":"-"}function Ke(e){const{width:s,height:i}=e.file;return s===null||i===null?null:`${s} x ${i}px`}function Ge(e){const{durationMs:s}=e.file;return s===null?null:s<1e3?`${s} ms`:`${(s/1e3).toFixed(1)} s`}function Ta(e){return`${Ra}/${e}/configure`}function Oa(e){return e.category==="decal"?e.roblox.creatorAssetId??e.roblox.assetId??null:e.roblox.assetId??null}function Fa(e){const s=Oa(e),i=s?Ta(s):null,n=e.category==="decal"?e.roblox.creatorAssetWebUrl??e.roblox.assetWebUrl:e.roblox.assetWebUrl;return!n||i&&$a.test(n)?i:n}function Ma(e){return`${je(e.startedAt)} -> ${e.status}`}function ze(e){return!e.creatorType||!e.creatorId?null:`${e.creatorType} ${e.creatorId}`}function We(e){return e.assetRole?`Asset role: ${e.assetRole}`:null}function Ha(e){const s=e.sourceProperty?` · ${e.sourceProperty}`:"";return`${e.path} · ${e.assetType} · ${e.status}${s}`}function Ka(e){return e.assetUri&&e.assetId?`${e.assetUri} (#${e.assetId})`:e.assetUri?e.assetUri:e.assetId?`#${e.assetId}`:e.message??"-"}function fe({label:e,value:s}){return s?t.jsx("button",{type:"button",className:a.inlineCopyButton,"aria-label":e,title:e,onClick:()=>{var i;return void((i=navigator.clipboard)==null?void 0:i.writeText(s))},children:t.jsx(et,{size:13})}):null}function Ga({asset:e,busyAction:s,canUpload:i,canImportRbxm:n,importRbxmTooltip:l,importRbxmTargetParent:N,onClose:y,onSave:_,onUpload:p,onDelete:E,onImportRbxm:Y,onRefreshStatus:T,onScanUsage:x}){var P,g;const{t:o}=me(),X=c.useRef(null),[z,W]=c.useState(""),[H,Z]=c.useState("");if(c.useEffect(()=>{W((e==null?void 0:e.displayName)??""),Z((e==null?void 0:e.description)??"")},[e==null?void 0:e.description,e==null?void 0:e.displayName,e==null?void 0:e.id]),c.useEffect(()=>{var C;if(!e)return;(C=X.current)==null||C.focus();const r=te=>{te.key==="Escape"&&y()};return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[e,y]),!e)return null;const O=e.status==="processing"&&!!(e.roblox.operationId??e.roblox.operationPath),Q=!!e.roblox.assetUri,B=Fa(e),ee=e.roblox.uploadAttempts??[],F=e.category==="decal"&&!!(e.roblox.creatorAssetId||e.roblox.backingImageAssetId||e.roblox.assetId),v=e.roblox.creatorAssetId??e.roblox.assetId,b=e.roblox.backingImageAssetId??e.roblox.assetId,A=ot(e,o),w=e.roblox.assetId?e.usage.lastScannedAt?o("assets.detail.noUsageAfterScan","No references were found in local Sync files during the last check."):o("assets.detail.noUsageUnscanned","Run Scan usage to search local Sync files for this Roblox Asset ID."):o("assets.detail.noUsageNoRobloxId","This asset does not have a Roblox Asset ID yet, so usage cannot be checked. Upload it before scanning usage.");return t.jsx("div",{className:a.detailPopupLayer,onClick:y,role:"presentation",children:t.jsxs("section",{ref:X,className:a.detailDialog,role:"dialog","aria-modal":"true","aria-label":o("assets.detail.title","Asset details"),tabIndex:-1,onClick:r=>r.stopPropagation(),children:[t.jsxs("div",{className:a.detailDialogHeader,children:[t.jsxs("div",{className:a.detailTitleBlock,children:[t.jsxs("span",{className:a.detailEyebrow,children:[ie(e,o)," · ",Be(e.status,o)]}),t.jsx("h2",{children:e.displayName}),t.jsx("span",{children:e.id})]}),t.jsxs("div",{className:a.detailHeaderActions,children:[t.jsx(G,{text:i?o("assets.upload.open.tooltip","Upload this local file to Roblox through Open Cloud."):o("assets.proOnly.tooltip","Roblox upload is available on Pro."),children:t.jsxs("button",{type:"button",className:a.commandButton,disabled:!i,onClick:p,children:[t.jsx(Tt,{size:15}),o("assets.upload.open","Upload")]})}),n&&t.jsx(G,{text:l,children:t.jsxs("button",{type:"button",className:a.commandButton,disabled:s==="import-rbxm",onClick:()=>void Y(),children:[t.jsx(ht,{size:15}),o("assets.detail.importRbxm","Insert into Studio")]})}),t.jsxs("button",{type:"button",className:a.commandButton,disabled:!O||s==="status-refresh",onClick:()=>void T(),children:[t.jsx(Ze,{size:15}),o("assets.detail.refreshStatus","Refresh")]}),t.jsxs("button",{type:"button",className:a.commandButton,disabled:!e.roblox.assetId||s==="usage-scan",onClick:()=>void x(),children:[t.jsx(Bt,{size:15}),o("assets.detail.scanUsage","Scan usage")]}),t.jsx(G,{text:o("assets.delete.tooltip","Delete this local Asset Library item."),children:t.jsxs("button",{type:"button",className:`${a.commandButton} ${a.dangerButton}`,disabled:s==="delete",onClick:E,children:[t.jsx(Dt,{size:15}),o("common.delete","Delete")]})}),t.jsx(G,{text:o("common.close","Close"),children:t.jsx("button",{type:"button",className:a.iconButton,onClick:y,"aria-label":o("common.close","Close"),children:t.jsx(Ue,{size:16})})})]})]}),t.jsxs("div",{className:a.detailDialogBody,children:[t.jsx("div",{className:a.detailPreviewPane,children:La(e)?t.jsx("img",{className:a.detailPreview,src:Ba(e),alt:e.displayName}):t.jsxs("div",{className:a.detailPreviewFallback,children:[t.jsx("span",{children:ie(e,o)}),t.jsx("code",{children:e.file.original}),((P=e.rbxm)==null?void 0:P.thumbnail)&&t.jsx("small",{children:He(e)})]})}),t.jsxs("div",{className:a.detailContentPane,children:[t.jsxs("div",{className:a.formStack,children:[t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:o("assets.detail.displayName","Display name")}),t.jsx("input",{value:z,onChange:r=>W(r.target.value)})]}),t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:o("assets.detail.description","Description")}),t.jsx("textarea",{value:H,rows:3,onChange:r=>Z(r.target.value)})]}),t.jsx("button",{type:"button",className:a.primaryButton,disabled:s==="update",onClick:()=>void _(z,H),children:o("assets.detail.save","Save metadata")})]}),t.jsxs("section",{className:a.detailSection,children:[t.jsx("h3",{children:o("assets.detail.localFile","Local file")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.fileName","File")}),t.jsx("dd",{children:e.file.original}),t.jsx("dt",{children:o("assets.detail.source","Source path")}),t.jsx("dd",{children:e.source.originalPath}),t.jsx("dt",{children:o("assets.detail.category","Category")}),t.jsx("dd",{children:ie(e,o)}),t.jsx("dt",{children:o("assets.detail.scope","Scope")}),t.jsx("dd",{children:e.scope.kind==="shared"?o("assets.scope.shared","Shared"):o("assets.scope.place","Current Place")}),t.jsx("dt",{children:o("assets.detail.mimeType","Type")}),t.jsx("dd",{children:e.file.mimeType}),t.jsx("dt",{children:o("assets.detail.size","Size")}),t.jsx("dd",{children:wa(e.file.sizeBytes)}),Ke(e)&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.dimensions","Dimensions")}),t.jsx("dd",{children:Ke(e)})]}),Ge(e)&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.duration","Duration")}),t.jsx("dd",{children:Ge(e)})]})]})]}),e.rbxm&&t.jsxs("section",{className:a.detailSection,children:[t.jsx("h3",{children:o("assets.detail.rbxm","RBXM contents")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.rbxmExportedCount","Exported roots")}),t.jsx("dd",{children:e.rbxm.exportedCount}),t.jsx("dt",{children:o("assets.detail.rbxmClasses","Classes")}),t.jsx("dd",{children:Ua(e)}),t.jsx("dt",{children:o("assets.detail.rbxmThumbnail","Thumbnail")}),t.jsx("dd",{children:He(e)}),A&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.rbxmStudioUploadsLabel","Studio uploads")}),t.jsx("dd",{children:A})]}),n&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.studioInsertTarget","Studio insert target")}),t.jsx("dd",{children:N})]})]}),e.rbxm.roots.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmRoots","Root tree")}),e.rbxm.roots.map(r=>t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("span",{children:[r.name," (",r.className,")"]}),t.jsx("code",{children:r.path})]},`${r.path}-${r.className}`))]}),e.rbxm.resourceReferences.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmReferences","Asset references")}),e.rbxm.resourceReferences.map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("span",{children:[r.path," · ",r.property]}),t.jsx("code",{children:r.assetId?`${r.value} (#${r.assetId})`:r.value})]},`${r.path}-${r.property}-${C}`))]}),e.rbxm.studioUploads&&e.rbxm.studioUploads.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmStudioUploads","Embedded Studio uploads")}),e.rbxm.studioUploads.map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:Ha(r)}),t.jsx("code",{children:Ka(r)})]},`${r.path}-${r.assetType}-${r.sourceProperty??""}-${C}`))]}),e.rbxm.generation&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmGeneration","Generated model")}),t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmGenerationProvider","Provider")}),t.jsx("code",{children:e.rbxm.generation.provider})]}),e.rbxm.generation.prompt&&t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmGenerationPrompt","Prompt")}),t.jsx("code",{children:e.rbxm.generation.prompt})]}),t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmGenerationSchema","Schema")}),t.jsx("code",{children:Ea(e)})]}),e.rbxm.generation.path&&t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmGenerationPath","Studio path")}),t.jsx("code",{children:e.rbxm.generation.path})]})]}),e.rbxm.review&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmReview","Model review")}),t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmReviewReadiness","Readiness")}),t.jsx("code",{children:e.rbxm.review.readiness})]}),t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmReviewSummary","Summary")}),t.jsx("code",{children:Da(e)})]}),e.rbxm.review.findings.slice(0,8).map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("span",{children:[r.severity," · ",r.category," · ",r.code]}),t.jsx("code",{children:r.path?`${r.path}: ${r.message}`:r.message})]},`${r.code}-${r.path}-${C}`))]})]}),t.jsxs("section",{className:a.detailSection,children:[t.jsx("h3",{children:o("assets.detail.roblox","Roblox upload status")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.status","Status")}),t.jsx("dd",{children:Be(e.status,o)}),F?t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.decalAssetId","Roblox Decal ID")}),t.jsxs("dd",{className:a.copyableValue,children:[t.jsx("span",{children:v??o("assets.status.localOnly","Local only")}),t.jsx(fe,{label:o("assets.detail.copyDecalAssetId","Copy Roblox Decal ID"),value:v})]}),t.jsx("dt",{children:o("assets.detail.studioTextureImageId","Studio Texture Image ID")}),t.jsxs("dd",{className:a.copyableValue,children:[t.jsx("span",{children:b??"-"}),t.jsx(fe,{label:o("assets.detail.copyStudioTextureImageId","Copy Studio Texture Image ID"),value:b})]})]}):t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.assetId","Asset ID")}),t.jsxs("dd",{className:a.copyableValue,children:[t.jsx("span",{children:e.roblox.assetId??o("assets.status.localOnly","Local only")}),t.jsx(fe,{label:o("assets.detail.copyAssetId","Copy Asset ID"),value:e.roblox.assetId})]})]}),t.jsx("dt",{children:o("assets.detail.studioUri","Studio URI")}),t.jsx("dd",{children:e.roblox.assetUri??"-"}),t.jsx("dt",{children:o("assets.detail.robloxWebUrl","Creator Dashboard URL")}),t.jsxs("dd",{className:a.copyableValue,children:[t.jsx("span",{children:B??"-"}),t.jsx(fe,{label:o("assets.detail.copyWebUrl","Copy configure URL"),value:B})]}),e.roblox.errorMessage&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.error","Error")}),t.jsx("dd",{children:e.roblox.errorMessage})]})]}),t.jsxs("div",{className:a.copyRow,children:[t.jsxs("button",{type:"button",className:a.commandButton,disabled:!Q,onClick:()=>{var r;return e.roblox.assetUri&&void((r=navigator.clipboard)==null?void 0:r.writeText(e.roblox.assetUri))},children:[t.jsx(et,{size:15}),o("assets.detail.copyStudioUri","Copy Studio URI")]}),B&&t.jsxs("a",{className:a.commandButton,href:B,target:"_blank",rel:"noreferrer",children:[t.jsx(xt,{size:15}),o("assets.detail.openRobloxPage","Open configure page")]})]}),e.roblox.assetId&&t.jsx("p",{className:a.muted,children:o("assets.detail.robloxWebUrlNotice","Opening this page requires the Roblox account that owns or can manage the uploaded asset.")}),ee.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.uploadHistory","Upload history")}),ee.slice().reverse().map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:Ma(r)}),ze(r)&&t.jsx("code",{children:ze(r)}),We(r)&&t.jsx("code",{children:We(r)}),r.operationPath&&t.jsx("code",{children:r.operationPath}),r.assetId&&t.jsxs("code",{children:[o("assets.detail.assetId","Asset ID"),": ",r.assetId]}),r.remotePath&&t.jsx("code",{children:r.remotePath}),r.message&&t.jsx("code",{children:r.message}),r.errorMessage&&t.jsx("code",{children:r.errorMessage})]},`${r.startedAt}-${r.operationPath??C}`))]})]}),t.jsxs("section",{className:a.detailSection,children:[t.jsx("h3",{children:o("assets.detail.usedInPlace","Where this asset is used in this Place")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.usageSource","Checked against")}),t.jsx("dd",{children:e.usage.scanSource==="localSync"?o("assets.detail.usageSource.localSync","Local Sync files"):o("assets.detail.usageSource.notScanned","Not checked yet")}),t.jsx("dt",{children:o("assets.detail.lastScanned","Last checked")}),t.jsx("dd",{children:e.usage.lastScannedAt?o("assets.detail.lastScannedAt","Last checked: {time}").replace("{time}",je(e.usage.lastScannedAt)):o("assets.detail.lastScanned.never","No check yet")})]}),e.usage.references.length===0?t.jsx("p",{className:a.muted,children:w}):t.jsx("div",{className:a.usageList,children:e.usage.references.map((r,C)=>t.jsxs("div",{className:a.usageItem,children:[t.jsx("strong",{children:r.kind==="property"?r.instancePath:r.filePath}),t.jsx("span",{children:r.property??o("assets.detail.line","line {line}").replace("{line}",String(r.line??"-"))}),t.jsx("code",{children:r.value})]},`${r.kind}-${C}`))})]}),t.jsxs("details",{className:a.technicalDetails,children:[t.jsx("summary",{children:o("assets.detail.technicalDetails","Technical details")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.stableId","Stable ID")}),t.jsx("dd",{className:a.hashText,children:e.id}),t.jsx("dt",{children:o("assets.detail.sourceKind","Source kind")}),t.jsx("dd",{children:e.source.kind}),t.jsx("dt",{children:o("assets.detail.sha256","SHA-256")}),t.jsx("dd",{className:a.hashText,children:e.file.sha256}),t.jsx("dt",{children:o("assets.detail.createdAt","Created")}),t.jsx("dd",{children:je(e.createdAt)}),t.jsx("dt",{children:o("assets.detail.updatedAt","Updated")}),t.jsx("dd",{children:je(e.updatedAt)}),e.roblox.operationId&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.operationId","Operation ID")}),t.jsx("dd",{className:a.hashText,children:e.roblox.operationId})]}),e.roblox.operationPath&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.operationPath","Operation path")}),t.jsx("dd",{className:a.hashText,children:e.roblox.operationPath})]}),e.roblox.versionId&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.versionId","Version ID")}),t.jsx("dd",{className:a.hashText,children:e.roblox.versionId})]}),e.roblox.remotePath&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.remotePath","Remote path")}),t.jsx("dd",{className:a.hashText,children:e.roblox.remotePath})]}),e.roblox.moderationState&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.moderationState","Moderation")}),t.jsx("dd",{children:e.roblox.moderationState})]})]}),((g=e.rbxm)==null?void 0:g.thumbnail.attempts)&&e.rbxm.thumbnail.attempts.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmThumbnailAttempts","Thumbnail attempts")}),e.rbxm.thumbnail.attempts.map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("span",{children:[r.method," · ",r.status]}),r.message&&t.jsx("code",{children:r.message})]},`${r.method}-${C}`))]})]})]})]})]})})}function rt(e){return{assetUploadByOpenCloudEnabled:e.hot.ENABLE_ASSET_UPLOAD_BY_OPEN_CLOUD===!0}}function za(e){const s={};return typeof e.assetUploadByOpenCloudEnabled=="boolean"&&(s.ENABLE_ASSET_UPLOAD_BY_OPEN_CLOUD=e.assetUploadByOpenCloudEnabled),s}async function lt(){const e=await $.get("/api/dashboard/settings");return rt(e)}async function Wa(e){const s=await $.patch("/api/dashboard/settings",za(e));return rt(s)}async function it(){return $.get("/api/dashboard/open-cloud/credential-profiles")}async function Va(e){return $.post("/api/dashboard/open-cloud/credential-profiles",e)}async function Ya(e){return $.patch("/api/dashboard/open-cloud/credential-profiles/active",{profileId:e})}async function Xa(e,s){return $.put(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/api-key`,s)}async function qa(e){return $.delete(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}`)}async function Za(e,s){return $.post(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/creators`,s)}async function Ja(e,s){return $.patch(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/creators/${encodeURIComponent(s)}/default`,{})}async function Qa(e,s){return $.delete(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/creators/${encodeURIComponent(s)}`)}async function en(e,s){return $.post(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/test`,s?{creatorPresetId:s}:{})}async function tn(e){return $.post("/api/dashboard/open-cloud/credential/test",e?{apiKey:e}:{})}function sn(e){return e.category==="image"||e.category==="decal"}function an(e,s){return e==="group"?s("assets.creator.group","Group"):s("assets.creator.user","User")}function nn(e,s){return`${e.label} · ${an(e.creatorType,s)} ${e.creatorId}`}function Ve(e){if(!e)return null;if(e.defaultCreatorId){const s=e.creators.find(i=>i.id===e.defaultCreatorId);if(s)return s}return e.creators[0]??null}function on({asset:e,open:s,canUpload:i,busyAction:n,onClose:l,onBack:N,onOpenSettings:y,onUpload:_}){const{t:p}=me(),E=c.useRef(null),[Y,T]=c.useState(null),[x,o]=c.useState(null),[X,z]=c.useState(!1),[W,H]=c.useState(null),[Z,O]=c.useState(""),[Q,B]=c.useState(""),[ee,F]=c.useState(""),[v,b]=c.useState("user"),[A,w]=c.useState("");if(c.useEffect(()=>{O((e==null?void 0:e.displayName)??""),B((e==null?void 0:e.description)??"")},[e==null?void 0:e.description,e==null?void 0:e.displayName,e==null?void 0:e.id]),c.useEffect(()=>{if(!s)return;let h=!1;return z(!0),H(null),(async()=>{try{const[L,D]=await Promise.all([lt(),it()]);if(h)return;T(L);const M=D.profiles.find(de=>de.id===D.activeProfileId)??D.profiles[0]??null;o(M);const J=Ve(M);F((J==null?void 0:J.id)??""),b((J==null?void 0:J.creatorType)??"user"),w((J==null?void 0:J.creatorId)??"")}catch(L){if(h)return;H(L instanceof Error?L.message:p("assets.upload.settingsLoadFailed","Failed to load upload settings.")),T(null),o(null)}finally{h||z(!1)}})(),()=>{h=!0}},[s,p]),c.useEffect(()=>{var L;if(!s||!e)return;(L=E.current)==null||L.focus();const h=D=>{D.key==="Escape"&&l()};return document.addEventListener("keydown",h),()=>document.removeEventListener("keydown",h)},[e,l,s]),!s||!e)return null;const P=(Y==null?void 0:Y.assetUploadByOpenCloudEnabled)===!0,g=!!x,r=Ve(x),C=(x==null?void 0:x.creators.find(h=>h.id===ee))??null,te=!!r,U=(x==null?void 0:x.storageProvider)==="env"&&g&&!te,K=U&&A.trim().length>0,m=i&&!X&&!W&&(!P||!g||!te&&!U),se=i&&!X&&!W&&P&&g&&(te||K)&&n!=="upload";return t.jsx("div",{className:a.detailPopupLayer,onClick:l,role:"presentation",children:t.jsxs("section",{ref:E,className:a.detailDialog,role:"dialog","aria-modal":"true","aria-label":p("assets.upload.title","Upload asset"),tabIndex:-1,onClick:h=>h.stopPropagation(),children:[t.jsxs("div",{className:a.detailDialogHeader,children:[t.jsxs("div",{className:a.detailTitleBlock,children:[t.jsxs("span",{className:a.detailEyebrow,children:[ie(e,p)," · ",p("assets.upload.intent","Upload to Roblox")]}),t.jsx("h2",{children:p("assets.upload.title","Upload asset")}),t.jsx("span",{children:e.displayName})]}),t.jsxs("div",{className:a.detailHeaderActions,children:[t.jsxs("button",{type:"button",className:a.commandButton,onClick:N,children:[t.jsx(Ct,{size:15}),p("assets.upload.backToDetails","Back to details")]}),t.jsx(G,{text:p("common.close","Close"),children:t.jsx("button",{type:"button",className:a.iconButton,onClick:l,"aria-label":p("common.close","Close"),children:t.jsx(Ue,{size:16})})})]})]}),t.jsxs("div",{className:a.detailDialogBody,children:[t.jsx("div",{className:a.detailPreviewPane,children:sn(e)?t.jsx("img",{className:a.detailPreview,src:st(e),alt:e.displayName}):t.jsxs("div",{className:a.detailPreviewFallback,children:[t.jsx("span",{children:ie(e,p)}),t.jsx("code",{children:e.file.original})]})}),t.jsxs("div",{className:a.detailContentPane,children:[!i&&t.jsx("div",{className:a.notice,children:p("assets.proOnly.upload","Roblox upload is available on Pro.")}),X&&t.jsx("div",{className:a.notice,children:p("assets.upload.checkingSettings","Checking upload settings...")}),W&&t.jsx("div",{className:a.errorState,children:W}),t.jsxs("dl",{className:a.compactMeta,children:[t.jsx("dt",{children:p("assets.detail.category","Category")}),t.jsx("dd",{children:ie(e,p)}),t.jsx("dt",{children:p("assets.detail.source","Source")}),t.jsx("dd",{children:e.source.originalPath})]}),m&&t.jsxs("div",{className:a.setupNotice,children:[t.jsx("strong",{children:p("assets.upload.settingsRequired","Upload settings required")}),t.jsx("p",{children:g?P?p("assets.upload.settingsRequired.creator","Save a default Creator before uploading."):p("assets.upload.settingsRequired.toggle","Enable Open Cloud upload before uploading."):p("assets.upload.settingsRequired.apiKey","Save an Open Cloud API key before uploading.")}),t.jsxs("button",{type:"button",className:a.commandButton,onClick:y,children:[t.jsx(Je,{size:15}),p("assets.upload.openSettings","Open Asset Library settings")]})]}),t.jsxs("div",{className:a.formStack,children:[t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.detail.displayName","Display name")}),t.jsx("input",{value:Z,disabled:!i,onChange:h=>O(h.target.value)}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.displayNameHelp","Saved to Roblox as the asset display name.")})]}),t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.detail.description","Description")}),t.jsx("textarea",{value:Q,rows:3,disabled:!i,onChange:h=>B(h.target.value)}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.descriptionHelp","Saved to Roblox as the asset description.")})]}),te&&t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.upload.creator","Creator")}),t.jsx("select",{"aria-label":p("assets.upload.creator","Creator"),value:ee,disabled:!i||X,onChange:h=>F(h.target.value),children:x==null?void 0:x.creators.map(h=>t.jsx("option",{value:h.id,children:nn(h,p)},h.id))}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.creatorHelp","Used by Open Cloud as the owner of the uploaded asset.")})]}),U&&t.jsxs(t.Fragment,{children:[t.jsx("p",{className:a.inlineHelp,children:p("assets.upload.envCreatorHelp","Environment API keys cannot save a default Creator here. Enter the Creator for this upload.")}),t.jsxs("div",{className:a.twoColumn,children:[t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.upload.creatorType","Creator type")}),t.jsxs("select",{value:v,disabled:!i,onChange:h=>b(h.target.value),children:[t.jsx("option",{value:"user",children:p("assets.creator.user","User")}),t.jsx("option",{value:"group",children:p("assets.creator.group","Group")})]}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.creatorTypeHelp","Sent to Open Cloud as the Creator type.")})]}),t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.upload.creatorId","Creator ID")}),t.jsx("input",{value:A,disabled:!i,onChange:h=>w(h.target.value)}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.creatorIdHelp","Sent to Open Cloud as the User or Group ID that owns the uploaded asset.")})]})]})]}),t.jsx("button",{type:"button",className:a.primaryButton,disabled:!se,onClick:()=>{const h=A.trim(),L=U&&h?{creatorType:v,creatorId:h}:{},D=!U&&C&&r&&C.id!==r.id?{creatorType:C.creatorType,creatorId:C.creatorId}:{};_({displayName:Z,description:Q,...L,...D})},children:n==="upload"?p("assets.upload.uploading","Uploading..."):p("assets.upload.submit","Upload with Roblox Open Cloud")})]}),t.jsxs("div",{className:a.noticeList,children:[t.jsx("p",{children:p("assets.upload.noDelete","WEPPY does not provide Roblox asset deletion.")}),t.jsx("p",{children:p("assets.upload.delay","Roblox processing and moderation can delay visibility in Studio or Creator Dashboard.")})]})]})]})]})})}function Ye(e,s){return e==="env"?s("assets.settings.credential.env","Environment variable"):s("assets.settings.credential.local","Local encrypted file")}function ke(e,s){return e==="valid"?s("assets.settings.validation.valid","Connected"):e==="invalid"?s("assets.settings.validation.invalid","Needs attention"):s("assets.settings.validation.unknown","Not tested")}function rn(e,s){return(e==null?void 0:e.status)==="valid"?s("assets.settings.apiKeyTested","Open Cloud API key connection tested."):(e==null?void 0:e.message)??s("assets.settings.tested","Connection tested.")}function ln(e,s){return(e==null?void 0:e.status)==="valid"?s("assets.settings.apiKeyTested","Open Cloud API key connection tested."):(e==null?void 0:e.message)??s("assets.settings.tested","Connection tested.")}function cn(e,s){return e==="group"?s("assets.creator.group","Group"):s("assets.creator.user","User")}function dn(e,s){return`${cn(e.creatorType,s)} ${e.creatorId}`}function un({open:e,tier:s,onClose:i}){const{t:n}=me(),[l,N]=c.useState(null),[y,_]=c.useState(null),[p,E]=c.useState(""),[Y,T]=c.useState(!1),[x,o]=c.useState(""),[X,z]=c.useState(""),[W,H]=c.useState("user"),[Z,O]=c.useState(""),[Q,B]=c.useState(""),[ee,F]=c.useState(!0),[v,b]=c.useState(null),[A,w]=c.useState(null),[P,g]=c.useState(!1),r=s==="basic",C=c.useCallback(async()=>{g(!0),b(null);try{const[u,I]=await Promise.all([lt(),it()]);N(u),_(I);const R=I.profiles.find(re=>re.id===I.activeProfileId)??I.profiles[0]??null;E((R==null?void 0:R.id)??""),T(!R),F(!R||R.creators.length===0),H("user"),O(""),B("")}catch(u){b(u instanceof Error?u.message:n("assets.settings.loadFailed","Failed to load upload settings."))}finally{g(!1)}},[n]);if(c.useEffect(()=>{e&&C()},[C,e]),!e)return null;const te=(l==null?void 0:l.assetUploadByOpenCloudEnabled)===!0,q=X.trim(),U=Z.trim(),K=(y==null?void 0:y.profiles)??[],m=K.find(u=>u.id===p)??K[0]??null,se=!!m,h=se&&(m==null?void 0:m.storageProvider)==="localFile",L=se&&(m==null?void 0:m.storageProvider)==="env",D=m!=null&&m.defaultCreatorId?m.creators.find(u=>u.id===m.defaultCreatorId):m==null?void 0:m.creators[0],M=!!(m!=null&&m.creators.length),J=!M||ee,de=K.length>1,oe=r?n("assets.settings.action.proRequired","Asset upload settings are available on Pro."):P?n("assets.settings.action.busy","Wait for the current settings action to finish."):null,_e=r||P||!q,Se=oe??(q?n("assets.settings.saveApiKey.tooltip.ready","Save this API key to local encrypted storage."):n("assets.settings.saveApiKey.tooltip.enter","Enter an Open Cloud API key to save it locally.")),he=r||P||!q&&!se,xe=oe??(q?n("assets.settings.testConnection.tooltip.entered","Test the entered API key before saving it."):se?n("assets.settings.testConnection.tooltip.saved","Test the saved Open Cloud API key."):n("assets.settings.testConnection.tooltip.enterOrSaved","Enter an API key or save one before testing the connection.")),ge=r||P||!h,be=oe??(h?n("assets.settings.removeApiKey.tooltip.ready","Remove the locally saved Open Cloud API key."):L?n("assets.settings.removeApiKey.tooltip.env","Environment API keys cannot be removed from Dashboard. Remove ROBLOX_OPEN_CLOUD_API_KEY outside WEPPY."):n("assets.settings.removeApiKey.tooltip.none","No local Open Cloud API key is saved.")),Ie=r||P||!h||!U,Ne=oe??(L?n("assets.settings.saveCreator.tooltip.env","Environment API keys cannot save a default Creator here. Enter Creator details in the upload dialog."):h?U?n("assets.settings.saveCreator.tooltip.ready","Save this Creator as the default owner for uploads."):n("assets.settings.saveCreator.tooltip.enterId","Enter a user or group ID before saving the default Creator."):n("assets.settings.saveCreator.tooltip.noLocal","Save a local Open Cloud API key before saving a default Creator.")),Ae=oe??(h?n("assets.settings.addCreator.tooltip.ready","Add another User or Group Creator preset to this profile."):n("assets.settings.saveCreator.tooltip.noLocal","Save a local Open Cloud API key before saving a default Creator.")),d=r||P||L||!h,f=oe??(h?n("assets.settings.unregisterCreator.tooltip.ready","Unregister this Creator from the selected profile."):L?n("assets.settings.saveCreator.tooltip.env","Environment API keys cannot save a default Creator here. Enter Creator details in the upload dialog."):n("assets.settings.saveCreator.tooltip.noLocal","Save a local Open Cloud API key before saving a default Creator.")),j=D?n("assets.settings.saveCreatorPreset","Save Creator"):n("assets.settings.saveCreator","Save default Creator"),S=(m==null?void 0:m.label)??n("assets.settings.credential.none","No API key saved"),k=u=>{const I=u.profiles.find(R=>R.id===u.activeProfileId)??u.profiles[0]??null;_(u),E((I==null?void 0:I.id)??""),F(!I||I.creators.length===0),T(u.profiles.length===0)},V=async()=>{if(m){g(!0);try{const u=await en(m.id,D==null?void 0:D.id);k(u),b(ln(u.validation,n))}catch(u){b(u instanceof Error?u.message:n("assets.settings.testFailed","Connection test failed."))}finally{g(!1)}}},ue=async()=>{if(A){g(!0);try{if(A.kind==="apiKey"){const u=await qa(A.profileId);k(u),b(n("assets.settings.apiKeyRemoved","Open Cloud API key unregistered from local storage."))}else{const u=await Qa(A.profileId,A.creatorPresetId);k(u),b(n("assets.settings.creatorUnregistered","Creator unregistered from this profile."))}w(null)}catch(u){b(u instanceof Error?u.message:A.kind==="apiKey"?n("assets.settings.removeFailed","Failed to unregister API key."):n("assets.settings.creatorUnregisterFailed","Failed to unregister Creator."))}finally{g(!1)}}},ct=(A==null?void 0:A.kind)==="apiKey"?n("assets.settings.unregisterApiKey.title","Unregister API Key?"):n("assets.settings.unregisterCreator.title","Unregister Creator?"),dt=(A==null?void 0:A.kind)==="apiKey"?n("assets.settings.unregisterApiKey.message","Roblox API key is not revoked. WEPPY only removes the local Credential Profile registration on this device."):n("assets.settings.unregisterCreator.message","Roblox user or group is not deleted. WEPPY only removes this Creator from the selected API Key profile."),ut=(A==null?void 0:A.kind)==="apiKey"?n("assets.settings.removeApiKey","Unregister API Key"):n("assets.settings.unregisterCreator","Unregister Creator");return t.jsxs("section",{id:"asset-library-settings-panel",className:`${a.settingsInlinePanel} ${a.settingsDrawer}`,role:"region","aria-label":n("assets.settings.title","Asset Library settings"),"data-panel-placement":"toolbar-popover",children:[t.jsxs("div",{className:a.drawerHeader,children:[t.jsxs("div",{children:[t.jsx("h2",{children:n("assets.settings.title","Asset Library settings")}),t.jsx("span",{children:S})]}),t.jsx(G,{text:n("common.close","Close"),children:t.jsx("button",{type:"button",className:a.iconButton,onClick:i,"aria-label":n("common.close","Close"),children:t.jsx(Ue,{size:16})})})]}),r&&t.jsx("div",{className:`${a.notice} ${a.proNotice}`,children:n("assets.settings.proOnly","Roblox upload settings and Open Cloud credential controls are available on Pro.")}),t.jsxs("section",{className:a.settingsPanel,children:[t.jsxs("label",{className:a.toggleRow,children:[t.jsxs("span",{children:[t.jsx("strong",{children:n("assets.settings.openCloudToggle","Open Cloud upload")}),t.jsx("small",{children:n("assets.settings.openCloudToggle.help","Controls whether server-side Open Cloud upload mutations can run.")})]}),t.jsx(yt,{checked:te,disabled:r||P,onChange:u=>{(async()=>{g(!0);try{const I=await Wa({assetUploadByOpenCloudEnabled:u.target.checked});N(I),b(n("assets.settings.saved","Upload settings saved."))}catch(I){b(I instanceof Error?I.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}})()}})]}),de&&t.jsx("div",{className:a.metadataList,children:K.map(u=>{const I=u.id===(m==null?void 0:m.id);return t.jsxs("div",{className:a.metadataItem,children:[t.jsx("strong",{children:u.label}),t.jsxs("span",{children:[n("assets.settings.field.storage","Storage"),": ",Ye(u.storageProvider,n)]}),t.jsxs("span",{children:[n("assets.settings.field.validationStatus","Validation status"),": ",ke(u.validationStatus,n)]}),I&&t.jsx("code",{children:n("assets.settings.activeProfileBadge","Active")}),!I&&u.storageProvider==="localFile"&&t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P,onClick:()=>{(async()=>{g(!0);try{const R=await Ya(u.id),re=R.profiles.find(Pe=>Pe.id===(R.activeProfileId??u.id))??u;_(R),E(re.id),F(re.creators.length===0),H("user"),O(""),B(""),b(n("assets.settings.profileSelected","Open Cloud credential profile selected."))}catch(R){b(R instanceof Error?R.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}})()},children:n("assets.settings.useProfile","Use profile")})]},u.id)})}),m&&t.jsxs("div",{className:a.settingsSubsection,children:[t.jsx("div",{className:a.settingsSectionHeader,children:t.jsx("h3",{children:n("assets.settings.credentialProfile","Credential Profile")})}),t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("dl",{className:a.settingsDefinitionList,children:[t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.profile","Profile")}),t.jsx("dd",{children:m.label})]}),m.maskedKey&&t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.apiKey","API Key")}),t.jsx("dd",{children:m.maskedKey})]}),t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.storage","Storage")}),t.jsx("dd",{children:Ye(m.storageProvider,n)})]}),t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.validationStatus","Validation status")}),t.jsx("dd",{children:ke(m.validationStatus,n)})]}),t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.creators","Creators")}),t.jsx("dd",{children:m.creators.length})]})]}),!Y&&t.jsxs("div",{className:a.buttonRow,children:[t.jsx(G,{text:xe,children:t.jsx("button",{type:"button",className:a.commandButton,disabled:he,onClick:()=>{V()},children:n("assets.settings.testConnection","Test Connection")})}),h&&t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P,onClick:()=>T(!0),children:n("assets.settings.replaceApiKey","Replace API Key")}),t.jsx(G,{text:be,children:t.jsx("button",{type:"button",className:`${a.commandButton} ${a.dangerButton}`,disabled:ge,onClick:()=>w({kind:"apiKey",profileId:m.id}),children:n("assets.settings.removeApiKey","Unregister API Key")})})]})]})]}),Y&&t.jsxs("div",{className:a.formStack,children:[t.jsxs("div",{className:a.field,children:[t.jsx("div",{className:a.fieldLabelRow,children:t.jsx("label",{htmlFor:"asset-settings-open-cloud-profile-label",children:n("assets.settings.profileLabel","Profile name")})}),t.jsx("input",{id:"asset-settings-open-cloud-profile-label",value:x,disabled:r||P,onChange:u=>o(u.target.value),placeholder:n("assets.settings.profileLabel.placeholder","Studio automation key")}),t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.profileLabel.help","Optional. If left blank, WEPPY saves this profile as Open Cloud key automatically.")})]}),t.jsxs("div",{className:a.field,children:[t.jsxs("div",{className:a.fieldLabelRow,children:[t.jsx("label",{htmlFor:"asset-settings-open-cloud-api-key",children:n("assets.settings.apiKey","Open Cloud API Key")}),t.jsx(Te,{topicId:"openCloudApiKey",variant:"field",state:{hasOpenCloudCredential:se}})]}),t.jsx("input",{id:"asset-settings-open-cloud-api-key",value:X,type:"password",disabled:r||P,onChange:u=>z(u.target.value)}),t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.apiKey.inlineHelp","WEPPY uses this key only for Roblox Open Cloud requests. The key is encrypted on this device and is not sent to WEPPY servers or stored in any other external storage.")})]}),!se&&t.jsx("p",{className:a.inlineHelp,children:t.jsx("a",{href:"https://create.roblox.com/docs/cloud/auth/api-keys",target:"_blank",rel:"noreferrer",children:n("assets.settings.apiKeyGuide","Create a Roblox API key with Assets Read and Write permissions.")})}),t.jsxs("div",{className:a.buttonRow,children:[t.jsx(G,{text:Se,children:t.jsx("button",{type:"button",className:a.commandButton,disabled:_e,onClick:()=>{(async()=>{var u;g(!0);try{const I={apiKey:q,...x.trim()?{label:x.trim()}:{}},R=(m==null?void 0:m.storageProvider)==="localFile"?await Xa(m.id,I):await Va(I),re=R.profiles.find(Pe=>{var De;return Pe.id===(R.activeProfileId??((De=R.profile)==null?void 0:De.id))});_(R),E(R.activeProfileId??((u=R.profile)==null?void 0:u.id)??""),F(!re||re.creators.length===0),T(!1),z(""),o(""),b(n("assets.settings.apiKeySaved","Open Cloud API key saved locally."))}catch(I){b(I instanceof Error?I.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}})()},children:n("assets.settings.saveApiKey","Save API Key")})}),t.jsx(G,{text:xe,children:t.jsx("button",{type:"button",className:a.commandButton,disabled:he,onClick:()=>{(async()=>{g(!0);try{const u=await tn(q||void 0);b(rn(u.validation,n))}catch(u){b(u instanceof Error?u.message:n("assets.settings.testFailed","Connection test failed."))}finally{g(!1)}})()},children:n("assets.settings.testConnection","Test Connection")})}),t.jsx(G,{text:be,children:t.jsx("button",{type:"button",className:`${a.commandButton} ${a.dangerButton}`,disabled:ge,onClick:()=>{m&&w({kind:"apiKey",profileId:m.id})},children:n("assets.settings.removeApiKey","Unregister API Key")})})]})]}),t.jsx("div",{className:a.metadataList,children:m==null?void 0:m.creators.map(u=>t.jsxs("div",{className:a.metadataItem,children:[t.jsx("strong",{children:u.label}),t.jsx("span",{children:dn(u,n)}),u.id===m.defaultCreatorId&&t.jsx("code",{children:n("assets.settings.defaultCreatorBadge","Default")}),t.jsxs("span",{children:[n("assets.settings.field.validationStatus","Validation status"),": ",ke(u.validationStatus,n)]}),t.jsxs("div",{className:a.buttonRow,children:[u.id!==m.defaultCreatorId&&m.storageProvider==="localFile"&&t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P,onClick:()=>{(async()=>{if(m){g(!0);try{const I=await Ja(m.id,u.id);_(I),b(n("assets.settings.defaultCreatorSaved","Open Cloud default Creator saved locally."))}catch(I){b(I instanceof Error?I.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}}})()},children:n("assets.settings.makeDefaultCreator","Make default")}),t.jsx(G,{text:f,children:t.jsx("button",{type:"button",className:`${a.commandButton} ${a.dangerButton}`,disabled:d,onClick:()=>w({kind:"creator",profileId:m.id,creatorPresetId:u.id}),children:n("assets.settings.unregisterCreator","Unregister Creator")})})]})]},u.id))}),M&&!ee&&t.jsx(G,{text:Ae,children:t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P||L||!h,onClick:()=>{H("user"),O(""),B(""),F(!0)},children:n("assets.settings.addCreator","Add Creator")})}),J&&t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:a.twoColumn,children:[t.jsxs("div",{className:a.field,children:[t.jsx("div",{className:a.fieldLabelRow,children:t.jsx("label",{htmlFor:"asset-settings-creator-type",children:n("assets.upload.creatorType","Creator type")})}),t.jsxs("select",{id:"asset-settings-creator-type",value:W,disabled:r||P||L||!h,onChange:u=>H(u.target.value),children:[t.jsx("option",{value:"user",children:n("assets.creator.user","User")}),t.jsx("option",{value:"group",children:n("assets.creator.group","Group")})]})]}),t.jsxs("div",{className:a.field,children:[t.jsxs("div",{className:a.fieldLabelRow,children:[t.jsx("label",{htmlFor:"asset-settings-creator-id",children:n("assets.upload.creatorId","Creator ID")}),t.jsx(Te,{topicId:"openCloudCreatorId",variant:"field",state:{hasDefaultCreator:!!D}})]}),t.jsx("input",{id:"asset-settings-creator-id",value:Z,disabled:r||P||L||!h,onChange:u=>O(u.target.value)}),t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.creatorId.inlineHelp","Default owner for new Roblox assets: your User ID or a Group ID.")})]})]}),t.jsxs("div",{className:a.field,children:[t.jsx("div",{className:a.fieldLabelRow,children:t.jsx("label",{htmlFor:"asset-settings-creator-label",children:n("assets.settings.creatorLabel","Creator label")})}),t.jsx("input",{id:"asset-settings-creator-label",value:Q,disabled:r||P||L||!h,onChange:u=>B(u.target.value),placeholder:n("assets.settings.creatorLabel.placeholder","Main studio group")}),t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.creatorLabel.help","Optional. If left blank, WEPPY automatically saves a label like User 123 or Group 456.")})]}),!D&&t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.creatorHelp","Use the numeric user ID from a profile URL or group ID from a group URL.")}),t.jsxs("div",{className:a.buttonRow,children:[t.jsx(G,{text:Ne,children:t.jsx("button",{type:"button",className:a.primaryButton,disabled:Ie,onClick:()=>{(async()=>{if(m){g(!0);try{const u=await Za(m.id,{creatorType:W,creatorId:U,makeDefault:!D,...Q.trim()?{label:Q.trim()}:{}});_(u),O(""),B(""),F(!1),b(n("assets.settings.defaultCreatorSaved","Open Cloud default Creator saved locally."))}catch(u){b(u instanceof Error?u.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}}})()},children:j})}),M&&t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P,onClick:()=>{H("user"),O(""),B(""),F(!1)},children:n("assets.settings.cancelCreator","Cancel")})]})]})]}),v&&t.jsx("div",{className:a.messageState,children:v}),t.jsx(Qe,{open:A!==null,title:ct,message:dt,cancelLabel:n("common.cancel","Cancel"),confirmLabel:ut,loading:P,onCancel:()=>w(null),onConfirm:()=>{ue()}})]})}const pn=12,mn=5e3;function le(e,s){return e instanceof Error&&e.message.trim().length>0?e.message:s}function Re(e,s){return e.some(n=>n.id===s.id)?e.map(n=>n.id===s.id?s:n):[s,...e]}function $e(e,s){return Zt(e.filter(i=>qt(i,s)))}function pe(e,s){return e?`${e.displayName} (${e.id})`:s??"unknown asset"}function hn(e){return e.length===0?"none":e.map(s=>pe(s)).join(", ")}function Xe(e){const s=`status ${e.status}`;return e.roblox.assetId?`Roblox asset ${e.roblox.assetId}; ${s}`:s}function xn(e,s){const i=pe(s);return e==="update"?`Updated metadata for asset: ${i}.`:e==="upload"?`Uploaded asset: ${i} -> ${Xe(s)}.`:e==="thumbnail-generate"?`Generated thumbnail for asset: ${i}.`:e==="status-refresh"?`Refreshed Roblox status for asset: ${i} -> ${Xe(s)}.`:e==="usage-scan"?`Scanned usage for asset: ${i} -> ${s.usage.references.length} reference(s).`:`Updated asset: ${i}.`}function gn(e){return e!=="upload"&&e!=="status-refresh"}function we(e,s){if((s==null?void 0:s.id)===e)return s.category;const i=/^asset_(image|decal|audio|mesh|model|video|animation)_/.exec(e);return i!=null&&i[1]?i[1]:null}function qe(e){return e.status==="processing"&&!!(e.roblox.operationId??e.roblox.operationPath)}function bn(e){return{scope:e.scope.kind,placeId:e.scope.kind==="place"?e.scope.placeId:void 0,category:e.category}}function fn(e){if(e.pluginConnected&&e.activePlaceId!==null)return{placeId:e.activePlaceId,placeName:e.activePlaceName,studioConnected:!0};if(e.lastActivePlaceId!==null)return{placeId:e.lastActivePlaceId,placeName:e.lastActivePlaceName,studioConnected:!1};const s=e.places[0];return{placeId:(s==null?void 0:s.placeId)??null,placeName:(s==null?void 0:s.placeName)??null,studioConnected:!1}}function yn(e,s){if(typeof s=="number"){const i=e.places.find(n=>n.placeId===s);if(i)return{placeId:i.placeId,placeName:i.placeName,studioConnected:i.isConnected,overrideStillValid:!0}}return{...fn(e),overrideStillValid:s===null}}function jn(){const[e,s]=c.useState([]),[i,n]=c.useState(0),[l,N]=c.useState(null),[y,_]=c.useState("place"),[p,E]=c.useState("all"),[Y,T]=c.useState([]),[x,o]=c.useState(null),[X,z]=c.useState(null),[W,H]=c.useState(null),[Z,O]=c.useState(null),[Q,B]=c.useState(!1),[ee,F]=c.useState(!1),[v,b]=c.useState(!0),[A,w]=c.useState(null),[P,g]=c.useState(null),[r,C]=c.useState(null),te=c.useRef(!0),q=c.useRef(new Map),U=c.useMemo(()=>e.find(d=>d.id===l)??null,[e,l]),K=c.useCallback(d=>{const f=q.current.get(d);f!==void 0&&(clearTimeout(f),q.current.delete(d))},[]),m=c.useCallback((d,f=pn)=>{if(!qe(d)||f<=0){K(d.id);return}K(d.id),(async()=>{try{const j=await Oe(bn(d),d.id);if(!te.current)return;if(s(S=>Re(S,j)),qe(j)&&f>1){const S=setTimeout(()=>{q.current.delete(j.id),m(j,f-1)},mn);q.current.set(j.id,S);return}K(j.id)}catch(j){if(!te.current)return;K(d.id),g(le(j,"Asset Library status refresh failed."))}})()},[K]);c.useEffect(()=>()=>{te.current=!1;for(const d of q.current.values())clearTimeout(d);q.current.clear()},[]);const se=c.useCallback(()=>({scope:y,placeId:y==="place"?W:void 0}),[W,y]),h=c.useCallback(d=>({...se(),category:d}),[se]),L=c.useCallback(async()=>{try{const d=await gt(),f=yn(d,x);return T(d.places),f.overrideStillValid||o(null),z(f.placeId),H(f.placeId),O(f.placeName),B(f.studioConnected),F(f.studioConnected),f.placeId}catch{return T([]),z(null),H(null),O(null),B(!1),F(!1),null}},[x]),D=c.useCallback(async()=>{g(null);try{const d=await L(),f={scope:y,placeId:y==="place"?d:void 0};if(y==="place"&&d===null){s([]),n(0),b(!1),g("No active place is connected for place-scoped assets.");return}const j=await Promise.all(Me(p).map(k=>Ot({...f,category:k}))),S=$e(j.flatMap(k=>k.assets),p);s(S),n(S.length)}catch(d){g(le(d,"Failed to load Asset Library."))}finally{b(!1)}},[p,L,y]);c.useEffect(()=>{D()},[D]);const M=c.useCallback(async(d,f,j)=>{const S=we(f,U);if(!S)return g("Asset category is unavailable."),null;w(d),g(null),C(null);try{const k=await j(h(S));return s(V=>Re(V,k)),N(k.id),gn(d)&&C(xn(d,k)),k}catch(k){return g(le(k,"Asset Library action failed.")),null}finally{w(null)}},[h,U]),J=c.useCallback(async()=>{w("rescan"),g(null),C(null);try{const d=await Promise.all(Me(p).map(V=>Ft(h(V)))),f=$e(d.flatMap(V=>V.assets),p),j=d.reduce((V,ue)=>V+ue.adoptedCount,0),S=d.reduce((V,ue)=>V+ue.skippedCount,0),k=$e(d.flatMap(V=>V.adopted),p);s(f),n(f.length),C(`Rescan complete for ${p}: ${j} asset(s) added, ${S} skipped. Added: ${hn(k)}.`)}catch(d){g(le(d,"Asset Library rescan failed."))}finally{w(null)}},[p,h]),de=c.useCallback(async(d,f)=>{w("export-selection-rbxm"),g(null),C(null);try{const j=await zt(h(d),f);return s(S=>Re(S,j.asset)),N(j.asset.id),C(`Exported Studio selection as RBXM asset: ${pe(j.asset)}${j.deduplicated?" (reused existing local asset)":""}.`),j}catch(j){return g(le(j,"Asset Library .rbxm export failed.")),null}finally{w(null)}},[h]),oe=c.useCallback((d,f)=>M("update",d,j=>Mt(j,d,f)),[M]),_e=c.useCallback(async(d,f)=>{const j=await M("upload",d,S=>Kt(S,d,f));return j&&m(j),j},[M,m]),Se=c.useCallback(async d=>{const f=we(d,U);if(!f)return g("Asset category is unavailable."),!1;K(d);const j=e.find(S=>S.id===d)??U;w("delete"),g(null),C(null);try{return await Ht(h(f),d),s(S=>{const k=S.filter(V=>V.id!==d);return n(k.length),k}),N(S=>S===d?null:S),C(`Deleted asset: ${pe(j,d)}. Local files removed; uploaded Roblox assets were not deleted.`),!0}catch(S){return g(le(S,"Asset Library delete failed.")),!1}finally{w(null)}},[e,K,h,U]),he=c.useCallback(async(d,f)=>{const j=we(d,U);if(!j)return g("Asset category is unavailable."),null;const S=e.find(k=>k.id===d)??U;w("import-rbxm"),g(null),C(null);try{const k=await Wt(h(j),d,f);return N(d),C(`Imported RBXM asset: ${pe(S,d)} -> ${k.importedCount} instance(s) to ${k.targetParent}.`),k}catch(k){return g(le(k,"Asset Library .rbxm import failed.")),null}finally{w(null)}},[e,h,U]),xe=c.useCallback(d=>M("thumbnail-generate",d,f=>Vt(f,d)),[M]),ge=c.useCallback(d=>(K(d),M("status-refresh",d,f=>Oe(f,d))),[K,M]),be=c.useCallback((d,f)=>M("usage-scan",d,async j=>(await Gt(j,d,f)).asset),[M]),Ie=c.useCallback(d=>{_(d),N(null)},[]),Ne=c.useCallback(d=>{o(d),N(null)},[]),Ae=c.useCallback(d=>{Xt(d)&&(E(d),N(null))},[]);return{assets:e,totalCount:i,selectedAsset:U,selectedAssetId:l,scope:y,categoryFilter:p,availablePlaces:Y,selectedPlaceId:X,activePlaceId:W,activePlaceName:Z,selectedPlaceIsConnected:Q,studioConnected:ee,loading:v,busyAction:A,error:P,lastMessage:r,setScope:Ie,setSelectedPlaceId:Ne,setCategoryFilter:Ae,selectAsset:N,refresh:D,rescan:J,exportSelectionRbxm:de,updateMetadata:oe,uploadAsset:_e,deleteAsset:Se,importRbxm:he,generateThumbnail:xe,refreshStatus:ge,scanUsage:be}}function vn(e,s){return s("assets.count.shown","Shown assets: {count}").replace("{count}",String(e))}function Cn(e,s){return e===null?null:s("assets.place.id","Place ID {placeId}").replace("{placeId}",String(e))}function kn(){const{t:e}=me(),{trackEvent:s}=bt(),{tier:i,loading:n}=ft(),l=jn(),[N,y]=c.useState(!1),[_,p]=c.useState(!1),[E,Y]=c.useState(!1),T=!n&&i==="pro",x=l.selectedAsset,o=(x==null?void 0:x.file.original.toLowerCase().endsWith(".rbxm"))??!1,X=(x==null?void 0:x.category)==="model"||(x==null?void 0:x.category)==="animation",z="game.Workspace",H=!!(T&&l.studioConnected&&x&&o&&X),Z=l.availablePlaces??[],O=l.selectedPlaceId??l.activePlaceId,Q=c.useMemo(()=>l.scope==="shared"?[e("assets.scope.shared","Shared")]:[l.activePlaceName??e("assets.scope.place","Current Place"),Cn(l.activePlaceId,e),l.selectedPlaceIsConnected?e("assets.place.connected","Connected"):null].filter(v=>!!v),[l.activePlaceId,l.activePlaceName,l.scope,l.selectedPlaceIsConnected,e]),B=c.useMemo(()=>Le(l.categoryFilter,e),[l.categoryFilter,e]),ee=vn(l.totalCount,e),F=e("assets.detail.importRbxm.tooltip","Insert this local RBXM asset into {target} in the connected Studio place.").replace("{target}",z);return t.jsxs("div",{className:a.page,children:[t.jsx(jt,{title:e("assets.title","Assets"),description:e("assets.subtitle","Browse local originals, upload to Roblox, and inspect synced usage by place."),badge:t.jsx("span",{className:a.experimentalBadge,children:e("assets.experimental","Experimental")}),helpTopicId:"assets",helpState:{tier:i}}),t.jsxs("div",{className:a.toolbarShell,children:[t.jsxs("div",{className:a.toolbar,children:[t.jsxs("div",{className:a.segmented,role:"group","aria-label":e("assets.scope.label","Asset scope"),children:[t.jsx("button",{type:"button",className:l.scope==="place"?a.segmentedActive:"",onClick:()=>l.setScope("place"),children:e("assets.scope.place","Current Place")}),t.jsx("button",{type:"button",className:l.scope==="shared"?a.segmentedActive:"",onClick:()=>l.setScope("shared"),children:e("assets.scope.shared","Shared")})]}),l.scope==="place"&&Z.length>0?t.jsxs("label",{className:a.placeSelectorLabel,children:[t.jsx("span",{children:e("assets.place.selector","Asset place")}),t.jsx("select",{className:a.placeSelect,value:typeof O=="number"?String(O):"",onChange:v=>{const b=Number.parseInt(v.currentTarget.value,10);Number.isInteger(b)&&l.setSelectedPlaceId(b)},children:Z.map(v=>t.jsxs("option",{value:v.placeId,children:[v.placeName," (",v.placeId,")"]},v.placeId))})]}):null,t.jsxs("div",{className:a.listContextSummary,children:[Q.map((v,b)=>t.jsxs("span",{children:[b>0?t.jsx("span",{className:a.contextDivider,children:" · "}):null,v]},`${v}-${b}`)),t.jsx("span",{className:a.contextDivider,children:" · "}),t.jsx("span",{children:B}),t.jsx("span",{className:a.contextDivider,children:" · "}),t.jsx("strong",{children:ee})]}),t.jsxs("div",{className:a.toolbarActions,children:[t.jsx(G,{text:e("assets.rescan.tooltip","Scan inbox folders for the current filter."),children:t.jsxs("button",{type:"button",className:a.commandButton,disabled:l.busyAction==="rescan",onClick:()=>{s("dashboard_click_event",{click_target:"assets_rescan",page:"assets"}),l.rescan()},children:[t.jsx(Ze,{size:15}),e("assets.rescan","Rescan")]})}),t.jsx(G,{text:_?"":e("assets.settings.open.tooltip","Open Roblox upload settings."),children:t.jsx("button",{type:"button",className:[a.iconButton,_?a.iconButtonActive:""].filter(Boolean).join(" "),onClick:()=>{s("dashboard_click_event",{click_target:"assets_open_settings",page:"assets"}),p(v=>!v)},"aria-label":e("assets.settings.open","Open settings"),"aria-controls":"asset-library-settings-panel","aria-expanded":_,children:t.jsx(Je,{size:16})})})]}),t.jsxs("div",{className:a.categoryControl,children:[t.jsx("span",{id:"assets-category-filter-label",className:a.categoryControlLabel,children:e("assets.category.filter","Category")}),t.jsx("div",{className:a.categoryRail,role:"radiogroup","aria-labelledby":"assets-category-filter-label",children:nt.map(v=>{const b=l.categoryFilter===v,A=Le(v,e);return t.jsx("button",{type:"button",role:"radio","aria-checked":b,className:[a.categoryButton,b?a.categoryButtonActive:""].filter(Boolean).join(" "),onClick:()=>{l.setCategoryFilter(v)},children:A},v)})})]})]}),t.jsx(un,{open:_,tier:i,onClose:()=>p(!1)})]}),l.error&&t.jsx("div",{className:a.errorState,children:l.error}),l.lastMessage&&t.jsx("div",{className:a.messageState,children:l.lastMessage}),l.categoryFilter==="rbxm"&&t.jsxs("section",{className:a.rbxmGuide,"aria-label":e("assets.rbxmGuide.title","Save RBXM from Studio"),children:[t.jsx("h2",{children:e("assets.rbxmGuide.title","Save RBXM from Studio")}),t.jsx("p",{children:e("assets.rbxmGuide.body","Select objects in Roblox Studio, then use WEPPY Plugin > Assets to save the selection as a local RBXM asset.")}),t.jsx("p",{children:e("assets.rbxmGuide.thumbnail","The plugin save flow includes a thumbnail option, and saved RBXM assets appear here for management, upload, and insertion.")})]}),!T&&!n&&t.jsx("div",{className:`${a.notice} ${a.proNotice}`,children:e("assets.basic.notice","Browse, preview, edit metadata, and scan usage on Basic. Roblox upload controls are available on Pro.")}),l.loading?t.jsx("div",{className:a.emptyState,children:e("common.loading","Loading...")}):t.jsx(ka,{assets:l.assets,selectedAssetId:l.selectedAssetId,onSelect:l.selectAsset}),t.jsx(Ga,{asset:N||_||E?null:x,busyAction:l.busyAction,canUpload:T,canImportRbxm:H,importRbxmTooltip:F,importRbxmTargetParent:z,onClose:()=>l.selectAsset(null),onSave:async(v,b)=>{x&&await l.updateMetadata(x.id,{displayName:v,description:b})},onUpload:()=>y(!0),onDelete:()=>Y(!0),onImportRbxm:async()=>{x&&(s("dashboard_click_event",{click_target:"assets_import_rbxm",page:"assets"}),await l.importRbxm(x.id,{targetParent:z}))},onRefreshStatus:async()=>{x&&await l.refreshStatus(x.id)},onScanUsage:async()=>{x&&(s("dashboard_click_event",{click_target:"assets_usage_scan",page:"assets"}),await l.scanUsage(x.id,l.activePlaceId??void 0))}}),t.jsx(Qe,{open:E&&!!x,title:e("assets.delete.title","Delete asset"),message:e("assets.delete.message","This removes the local Asset Library files only. Uploaded Roblox assets are not deleted."),cancelLabel:e("common.cancel","Cancel"),confirmLabel:e("common.delete","Delete"),loading:l.busyAction==="delete",onCancel:()=>Y(!1),onConfirm:()=>{x&&(s("dashboard_click_event",{click_target:"assets_delete",page:"assets"}),l.deleteAsset(x.id).then(v=>{v&&Y(!1)}))}}),t.jsx(on,{asset:x,open:N,canUpload:T,busyAction:l.busyAction,onClose:()=>{y(!1),l.selectAsset(null)},onBack:()=>y(!1),onOpenSettings:()=>{y(!1),p(!0)},onUpload:async v=>{if(!x)return;s("dashboard_click_event",{click_target:"assets_upload_submit",page:"assets"}),await l.uploadAsset(x.id,v)&&y(!1)}})]})}export{kn as Component};
46
+ */const Tt=[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m17 8-5-5-5 5",key:"7q97r8"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}]],Ot=ne("upload",Tt);function tt(e){if(e.scope==="place"&&typeof e.placeId=="number")return{placeId:String(e.placeId)}}function ae(e){const s=tt(e);return s?`?placeId=${encodeURIComponent(s.placeId)}`:""}function Ce(e){return`/api/assets/${encodeURIComponent(e.scope)}/${encodeURIComponent(e.category)}`}function de(e,s){return`${Ce(e)}/${encodeURIComponent(s)}`}async function Ft(e){return $.get(Ce(e),tt(e))}async function Mt(e){return $.post(`${Ce(e)}/rescan${ae(e)}`,{})}async function Ht(e,s,i){return(await $.patch(`${de(e,s)}${ae(e)}`,i)).asset}async function Kt(e,s){return $.delete(`${de(e,s)}${ae(e)}`)}async function Gt(e,s,i){return(await $.post(`${de(e,s)}/upload${ae(e)}`,i)).asset}async function Oe(e,s){return(await $.post(`${de(e,s)}/status-refresh${ae(e)}`,{})).asset}async function zt(e,s,i){const n={...e,placeId:i??e.placeId};return $.post(`${de(e,s)}/usage-scan${ae(n)}`,{})}async function Wt(e,s){return $.post(`${Ce(e)}/export-selection-rbxm${ae(e)}`,s)}async function Vt(e,s,i){return $.post(`${de(e,s)}/import-rbxm${ae(e)}`,i)}async function Yt(e,s){return(await $.post(`${de(e,s)}/thumbnail-generate${ae(e)}`,{})).asset}function st(e){return e.fileUrl?`${ve}${e.fileUrl}`:`${ve}/api/assets/${e.scope.kind}/${e.category}/${encodeURIComponent(e.id)}/file${ae({scope:e.scope.kind,placeId:e.scope.kind==="place"?e.scope.placeId:void 0})}`}function at(e){return e.previewUrl?`${ve}${e.previewUrl}`:`${ve}/api/assets/${e.scope.kind}/${e.category}/${encodeURIComponent(e.id)}/preview${ae({scope:e.scope.kind,placeId:e.scope.kind==="place"?e.scope.placeId:void 0})}`}const nt=["all","image","decal","rbxm"],Xt=new Set(nt),Fe=["model","animation"];function ye(e){return/\.(rbxm|rbxmx)$/i.test(e.file.original)}function qt(e){return Xt.has(e)}function Le(e,s){return e==="all"?s("assets.category.all","All"):s(`assets.category.${e}`,e==="rbxm"?"RBXM":e)}function ie(e,s){return Le(ye(e)?"rbxm":e.category,s)}function Me(e){return e==="all"?["image","decal",...Fe]:e==="rbxm"?Fe:[e]}function Zt(e,s){return s==="all"?e.category==="image"||e.category==="decal"||ye(e):s==="rbxm"?ye(e):(s==="model"||s==="animation")&&ye(e)?!1:e.category===s}function Jt(e){return[...e].sort((s,i)=>i.createdAt.localeCompare(s.createdAt)||i.id.localeCompare(s.id))}const Qt="_page_u8a6t_1",es="_experimentalBadge_u8a6t_9",ts="_toolbarShell_u8a6t_23",ss="_toolbar_u8a6t_23",as="_segmented_u8a6t_39",ns="_placeSelectorLabel_u8a6t_43",os="_listContextSummary_u8a6t_47",rs="_toolbarActions_u8a6t_53",ls="_categoryControl_u8a6t_58",is="_contextDivider_u8a6t_80",ds="_categoryControlLabel_u8a6t_84",cs="_categoryRail_u8a6t_90",us="_categoryButton_u8a6t_98",ps="_categoryButtonActive_u8a6t_127",ms="_copyRow_u8a6t_140",hs="_buttonRow_u8a6t_141",xs="_segmentedActive_u8a6t_183",gs="_placeSelect_u8a6t_43",bs="_commandButton_u8a6t_231",fs="_primaryButton_u8a6t_232",ys="_iconButton_u8a6t_233",js="_dangerButton_u8a6t_273",vs="_iconButtonActive_u8a6t_294",Cs="_grid_u8a6t_307",_s="_assetCard_u8a6t_313",Ss="_assetCardSelected_u8a6t_327",Is="_thumbnailWrap_u8a6t_332",Ns="_thumbnail_u8a6t_332",As="_thumbnailFallback_u8a6t_348",Ps="_assetCardBody_u8a6t_359",ks="_assetName_u8a6t_366",Rs="_assetMeta_u8a6t_374",$s="_statusChip_u8a6t_381",ws="_categoryPill_u8a6t_382",Ls="_assetId_u8a6t_387",Bs="_scopeText_u8a6t_388",Us="_muted_u8a6t_389",Ds="_emptyState_u8a6t_394",Es="_notice_u8a6t_395",Ts="_errorState_u8a6t_396",Os="_messageState_u8a6t_397",Fs="_proNotice_u8a6t_427",Ms="_rbxmGuide_u8a6t_443",Hs="_settingsInlinePanel_u8a6t_483",Ks="_settingsDrawer_u8a6t_503",Gs="_detailPopupLayer_u8a6t_519",zs="_detailDialog_u8a6t_535",Ws="_detailDialogHeader_u8a6t_552",Vs="_detailTitleBlock_u8a6t_563",Ys="_detailEyebrow_u8a6t_585",Xs="_detailHeaderActions_u8a6t_594",qs="_detailDialogBody_u8a6t_602",Zs="_detailPreviewPane_u8a6t_611",Js="_detailPreview_u8a6t_611",Qs="_detailPreviewFallback_u8a6t_623",ea="_detailContentPane_u8a6t_659",ta="_formStack_u8a6t_665",sa="_drawerHeader_u8a6t_669",aa="_detailSection_u8a6t_720",na="_noticeList_u8a6t_721",oa="_settingsPanel_u8a6t_722",ra="_setupNotice_u8a6t_739",la="_field_u8a6t_764",ia="_fieldLabelRow_u8a6t_772",da="_fieldHelp_u8a6t_796",ca="_twoColumn_u8a6t_801",ua="_technicalDetails_u8a6t_812",pa="_detailGrid_u8a6t_829",ma="_metadataList_u8a6t_830",ha="_compactMeta_u8a6t_841",xa="_copyableValue_u8a6t_868",ga="_inlineCopyButton_u8a6t_879",ba="_hashText_u8a6t_900",fa="_usageList_u8a6t_904",ya="_usageItem_u8a6t_910",ja="_metadataItem_u8a6t_911",va="_settingsSubsection_u8a6t_959",Ca="_settingsSectionHeader_u8a6t_964",_a="_settingsDefinitionList_u8a6t_977",Sa="_toggleRow_u8a6t_999",Ia="_inlineHelp_u8a6t_1013",a={page:Qt,experimentalBadge:es,toolbarShell:ts,toolbar:ss,segmented:as,placeSelectorLabel:ns,listContextSummary:os,toolbarActions:rs,categoryControl:ls,contextDivider:is,categoryControlLabel:ds,categoryRail:cs,categoryButton:us,categoryButtonActive:ps,copyRow:ms,buttonRow:hs,segmentedActive:xs,placeSelect:gs,commandButton:bs,primaryButton:fs,iconButton:ys,dangerButton:js,iconButtonActive:vs,grid:Cs,assetCard:_s,assetCardSelected:Ss,thumbnailWrap:Is,thumbnail:Ns,thumbnailFallback:As,assetCardBody:Ps,assetName:ks,assetMeta:Rs,statusChip:$s,categoryPill:ws,assetId:Ls,scopeText:Bs,muted:Us,emptyState:Ds,notice:Es,errorState:Ts,messageState:Os,proNotice:Fs,rbxmGuide:Ms,settingsInlinePanel:Hs,settingsDrawer:Ks,detailPopupLayer:Gs,detailDialog:zs,detailDialogHeader:Ws,detailTitleBlock:Vs,detailEyebrow:Ys,detailHeaderActions:Xs,detailDialogBody:qs,detailPreviewPane:Zs,detailPreview:Js,detailPreviewFallback:Qs,detailContentPane:ea,formStack:ta,drawerHeader:sa,detailSection:aa,noticeList:na,settingsPanel:oa,setupNotice:ra,field:la,fieldLabelRow:ia,fieldHelp:da,twoColumn:ca,technicalDetails:ua,detailGrid:pa,metadataList:ma,compactMeta:ha,copyableValue:xa,inlineCopyButton:ga,hashText:ba,usageList:fa,usageItem:ya,metadataItem:ja,settingsSubsection:va,settingsSectionHeader:Ca,settingsDefinitionList:_a,toggleRow:Sa,inlineHelp:Ia},Na={image:mt,decal:At,audio:It,mesh:kt,model:pt,video:Lt,animation:$t};function Be(e,s){return s(`assets.status.${e}`,e)}function Aa(e){switch(e){case"uploaded":return"success";case"failed":return"error";case"processing":case"uploading":return"warning";case"localOnly":case"superseded":default:return"neutral"}}function Pa(e){return e.category==="image"||e.category==="decal"||!!e.file.preview}function ka(e){return e.category==="decal"?e.roblox.creatorAssetId??e.roblox.assetId:e.roblox.assetId}function ot(e,s){var y;const i=((y=e.rbxm)==null?void 0:y.studioUploads)??[];if(i.length===0)return null;const n=i.filter(_=>_.status==="uploaded").length,l=i.filter(_=>_.status==="failed").length,N=[n>0?`${n} ${s("assets.detail.rbxmStudioUploadsUploaded","uploaded")}`:null,l>0?`${l} ${s("assets.detail.rbxmStudioUploadsFailed","failed")}`:null].filter(Boolean);return`${s("assets.detail.rbxmStudioUploadsLabel","Studio uploads")}: ${N.join(", ")}`}function Ra({assets:e,selectedAssetId:s,onSelect:i}){const{t:n}=me();return e.length===0?t.jsxs("div",{className:a.emptyState,children:[t.jsx("p",{children:n("assets.empty.title","No assets yet")}),t.jsx("span",{children:n("assets.empty.body","Choose a scope and category, then rescan that inbox folder.")})]}):t.jsx("div",{className:a.grid,children:e.map(l=>{const N=Na[l.category],y=ka(l),_=ot(l,n);return t.jsxs("button",{type:"button",className:[a.assetCard,s===l.id?a.assetCardSelected:""].filter(Boolean).join(" "),onClick:()=>i(l.id),children:[t.jsx("span",{className:a.thumbnailWrap,children:Pa(l)?t.jsx("img",{className:a.thumbnail,src:at(l),alt:l.displayName,loading:"lazy"}):t.jsx("span",{className:a.thumbnailFallback,"aria-hidden":"true",children:t.jsx(N,{size:30})})}),t.jsxs("span",{className:a.assetCardBody,children:[t.jsx("span",{className:a.assetName,children:l.displayName}),t.jsxs("span",{className:a.assetMeta,children:[t.jsx(Te,{variant:"neutral",className:a.categoryPill,children:ie(l,n)}),t.jsx(Te,{variant:Aa(l.status),className:a.statusChip,children:Be(l.status,n)})]}),t.jsxs("span",{className:a.assetMeta,children:[t.jsx("span",{className:a.scopeText,children:l.scope.kind==="shared"?n("assets.scope.shared","Shared"):n("assets.scope.place","Current Place")}),t.jsx("span",{className:a.assetId,children:y?`#${y}`:_??n("assets.status.localOnly","Local only")})]})]})]},l.id)})})}const $a="https://create.roblox.com/dashboard/creations/store",wa=/^https:\/\/create\.roblox\.com\/store\/asset\/\d+(?:\/.*)?$/;function La(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function je(e){const s=new Date(e);if(Number.isNaN(s.getTime()))return e;const i=s.getFullYear(),n=String(s.getMonth()+1).padStart(2,"0"),l=String(s.getDate()).padStart(2,"0"),N=String(s.getHours()).padStart(2,"0"),y=String(s.getMinutes()).padStart(2,"0");return`${i}-${n}-${l} ${N}:${y}`}function Ba(e){return e.category==="image"||e.category==="decal"||!!e.file.preview}function Ua(e){return e.file.preview?at(e):st(e)}function Da(e){var i;const s=Object.entries(((i=e.rbxm)==null?void 0:i.classCounts)??{}).sort((n,l)=>l[1]-n[1]).slice(0,8);return s.length===0?"-":s.map(([n,l])=>`${n} ${l}`).join(", ")}function He(e){var l;const s=(l=e.rbxm)==null?void 0:l.thumbnail;if(!s)return"-";const i=s.source?` via ${s.source}`:"",n=s.message?` · ${s.message}`:"";return`${s.status}${i}${n}`}function Ea(e){var l,N;const s=(N=(l=e.rbxm)==null?void 0:l.review)==null?void 0:N.summary;if(!s)return"-";const i=[["roots",s.rootCount],["parts",s.partCount],["mesh parts",s.meshPartCount],["scripts",s.scriptCount],["unanchored",s.unanchoredPartCount]].flatMap(([y,_])=>typeof _=="number"?[`${y} ${_}`]:[]),n=s.bounds;if(n&&typeof n=="object"&&"size"in n){const y=n.size;if(y&&typeof y=="object"){const{x:_,y:p,z:E}=y;typeof _=="number"&&typeof p=="number"&&typeof E=="number"&&i.push(`bounds ${_} x ${p} x ${E}`)}}return i.length>0?i.join(", "):"-"}function Ta(e){var i,n;const s=(i=e.rbxm)==null?void 0:i.generation;return s?s.schemaMode==="custom"&&((n=s.schemaGroups)!=null&&n.length)?`custom · ${s.schemaGroups.join(", ")}`:s.predefinedSchema?`${s.schemaMode??"predefined"} · ${s.predefinedSchema}`:s.schemaMode??"-":"-"}function Ke(e){const{width:s,height:i}=e.file;return s===null||i===null?null:`${s} x ${i}px`}function Ge(e){const{durationMs:s}=e.file;return s===null?null:s<1e3?`${s} ms`:`${(s/1e3).toFixed(1)} s`}function Oa(e){return`${$a}/${e}/configure`}function Fa(e){return e.category==="decal"?e.roblox.creatorAssetId??e.roblox.assetId??null:e.roblox.assetId??null}function Ma(e){const s=Fa(e),i=s?Oa(s):null,n=e.category==="decal"?e.roblox.creatorAssetWebUrl??e.roblox.assetWebUrl:e.roblox.assetWebUrl;return!n||i&&wa.test(n)?i:n}function Ha(e){return`${je(e.startedAt)} -> ${e.status}`}function ze(e){return!e.creatorType||!e.creatorId?null:`${e.creatorType} ${e.creatorId}`}function We(e){return e.assetRole?`Asset role: ${e.assetRole}`:null}function Ka(e){const s=e.sourceProperty?` · ${e.sourceProperty}`:"";return`${e.path} · ${e.assetType} · ${e.status}${s}`}function Ga(e){return e.assetUri&&e.assetId?`${e.assetUri} (#${e.assetId})`:e.assetUri?e.assetUri:e.assetId?`#${e.assetId}`:e.message??"-"}function fe({label:e,value:s}){return s?t.jsx("button",{type:"button",className:a.inlineCopyButton,"aria-label":e,title:e,onClick:()=>{var i;return void((i=navigator.clipboard)==null?void 0:i.writeText(s))},children:t.jsx(et,{size:13})}):null}function za({asset:e,busyAction:s,canUpload:i,canImportRbxm:n,importRbxmTooltip:l,importRbxmTargetParent:N,onClose:y,onSave:_,onUpload:p,onDelete:E,onImportRbxm:Y,onRefreshStatus:T,onScanUsage:x}){var P,g;const{t:o}=me(),X=d.useRef(null),[z,W]=d.useState(""),[H,Z]=d.useState("");if(d.useEffect(()=>{W((e==null?void 0:e.displayName)??""),Z((e==null?void 0:e.description)??"")},[e==null?void 0:e.description,e==null?void 0:e.displayName,e==null?void 0:e.id]),d.useEffect(()=>{var C;if(!e)return;(C=X.current)==null||C.focus();const r=te=>{te.key==="Escape"&&y()};return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[e,y]),!e)return null;const O=e.status==="processing"&&!!(e.roblox.operationId??e.roblox.operationPath),Q=!!e.roblox.assetUri,B=Ma(e),ee=e.roblox.uploadAttempts??[],F=e.category==="decal"&&!!(e.roblox.creatorAssetId||e.roblox.backingImageAssetId||e.roblox.assetId),v=e.roblox.creatorAssetId??e.roblox.assetId,b=e.roblox.backingImageAssetId??e.roblox.assetId,A=ot(e,o),w=e.roblox.assetId?e.usage.lastScannedAt?o("assets.detail.noUsageAfterScan","No references were found in local Sync files during the last check."):o("assets.detail.noUsageUnscanned","Run Scan usage to search local Sync files for this Roblox Asset ID."):o("assets.detail.noUsageNoRobloxId","This asset does not have a Roblox Asset ID yet, so usage cannot be checked. Upload it before scanning usage.");return t.jsx("div",{className:a.detailPopupLayer,onClick:y,role:"presentation",children:t.jsxs("section",{ref:X,className:a.detailDialog,role:"dialog","aria-modal":"true","aria-label":o("assets.detail.title","Asset details"),tabIndex:-1,onClick:r=>r.stopPropagation(),children:[t.jsxs("div",{className:a.detailDialogHeader,children:[t.jsxs("div",{className:a.detailTitleBlock,children:[t.jsxs("span",{className:a.detailEyebrow,children:[ie(e,o)," · ",Be(e.status,o)]}),t.jsx("h2",{children:e.displayName}),t.jsx("span",{children:e.id})]}),t.jsxs("div",{className:a.detailHeaderActions,children:[t.jsx(G,{text:i?o("assets.upload.open.tooltip","Upload this local file to Roblox through Open Cloud."):o("assets.proOnly.tooltip","Roblox upload is available on Pro."),children:t.jsxs("button",{type:"button",className:a.commandButton,disabled:!i,onClick:p,children:[t.jsx(Ot,{size:15}),o("assets.upload.open","Upload")]})}),n&&t.jsx(G,{text:l,children:t.jsxs("button",{type:"button",className:a.commandButton,disabled:s==="import-rbxm",onClick:()=>void Y(),children:[t.jsx(ht,{size:15}),o("assets.detail.importRbxm","Insert into Studio")]})}),t.jsxs("button",{type:"button",className:a.commandButton,disabled:!O||s==="status-refresh",onClick:()=>void T(),children:[t.jsx(Ze,{size:15}),o("assets.detail.refreshStatus","Refresh")]}),t.jsxs("button",{type:"button",className:a.commandButton,disabled:!e.roblox.assetId||s==="usage-scan",onClick:()=>void x(),children:[t.jsx(Ut,{size:15}),o("assets.detail.scanUsage","Scan usage")]}),t.jsx(G,{text:o("assets.delete.tooltip","Delete this local Asset Library item."),children:t.jsxs("button",{type:"button",className:`${a.commandButton} ${a.dangerButton}`,disabled:s==="delete",onClick:E,children:[t.jsx(Et,{size:15}),o("common.delete","Delete")]})}),t.jsx(G,{text:o("common.close","Close"),children:t.jsx("button",{type:"button",className:a.iconButton,onClick:y,"aria-label":o("common.close","Close"),children:t.jsx(Ue,{size:16})})})]})]}),t.jsxs("div",{className:a.detailDialogBody,children:[t.jsx("div",{className:a.detailPreviewPane,children:Ba(e)?t.jsx("img",{className:a.detailPreview,src:Ua(e),alt:e.displayName}):t.jsxs("div",{className:a.detailPreviewFallback,children:[t.jsx("span",{children:ie(e,o)}),t.jsx("code",{children:e.file.original}),((P=e.rbxm)==null?void 0:P.thumbnail)&&t.jsx("small",{children:He(e)})]})}),t.jsxs("div",{className:a.detailContentPane,children:[t.jsxs("div",{className:a.formStack,children:[t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:o("assets.detail.displayName","Display name")}),t.jsx("input",{value:z,onChange:r=>W(r.target.value)})]}),t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:o("assets.detail.description","Description")}),t.jsx("textarea",{value:H,rows:3,onChange:r=>Z(r.target.value)})]}),t.jsx("button",{type:"button",className:a.primaryButton,disabled:s==="update",onClick:()=>void _(z,H),children:o("assets.detail.save","Save metadata")})]}),t.jsxs("section",{className:a.detailSection,children:[t.jsx("h3",{children:o("assets.detail.localFile","Local file")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.fileName","File")}),t.jsx("dd",{children:e.file.original}),t.jsx("dt",{children:o("assets.detail.source","Source path")}),t.jsx("dd",{children:e.source.originalPath}),t.jsx("dt",{children:o("assets.detail.category","Category")}),t.jsx("dd",{children:ie(e,o)}),t.jsx("dt",{children:o("assets.detail.scope","Scope")}),t.jsx("dd",{children:e.scope.kind==="shared"?o("assets.scope.shared","Shared"):o("assets.scope.place","Current Place")}),t.jsx("dt",{children:o("assets.detail.mimeType","Type")}),t.jsx("dd",{children:e.file.mimeType}),t.jsx("dt",{children:o("assets.detail.size","Size")}),t.jsx("dd",{children:La(e.file.sizeBytes)}),Ke(e)&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.dimensions","Dimensions")}),t.jsx("dd",{children:Ke(e)})]}),Ge(e)&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.duration","Duration")}),t.jsx("dd",{children:Ge(e)})]})]})]}),e.rbxm&&t.jsxs("section",{className:a.detailSection,children:[t.jsx("h3",{children:o("assets.detail.rbxm","RBXM contents")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.rbxmExportedCount","Exported roots")}),t.jsx("dd",{children:e.rbxm.exportedCount}),t.jsx("dt",{children:o("assets.detail.rbxmClasses","Classes")}),t.jsx("dd",{children:Da(e)}),t.jsx("dt",{children:o("assets.detail.rbxmThumbnail","Thumbnail")}),t.jsx("dd",{children:He(e)}),A&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.rbxmStudioUploadsLabel","Studio uploads")}),t.jsx("dd",{children:A})]}),n&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.studioInsertTarget","Studio insert target")}),t.jsx("dd",{children:N})]})]}),e.rbxm.roots.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmRoots","Root tree")}),e.rbxm.roots.map(r=>t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("span",{children:[r.name," (",r.className,")"]}),t.jsx("code",{children:r.path})]},`${r.path}-${r.className}`))]}),e.rbxm.resourceReferences.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmReferences","Asset references")}),e.rbxm.resourceReferences.map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("span",{children:[r.path," · ",r.property]}),t.jsx("code",{children:r.assetId?`${r.value} (#${r.assetId})`:r.value})]},`${r.path}-${r.property}-${C}`))]}),e.rbxm.studioUploads&&e.rbxm.studioUploads.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmStudioUploads","Embedded Studio uploads")}),e.rbxm.studioUploads.map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:Ka(r)}),t.jsx("code",{children:Ga(r)})]},`${r.path}-${r.assetType}-${r.sourceProperty??""}-${C}`))]}),e.rbxm.generation&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmGeneration","Generated model")}),t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmGenerationProvider","Provider")}),t.jsx("code",{children:e.rbxm.generation.provider})]}),e.rbxm.generation.prompt&&t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmGenerationPrompt","Prompt")}),t.jsx("code",{children:e.rbxm.generation.prompt})]}),t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmGenerationSchema","Schema")}),t.jsx("code",{children:Ta(e)})]}),e.rbxm.generation.path&&t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmGenerationPath","Studio path")}),t.jsx("code",{children:e.rbxm.generation.path})]})]}),e.rbxm.review&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmReview","Model review")}),t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmReviewReadiness","Readiness")}),t.jsx("code",{children:e.rbxm.review.readiness})]}),t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:o("assets.detail.rbxmReviewSummary","Summary")}),t.jsx("code",{children:Ea(e)})]}),e.rbxm.review.findings.slice(0,8).map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("span",{children:[r.severity," · ",r.category," · ",r.code]}),t.jsx("code",{children:r.path?`${r.path}: ${r.message}`:r.message})]},`${r.code}-${r.path}-${C}`))]})]}),t.jsxs("section",{className:a.detailSection,children:[t.jsx("h3",{children:o("assets.detail.roblox","Roblox upload status")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.status","Status")}),t.jsx("dd",{children:Be(e.status,o)}),F?t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.decalAssetId","Roblox Decal ID")}),t.jsxs("dd",{className:a.copyableValue,children:[t.jsx("span",{children:v??o("assets.status.localOnly","Local only")}),t.jsx(fe,{label:o("assets.detail.copyDecalAssetId","Copy Roblox Decal ID"),value:v})]}),t.jsx("dt",{children:o("assets.detail.studioTextureImageId","Studio Texture Image ID")}),t.jsxs("dd",{className:a.copyableValue,children:[t.jsx("span",{children:b??"-"}),t.jsx(fe,{label:o("assets.detail.copyStudioTextureImageId","Copy Studio Texture Image ID"),value:b})]})]}):t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.assetId","Asset ID")}),t.jsxs("dd",{className:a.copyableValue,children:[t.jsx("span",{children:e.roblox.assetId??o("assets.status.localOnly","Local only")}),t.jsx(fe,{label:o("assets.detail.copyAssetId","Copy Asset ID"),value:e.roblox.assetId})]})]}),t.jsx("dt",{children:o("assets.detail.studioUri","Studio URI")}),t.jsx("dd",{children:e.roblox.assetUri??"-"}),t.jsx("dt",{children:o("assets.detail.robloxWebUrl","Creator Dashboard URL")}),t.jsxs("dd",{className:a.copyableValue,children:[t.jsx("span",{children:B??"-"}),t.jsx(fe,{label:o("assets.detail.copyWebUrl","Copy configure URL"),value:B})]}),e.roblox.errorMessage&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.error","Error")}),t.jsx("dd",{children:e.roblox.errorMessage})]})]}),t.jsxs("div",{className:a.copyRow,children:[t.jsxs("button",{type:"button",className:a.commandButton,disabled:!Q,onClick:()=>{var r;return e.roblox.assetUri&&void((r=navigator.clipboard)==null?void 0:r.writeText(e.roblox.assetUri))},children:[t.jsx(et,{size:15}),o("assets.detail.copyStudioUri","Copy Studio URI")]}),B&&t.jsxs("a",{className:a.commandButton,href:B,target:"_blank",rel:"noreferrer",children:[t.jsx(xt,{size:15}),o("assets.detail.openRobloxPage","Open configure page")]})]}),e.roblox.assetId&&t.jsx("p",{className:a.muted,children:o("assets.detail.robloxWebUrlNotice","Opening this page requires the Roblox account that owns or can manage the uploaded asset.")}),ee.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.uploadHistory","Upload history")}),ee.slice().reverse().map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsx("span",{children:Ha(r)}),ze(r)&&t.jsx("code",{children:ze(r)}),We(r)&&t.jsx("code",{children:We(r)}),r.operationPath&&t.jsx("code",{children:r.operationPath}),r.assetId&&t.jsxs("code",{children:[o("assets.detail.assetId","Asset ID"),": ",r.assetId]}),r.remotePath&&t.jsx("code",{children:r.remotePath}),r.message&&t.jsx("code",{children:r.message}),r.errorMessage&&t.jsx("code",{children:r.errorMessage})]},`${r.startedAt}-${r.operationPath??C}`))]})]}),t.jsxs("section",{className:a.detailSection,children:[t.jsx("h3",{children:o("assets.detail.usedInPlace","Where this asset is used in this Place")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.usageSource","Checked against")}),t.jsx("dd",{children:e.usage.scanSource==="localSync"?o("assets.detail.usageSource.localSync","Local Sync files"):o("assets.detail.usageSource.notScanned","Not checked yet")}),t.jsx("dt",{children:o("assets.detail.lastScanned","Last checked")}),t.jsx("dd",{children:e.usage.lastScannedAt?o("assets.detail.lastScannedAt","Last checked: {time}").replace("{time}",je(e.usage.lastScannedAt)):o("assets.detail.lastScanned.never","No check yet")})]}),e.usage.references.length===0?t.jsx("p",{className:a.muted,children:w}):t.jsx("div",{className:a.usageList,children:e.usage.references.map((r,C)=>t.jsxs("div",{className:a.usageItem,children:[t.jsx("strong",{children:r.kind==="property"?r.instancePath:r.filePath}),t.jsx("span",{children:r.property??o("assets.detail.line","line {line}").replace("{line}",String(r.line??"-"))}),t.jsx("code",{children:r.value})]},`${r.kind}-${C}`))})]}),t.jsxs("details",{className:a.technicalDetails,children:[t.jsx("summary",{children:o("assets.detail.technicalDetails","Technical details")}),t.jsxs("dl",{className:a.detailGrid,children:[t.jsx("dt",{children:o("assets.detail.stableId","Stable ID")}),t.jsx("dd",{className:a.hashText,children:e.id}),t.jsx("dt",{children:o("assets.detail.sourceKind","Source kind")}),t.jsx("dd",{children:e.source.kind}),t.jsx("dt",{children:o("assets.detail.sha256","SHA-256")}),t.jsx("dd",{className:a.hashText,children:e.file.sha256}),t.jsx("dt",{children:o("assets.detail.createdAt","Created")}),t.jsx("dd",{children:je(e.createdAt)}),t.jsx("dt",{children:o("assets.detail.updatedAt","Updated")}),t.jsx("dd",{children:je(e.updatedAt)}),e.roblox.operationId&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.operationId","Operation ID")}),t.jsx("dd",{className:a.hashText,children:e.roblox.operationId})]}),e.roblox.operationPath&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.operationPath","Operation path")}),t.jsx("dd",{className:a.hashText,children:e.roblox.operationPath})]}),e.roblox.versionId&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.versionId","Version ID")}),t.jsx("dd",{className:a.hashText,children:e.roblox.versionId})]}),e.roblox.remotePath&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.remotePath","Remote path")}),t.jsx("dd",{className:a.hashText,children:e.roblox.remotePath})]}),e.roblox.moderationState&&t.jsxs(t.Fragment,{children:[t.jsx("dt",{children:o("assets.detail.moderationState","Moderation")}),t.jsx("dd",{children:e.roblox.moderationState})]})]}),((g=e.rbxm)==null?void 0:g.thumbnail.attempts)&&e.rbxm.thumbnail.attempts.length>0&&t.jsxs("div",{className:a.metadataList,children:[t.jsx("strong",{children:o("assets.detail.rbxmThumbnailAttempts","Thumbnail attempts")}),e.rbxm.thumbnail.attempts.map((r,C)=>t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("span",{children:[r.method," · ",r.status]}),r.message&&t.jsx("code",{children:r.message})]},`${r.method}-${C}`))]})]})]})]})]})})}function rt(e){return{assetUploadByOpenCloudEnabled:e.hot.ENABLE_ASSET_UPLOAD_BY_OPEN_CLOUD===!0}}function Wa(e){const s={};return typeof e.assetUploadByOpenCloudEnabled=="boolean"&&(s.ENABLE_ASSET_UPLOAD_BY_OPEN_CLOUD=e.assetUploadByOpenCloudEnabled),s}async function lt(){const e=await $.get("/api/dashboard/settings");return rt(e)}async function Va(e){const s=await $.patch("/api/dashboard/settings",Wa(e));return rt(s)}async function it(){return $.get("/api/dashboard/open-cloud/credential-profiles")}async function Ya(e){return $.post("/api/dashboard/open-cloud/credential-profiles",e)}async function Xa(e){return $.patch("/api/dashboard/open-cloud/credential-profiles/active",{profileId:e})}async function qa(e,s){return $.put(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/api-key`,s)}async function Za(e){return $.delete(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}`)}async function Ja(e,s){return $.post(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/creators`,s)}async function Qa(e,s){return $.patch(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/creators/${encodeURIComponent(s)}/default`,{})}async function en(e,s){return $.delete(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/creators/${encodeURIComponent(s)}`)}async function tn(e,s){return $.post(`/api/dashboard/open-cloud/credential-profiles/${encodeURIComponent(e)}/test`,s?{creatorPresetId:s}:{})}async function sn(e){return $.post("/api/dashboard/open-cloud/credential/test",e?{apiKey:e}:{})}function an(e){return e.category==="image"||e.category==="decal"}function nn(e,s){return e==="group"?s("assets.creator.group","Group"):s("assets.creator.user","User")}function on(e,s){return`${e.label} · ${nn(e.creatorType,s)} ${e.creatorId}`}function Ve(e){if(!e)return null;if(e.defaultCreatorId){const s=e.creators.find(i=>i.id===e.defaultCreatorId);if(s)return s}return e.creators[0]??null}function rn({asset:e,open:s,canUpload:i,busyAction:n,onClose:l,onBack:N,onOpenSettings:y,onUpload:_}){const{t:p}=me(),E=d.useRef(null),[Y,T]=d.useState(null),[x,o]=d.useState(null),[X,z]=d.useState(!1),[W,H]=d.useState(null),[Z,O]=d.useState(""),[Q,B]=d.useState(""),[ee,F]=d.useState(""),[v,b]=d.useState("user"),[A,w]=d.useState("");if(d.useEffect(()=>{O((e==null?void 0:e.displayName)??""),B((e==null?void 0:e.description)??"")},[e==null?void 0:e.description,e==null?void 0:e.displayName,e==null?void 0:e.id]),d.useEffect(()=>{if(!s)return;let h=!1;return z(!0),H(null),(async()=>{try{const[L,D]=await Promise.all([lt(),it()]);if(h)return;T(L);const M=D.profiles.find(ce=>ce.id===D.activeProfileId)??D.profiles[0]??null;o(M);const J=Ve(M);F((J==null?void 0:J.id)??""),b((J==null?void 0:J.creatorType)??"user"),w((J==null?void 0:J.creatorId)??"")}catch(L){if(h)return;H(L instanceof Error?L.message:p("assets.upload.settingsLoadFailed","Failed to load upload settings.")),T(null),o(null)}finally{h||z(!1)}})(),()=>{h=!0}},[s,p]),d.useEffect(()=>{var L;if(!s||!e)return;(L=E.current)==null||L.focus();const h=D=>{D.key==="Escape"&&l()};return document.addEventListener("keydown",h),()=>document.removeEventListener("keydown",h)},[e,l,s]),!s||!e)return null;const P=(Y==null?void 0:Y.assetUploadByOpenCloudEnabled)===!0,g=!!x,r=Ve(x),C=(x==null?void 0:x.creators.find(h=>h.id===ee))??null,te=!!r,U=(x==null?void 0:x.storageProvider)==="env"&&g&&!te,K=U&&A.trim().length>0,m=i&&!X&&!W&&(!P||!g||!te&&!U),se=i&&!X&&!W&&P&&g&&(te||K)&&n!=="upload";return t.jsx("div",{className:a.detailPopupLayer,onClick:l,role:"presentation",children:t.jsxs("section",{ref:E,className:a.detailDialog,role:"dialog","aria-modal":"true","aria-label":p("assets.upload.title","Upload asset"),tabIndex:-1,onClick:h=>h.stopPropagation(),children:[t.jsxs("div",{className:a.detailDialogHeader,children:[t.jsxs("div",{className:a.detailTitleBlock,children:[t.jsxs("span",{className:a.detailEyebrow,children:[ie(e,p)," · ",p("assets.upload.intent","Upload to Roblox")]}),t.jsx("h2",{children:p("assets.upload.title","Upload asset")}),t.jsx("span",{children:e.displayName})]}),t.jsxs("div",{className:a.detailHeaderActions,children:[t.jsxs("button",{type:"button",className:a.commandButton,onClick:N,children:[t.jsx(_t,{size:15}),p("assets.upload.backToDetails","Back to details")]}),t.jsx(G,{text:p("common.close","Close"),children:t.jsx("button",{type:"button",className:a.iconButton,onClick:l,"aria-label":p("common.close","Close"),children:t.jsx(Ue,{size:16})})})]})]}),t.jsxs("div",{className:a.detailDialogBody,children:[t.jsx("div",{className:a.detailPreviewPane,children:an(e)?t.jsx("img",{className:a.detailPreview,src:st(e),alt:e.displayName}):t.jsxs("div",{className:a.detailPreviewFallback,children:[t.jsx("span",{children:ie(e,p)}),t.jsx("code",{children:e.file.original})]})}),t.jsxs("div",{className:a.detailContentPane,children:[!i&&t.jsx("div",{className:a.notice,children:p("assets.proOnly.upload","Roblox upload is available on Pro.")}),X&&t.jsx("div",{className:a.notice,children:p("assets.upload.checkingSettings","Checking upload settings...")}),W&&t.jsx("div",{className:a.errorState,children:W}),t.jsxs("dl",{className:a.compactMeta,children:[t.jsx("dt",{children:p("assets.detail.category","Category")}),t.jsx("dd",{children:ie(e,p)}),t.jsx("dt",{children:p("assets.detail.source","Source")}),t.jsx("dd",{children:e.source.originalPath})]}),m&&t.jsxs("div",{className:a.setupNotice,children:[t.jsx("strong",{children:p("assets.upload.settingsRequired","Upload settings required")}),t.jsx("p",{children:g?P?p("assets.upload.settingsRequired.creator","Save a default Creator before uploading."):p("assets.upload.settingsRequired.toggle","Enable Open Cloud upload before uploading."):p("assets.upload.settingsRequired.apiKey","Save an Open Cloud API key before uploading.")}),t.jsxs("button",{type:"button",className:a.commandButton,onClick:y,children:[t.jsx(Je,{size:15}),p("assets.upload.openSettings","Open Asset Library settings")]})]}),t.jsxs("div",{className:a.formStack,children:[t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.detail.displayName","Display name")}),t.jsx("input",{value:Z,disabled:!i,onChange:h=>O(h.target.value)}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.displayNameHelp","Saved to Roblox as the asset display name.")})]}),t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.detail.description","Description")}),t.jsx("textarea",{value:Q,rows:3,disabled:!i,onChange:h=>B(h.target.value)}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.descriptionHelp","Saved to Roblox as the asset description.")})]}),te&&t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.upload.creator","Creator")}),t.jsx("select",{"aria-label":p("assets.upload.creator","Creator"),value:ee,disabled:!i||X,onChange:h=>F(h.target.value),children:x==null?void 0:x.creators.map(h=>t.jsx("option",{value:h.id,children:on(h,p)},h.id))}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.creatorHelp","Used by Open Cloud as the owner of the uploaded asset.")})]}),U&&t.jsxs(t.Fragment,{children:[t.jsx("p",{className:a.inlineHelp,children:p("assets.upload.envCreatorHelp","Environment API keys cannot save a default Creator here. Enter the Creator for this upload.")}),t.jsxs("div",{className:a.twoColumn,children:[t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.upload.creatorType","Creator type")}),t.jsxs("select",{value:v,disabled:!i,onChange:h=>b(h.target.value),children:[t.jsx("option",{value:"user",children:p("assets.creator.user","User")}),t.jsx("option",{value:"group",children:p("assets.creator.group","Group")})]}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.creatorTypeHelp","Sent to Open Cloud as the Creator type.")})]}),t.jsxs("label",{className:a.field,children:[t.jsx("span",{children:p("assets.upload.creatorId","Creator ID")}),t.jsx("input",{value:A,disabled:!i,onChange:h=>w(h.target.value)}),t.jsx("small",{className:a.fieldHelp,children:p("assets.upload.creatorIdHelp","Sent to Open Cloud as the User or Group ID that owns the uploaded asset.")})]})]})]}),t.jsx("button",{type:"button",className:a.primaryButton,disabled:!se,onClick:()=>{const h=A.trim(),L=U&&h?{creatorType:v,creatorId:h}:{},D=!U&&C&&r&&C.id!==r.id?{creatorType:C.creatorType,creatorId:C.creatorId}:{};_({displayName:Z,description:Q,...L,...D})},children:n==="upload"?p("assets.upload.uploading","Uploading..."):p("assets.upload.submit","Upload with Roblox Open Cloud")})]}),t.jsxs("div",{className:a.noticeList,children:[t.jsx("p",{children:p("assets.upload.noDelete","WEPPY does not provide Roblox asset deletion.")}),t.jsx("p",{children:p("assets.upload.delay","Roblox processing and moderation can delay visibility in Studio or Creator Dashboard.")})]})]})]})]})})}function Ye(e,s){return e==="env"?s("assets.settings.credential.env","Environment variable"):s("assets.settings.credential.local","Local encrypted file")}function ke(e,s){return e==="valid"?s("assets.settings.validation.valid","Connected"):e==="invalid"?s("assets.settings.validation.invalid","Needs attention"):s("assets.settings.validation.unknown","Not tested")}function ln(e,s){return(e==null?void 0:e.status)==="valid"?s("assets.settings.apiKeyTested","Open Cloud API key connection tested."):(e==null?void 0:e.message)??s("assets.settings.tested","Connection tested.")}function dn(e,s){return(e==null?void 0:e.status)==="valid"?s("assets.settings.apiKeyTested","Open Cloud API key connection tested."):(e==null?void 0:e.message)??s("assets.settings.tested","Connection tested.")}function cn(e,s){return e==="group"?s("assets.creator.group","Group"):s("assets.creator.user","User")}function un(e,s){return`${cn(e.creatorType,s)} ${e.creatorId}`}function pn({open:e,tier:s,onClose:i}){const{t:n}=me(),[l,N]=d.useState(null),[y,_]=d.useState(null),[p,E]=d.useState(""),[Y,T]=d.useState(!1),[x,o]=d.useState(""),[X,z]=d.useState(""),[W,H]=d.useState("user"),[Z,O]=d.useState(""),[Q,B]=d.useState(""),[ee,F]=d.useState(!0),[v,b]=d.useState(null),[A,w]=d.useState(null),[P,g]=d.useState(!1),r=s==="basic",C=d.useCallback(async()=>{g(!0),b(null);try{const[u,I]=await Promise.all([lt(),it()]);N(u),_(I);const R=I.profiles.find(re=>re.id===I.activeProfileId)??I.profiles[0]??null;E((R==null?void 0:R.id)??""),T(!R),F(!R||R.creators.length===0),H("user"),O(""),B("")}catch(u){b(u instanceof Error?u.message:n("assets.settings.loadFailed","Failed to load upload settings."))}finally{g(!1)}},[n]);if(d.useEffect(()=>{e&&C()},[C,e]),!e)return null;const te=(l==null?void 0:l.assetUploadByOpenCloudEnabled)===!0,q=X.trim(),U=Z.trim(),K=(y==null?void 0:y.profiles)??[],m=K.find(u=>u.id===p)??K[0]??null,se=!!m,h=se&&(m==null?void 0:m.storageProvider)==="localFile",L=se&&(m==null?void 0:m.storageProvider)==="env",D=m!=null&&m.defaultCreatorId?m.creators.find(u=>u.id===m.defaultCreatorId):m==null?void 0:m.creators[0],M=!!(m!=null&&m.creators.length),J=!M||ee,ce=K.length>1,oe=r?n("assets.settings.action.proRequired","Asset upload settings are available on Pro."):P?n("assets.settings.action.busy","Wait for the current settings action to finish."):null,_e=r||P||!q,Se=oe??(q?n("assets.settings.saveApiKey.tooltip.ready","Save this API key to local encrypted storage."):n("assets.settings.saveApiKey.tooltip.enter","Enter an Open Cloud API key to save it locally.")),he=r||P||!q&&!se,xe=oe??(q?n("assets.settings.testConnection.tooltip.entered","Test the entered API key before saving it."):se?n("assets.settings.testConnection.tooltip.saved","Test the saved Open Cloud API key."):n("assets.settings.testConnection.tooltip.enterOrSaved","Enter an API key or save one before testing the connection.")),ge=r||P||!h,be=oe??(h?n("assets.settings.removeApiKey.tooltip.ready","Remove the locally saved Open Cloud API key."):L?n("assets.settings.removeApiKey.tooltip.env","Environment API keys cannot be removed from Dashboard. Remove ROBLOX_OPEN_CLOUD_API_KEY outside WEPPY."):n("assets.settings.removeApiKey.tooltip.none","No local Open Cloud API key is saved.")),Ie=r||P||!h||!U,Ne=oe??(L?n("assets.settings.saveCreator.tooltip.env","Environment API keys cannot save a default Creator here. Enter Creator details in the upload dialog."):h?U?n("assets.settings.saveCreator.tooltip.ready","Save this Creator as the default owner for uploads."):n("assets.settings.saveCreator.tooltip.enterId","Enter a user or group ID before saving the default Creator."):n("assets.settings.saveCreator.tooltip.noLocal","Save a local Open Cloud API key before saving a default Creator.")),Ae=oe??(h?n("assets.settings.addCreator.tooltip.ready","Add another User or Group Creator preset to this profile."):n("assets.settings.saveCreator.tooltip.noLocal","Save a local Open Cloud API key before saving a default Creator.")),c=r||P||L||!h,f=oe??(h?n("assets.settings.unregisterCreator.tooltip.ready","Unregister this Creator from the selected profile."):L?n("assets.settings.saveCreator.tooltip.env","Environment API keys cannot save a default Creator here. Enter Creator details in the upload dialog."):n("assets.settings.saveCreator.tooltip.noLocal","Save a local Open Cloud API key before saving a default Creator.")),j=D?n("assets.settings.saveCreatorPreset","Save Creator"):n("assets.settings.saveCreator","Save default Creator"),S=(m==null?void 0:m.label)??n("assets.settings.credential.none","No API key saved"),k=u=>{const I=u.profiles.find(R=>R.id===u.activeProfileId)??u.profiles[0]??null;_(u),E((I==null?void 0:I.id)??""),F(!I||I.creators.length===0),T(u.profiles.length===0)},V=async()=>{if(m){g(!0);try{const u=await tn(m.id,D==null?void 0:D.id);k(u),b(dn(u.validation,n))}catch(u){b(u instanceof Error?u.message:n("assets.settings.testFailed","Connection test failed."))}finally{g(!1)}}},ue=async()=>{if(A){g(!0);try{if(A.kind==="apiKey"){const u=await Za(A.profileId);k(u),b(n("assets.settings.apiKeyRemoved","Open Cloud API key unregistered from local storage."))}else{const u=await en(A.profileId,A.creatorPresetId);k(u),b(n("assets.settings.creatorUnregistered","Creator unregistered from this profile."))}w(null)}catch(u){b(u instanceof Error?u.message:A.kind==="apiKey"?n("assets.settings.removeFailed","Failed to unregister API key."):n("assets.settings.creatorUnregisterFailed","Failed to unregister Creator."))}finally{g(!1)}}},dt=(A==null?void 0:A.kind)==="apiKey"?n("assets.settings.unregisterApiKey.title","Unregister API Key?"):n("assets.settings.unregisterCreator.title","Unregister Creator?"),ct=(A==null?void 0:A.kind)==="apiKey"?n("assets.settings.unregisterApiKey.message","Roblox API key is not revoked. WEPPY only removes the local Credential Profile registration on this device."):n("assets.settings.unregisterCreator.message","Roblox user or group is not deleted. WEPPY only removes this Creator from the selected API Key profile."),ut=(A==null?void 0:A.kind)==="apiKey"?n("assets.settings.removeApiKey","Unregister API Key"):n("assets.settings.unregisterCreator","Unregister Creator");return t.jsxs("section",{id:"asset-library-settings-panel",className:`${a.settingsInlinePanel} ${a.settingsDrawer}`,role:"region","aria-label":n("assets.settings.title","Asset Library settings"),"data-panel-placement":"toolbar-popover",children:[t.jsxs("div",{className:a.drawerHeader,children:[t.jsxs("div",{children:[t.jsx("h2",{children:n("assets.settings.title","Asset Library settings")}),t.jsx("span",{children:S})]}),t.jsx(G,{text:n("common.close","Close"),children:t.jsx("button",{type:"button",className:a.iconButton,onClick:i,"aria-label":n("common.close","Close"),children:t.jsx(Ue,{size:16})})})]}),r&&t.jsx("div",{className:`${a.notice} ${a.proNotice}`,children:n("assets.settings.proOnly","Roblox upload settings and Open Cloud credential controls are available on Pro.")}),t.jsxs("section",{className:a.settingsPanel,children:[t.jsxs("label",{className:a.toggleRow,children:[t.jsxs("span",{children:[t.jsx("strong",{children:n("assets.settings.openCloudToggle","Open Cloud upload")}),t.jsx("small",{children:n("assets.settings.openCloudToggle.help","Controls whether server-side Open Cloud upload mutations can run.")})]}),t.jsx(vt,{checked:te,disabled:r||P,onChange:u=>{(async()=>{g(!0);try{const I=await Va({assetUploadByOpenCloudEnabled:u.target.checked});N(I),b(n("assets.settings.saved","Upload settings saved."))}catch(I){b(I instanceof Error?I.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}})()}})]}),ce&&t.jsx("div",{className:a.metadataList,children:K.map(u=>{const I=u.id===(m==null?void 0:m.id);return t.jsxs("div",{className:a.metadataItem,children:[t.jsx("strong",{children:u.label}),t.jsxs("span",{children:[n("assets.settings.field.storage","Storage"),": ",Ye(u.storageProvider,n)]}),t.jsxs("span",{children:[n("assets.settings.field.validationStatus","Validation status"),": ",ke(u.validationStatus,n)]}),I&&t.jsx("code",{children:n("assets.settings.activeProfileBadge","Active")}),!I&&u.storageProvider==="localFile"&&t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P,onClick:()=>{(async()=>{g(!0);try{const R=await Xa(u.id),re=R.profiles.find(Pe=>Pe.id===(R.activeProfileId??u.id))??u;_(R),E(re.id),F(re.creators.length===0),H("user"),O(""),B(""),b(n("assets.settings.profileSelected","Open Cloud credential profile selected."))}catch(R){b(R instanceof Error?R.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}})()},children:n("assets.settings.useProfile","Use profile")})]},u.id)})}),m&&t.jsxs("div",{className:a.settingsSubsection,children:[t.jsx("div",{className:a.settingsSectionHeader,children:t.jsx("h3",{children:n("assets.settings.credentialProfile","Credential Profile")})}),t.jsxs("div",{className:a.metadataItem,children:[t.jsxs("dl",{className:a.settingsDefinitionList,children:[t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.profile","Profile")}),t.jsx("dd",{children:m.label})]}),m.maskedKey&&t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.apiKey","API Key")}),t.jsx("dd",{children:m.maskedKey})]}),t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.storage","Storage")}),t.jsx("dd",{children:Ye(m.storageProvider,n)})]}),t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.validationStatus","Validation status")}),t.jsx("dd",{children:ke(m.validationStatus,n)})]}),t.jsxs("div",{children:[t.jsx("dt",{children:n("assets.settings.field.creators","Creators")}),t.jsx("dd",{children:m.creators.length})]})]}),!Y&&t.jsxs("div",{className:a.buttonRow,children:[t.jsx(G,{text:xe,children:t.jsx("button",{type:"button",className:a.commandButton,disabled:he,onClick:()=>{V()},children:n("assets.settings.testConnection","Test Connection")})}),h&&t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P,onClick:()=>T(!0),children:n("assets.settings.replaceApiKey","Replace API Key")}),t.jsx(G,{text:be,children:t.jsx("button",{type:"button",className:`${a.commandButton} ${a.dangerButton}`,disabled:ge,onClick:()=>w({kind:"apiKey",profileId:m.id}),children:n("assets.settings.removeApiKey","Unregister API Key")})})]})]})]}),Y&&t.jsxs("div",{className:a.formStack,children:[t.jsxs("div",{className:a.field,children:[t.jsx("div",{className:a.fieldLabelRow,children:t.jsx("label",{htmlFor:"asset-settings-open-cloud-profile-label",children:n("assets.settings.profileLabel","Profile name")})}),t.jsx("input",{id:"asset-settings-open-cloud-profile-label",value:x,disabled:r||P,onChange:u=>o(u.target.value),placeholder:n("assets.settings.profileLabel.placeholder","Studio automation key")}),t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.profileLabel.help","Optional. If left blank, WEPPY saves this profile as Open Cloud key automatically.")})]}),t.jsxs("div",{className:a.field,children:[t.jsxs("div",{className:a.fieldLabelRow,children:[t.jsx("label",{htmlFor:"asset-settings-open-cloud-api-key",children:n("assets.settings.apiKey","Open Cloud API Key")}),t.jsx(Ee,{topicId:"openCloudApiKey",variant:"field",state:{hasOpenCloudCredential:se}})]}),t.jsx("input",{id:"asset-settings-open-cloud-api-key",value:X,type:"password",disabled:r||P,onChange:u=>z(u.target.value)}),t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.apiKey.inlineHelp","WEPPY uses this key only for Roblox Open Cloud requests. The key is encrypted on this device and is not sent to WEPPY servers or stored in any other external storage.")})]}),!se&&t.jsx("p",{className:a.inlineHelp,children:t.jsx("a",{href:yt["open_cloud.api_key"].docsUrl,target:"_blank",rel:"noreferrer",children:n("assets.settings.apiKeyGuide","Create a Roblox API key with Assets Read and Write permissions.")})}),t.jsxs("div",{className:a.buttonRow,children:[t.jsx(G,{text:Se,children:t.jsx("button",{type:"button",className:a.commandButton,disabled:_e,onClick:()=>{(async()=>{var u;g(!0);try{const I={apiKey:q,...x.trim()?{label:x.trim()}:{}},R=(m==null?void 0:m.storageProvider)==="localFile"?await qa(m.id,I):await Ya(I),re=R.profiles.find(Pe=>{var De;return Pe.id===(R.activeProfileId??((De=R.profile)==null?void 0:De.id))});_(R),E(R.activeProfileId??((u=R.profile)==null?void 0:u.id)??""),F(!re||re.creators.length===0),T(!1),z(""),o(""),b(n("assets.settings.apiKeySaved","Open Cloud API key saved locally."))}catch(I){b(I instanceof Error?I.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}})()},children:n("assets.settings.saveApiKey","Save API Key")})}),t.jsx(G,{text:xe,children:t.jsx("button",{type:"button",className:a.commandButton,disabled:he,onClick:()=>{(async()=>{g(!0);try{const u=await sn(q||void 0);b(ln(u.validation,n))}catch(u){b(u instanceof Error?u.message:n("assets.settings.testFailed","Connection test failed."))}finally{g(!1)}})()},children:n("assets.settings.testConnection","Test Connection")})}),t.jsx(G,{text:be,children:t.jsx("button",{type:"button",className:`${a.commandButton} ${a.dangerButton}`,disabled:ge,onClick:()=>{m&&w({kind:"apiKey",profileId:m.id})},children:n("assets.settings.removeApiKey","Unregister API Key")})})]})]}),t.jsx("div",{className:a.metadataList,children:m==null?void 0:m.creators.map(u=>t.jsxs("div",{className:a.metadataItem,children:[t.jsx("strong",{children:u.label}),t.jsx("span",{children:un(u,n)}),u.id===m.defaultCreatorId&&t.jsx("code",{children:n("assets.settings.defaultCreatorBadge","Default")}),t.jsxs("span",{children:[n("assets.settings.field.validationStatus","Validation status"),": ",ke(u.validationStatus,n)]}),t.jsxs("div",{className:a.buttonRow,children:[u.id!==m.defaultCreatorId&&m.storageProvider==="localFile"&&t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P,onClick:()=>{(async()=>{if(m){g(!0);try{const I=await Qa(m.id,u.id);_(I),b(n("assets.settings.defaultCreatorSaved","Open Cloud default Creator saved locally."))}catch(I){b(I instanceof Error?I.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}}})()},children:n("assets.settings.makeDefaultCreator","Make default")}),t.jsx(G,{text:f,children:t.jsx("button",{type:"button",className:`${a.commandButton} ${a.dangerButton}`,disabled:c,onClick:()=>w({kind:"creator",profileId:m.id,creatorPresetId:u.id}),children:n("assets.settings.unregisterCreator","Unregister Creator")})})]})]},u.id))}),M&&!ee&&t.jsx(G,{text:Ae,children:t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P||L||!h,onClick:()=>{H("user"),O(""),B(""),F(!0)},children:n("assets.settings.addCreator","Add Creator")})}),J&&t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:a.twoColumn,children:[t.jsxs("div",{className:a.field,children:[t.jsx("div",{className:a.fieldLabelRow,children:t.jsx("label",{htmlFor:"asset-settings-creator-type",children:n("assets.upload.creatorType","Creator type")})}),t.jsxs("select",{id:"asset-settings-creator-type",value:W,disabled:r||P||L||!h,onChange:u=>H(u.target.value),children:[t.jsx("option",{value:"user",children:n("assets.creator.user","User")}),t.jsx("option",{value:"group",children:n("assets.creator.group","Group")})]})]}),t.jsxs("div",{className:a.field,children:[t.jsxs("div",{className:a.fieldLabelRow,children:[t.jsx("label",{htmlFor:"asset-settings-creator-id",children:n("assets.upload.creatorId","Creator ID")}),t.jsx(Ee,{topicId:"openCloudCreatorId",variant:"field",state:{hasDefaultCreator:!!D}})]}),t.jsx("input",{id:"asset-settings-creator-id",value:Z,disabled:r||P||L||!h,onChange:u=>O(u.target.value)}),t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.creatorId.inlineHelp","Default owner for new Roblox assets: your User ID or a Group ID.")})]})]}),t.jsxs("div",{className:a.field,children:[t.jsx("div",{className:a.fieldLabelRow,children:t.jsx("label",{htmlFor:"asset-settings-creator-label",children:n("assets.settings.creatorLabel","Creator label")})}),t.jsx("input",{id:"asset-settings-creator-label",value:Q,disabled:r||P||L||!h,onChange:u=>B(u.target.value),placeholder:n("assets.settings.creatorLabel.placeholder","Main studio group")}),t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.creatorLabel.help","Optional. If left blank, WEPPY automatically saves a label like User 123 or Group 456.")})]}),!D&&t.jsx("p",{className:a.inlineHelp,children:n("assets.settings.creatorHelp","Use the numeric user ID from a profile URL or group ID from a group URL.")}),t.jsxs("div",{className:a.buttonRow,children:[t.jsx(G,{text:Ne,children:t.jsx("button",{type:"button",className:a.primaryButton,disabled:Ie,onClick:()=>{(async()=>{if(m){g(!0);try{const u=await Ja(m.id,{creatorType:W,creatorId:U,makeDefault:!D,...Q.trim()?{label:Q.trim()}:{}});_(u),O(""),B(""),F(!1),b(n("assets.settings.defaultCreatorSaved","Open Cloud default Creator saved locally."))}catch(u){b(u instanceof Error?u.message:n("assets.settings.saveFailed","Failed to save upload settings."))}finally{g(!1)}}})()},children:j})}),M&&t.jsx("button",{type:"button",className:a.commandButton,disabled:r||P,onClick:()=>{H("user"),O(""),B(""),F(!1)},children:n("assets.settings.cancelCreator","Cancel")})]})]})]}),v&&t.jsx("div",{className:a.messageState,children:v}),t.jsx(Qe,{open:A!==null,title:dt,message:ct,cancelLabel:n("common.cancel","Cancel"),confirmLabel:ut,loading:P,onCancel:()=>w(null),onConfirm:()=>{ue()}})]})}const mn=12,hn=5e3;function le(e,s){return e instanceof Error&&e.message.trim().length>0?e.message:s}function Re(e,s){return e.some(n=>n.id===s.id)?e.map(n=>n.id===s.id?s:n):[s,...e]}function $e(e,s){return Jt(e.filter(i=>Zt(i,s)))}function pe(e,s){return e?`${e.displayName} (${e.id})`:s??"unknown asset"}function xn(e){return e.length===0?"none":e.map(s=>pe(s)).join(", ")}function Xe(e){const s=`status ${e.status}`;return e.roblox.assetId?`Roblox asset ${e.roblox.assetId}; ${s}`:s}function gn(e,s){const i=pe(s);return e==="update"?`Updated metadata for asset: ${i}.`:e==="upload"?`Uploaded asset: ${i} -> ${Xe(s)}.`:e==="thumbnail-generate"?`Generated thumbnail for asset: ${i}.`:e==="status-refresh"?`Refreshed Roblox status for asset: ${i} -> ${Xe(s)}.`:e==="usage-scan"?`Scanned usage for asset: ${i} -> ${s.usage.references.length} reference(s).`:`Updated asset: ${i}.`}function bn(e){return e!=="upload"&&e!=="status-refresh"}function we(e,s){if((s==null?void 0:s.id)===e)return s.category;const i=/^asset_(image|decal|audio|mesh|model|video|animation)_/.exec(e);return i!=null&&i[1]?i[1]:null}function qe(e){return e.status==="processing"&&!!(e.roblox.operationId??e.roblox.operationPath)}function fn(e){return{scope:e.scope.kind,placeId:e.scope.kind==="place"?e.scope.placeId:void 0,category:e.category}}function yn(e){if(e.pluginConnected&&e.activePlaceId!==null)return{placeId:e.activePlaceId,placeName:e.activePlaceName,studioConnected:!0};if(e.lastActivePlaceId!==null)return{placeId:e.lastActivePlaceId,placeName:e.lastActivePlaceName,studioConnected:!1};const s=e.places[0];return{placeId:(s==null?void 0:s.placeId)??null,placeName:(s==null?void 0:s.placeName)??null,studioConnected:!1}}function jn(e,s){if(typeof s=="number"){const i=e.places.find(n=>n.placeId===s);if(i)return{placeId:i.placeId,placeName:i.placeName,studioConnected:i.isConnected,overrideStillValid:!0}}return{...yn(e),overrideStillValid:s===null}}function vn(){const[e,s]=d.useState([]),[i,n]=d.useState(0),[l,N]=d.useState(null),[y,_]=d.useState("place"),[p,E]=d.useState("all"),[Y,T]=d.useState([]),[x,o]=d.useState(null),[X,z]=d.useState(null),[W,H]=d.useState(null),[Z,O]=d.useState(null),[Q,B]=d.useState(!1),[ee,F]=d.useState(!1),[v,b]=d.useState(!0),[A,w]=d.useState(null),[P,g]=d.useState(null),[r,C]=d.useState(null),te=d.useRef(!0),q=d.useRef(new Map),U=d.useMemo(()=>e.find(c=>c.id===l)??null,[e,l]),K=d.useCallback(c=>{const f=q.current.get(c);f!==void 0&&(clearTimeout(f),q.current.delete(c))},[]),m=d.useCallback((c,f=mn)=>{if(!qe(c)||f<=0){K(c.id);return}K(c.id),(async()=>{try{const j=await Oe(fn(c),c.id);if(!te.current)return;if(s(S=>Re(S,j)),qe(j)&&f>1){const S=setTimeout(()=>{q.current.delete(j.id),m(j,f-1)},hn);q.current.set(j.id,S);return}K(j.id)}catch(j){if(!te.current)return;K(c.id),g(le(j,"Asset Library status refresh failed."))}})()},[K]);d.useEffect(()=>()=>{te.current=!1;for(const c of q.current.values())clearTimeout(c);q.current.clear()},[]);const se=d.useCallback(()=>({scope:y,placeId:y==="place"?W:void 0}),[W,y]),h=d.useCallback(c=>({...se(),category:c}),[se]),L=d.useCallback(async()=>{try{const c=await gt(),f=jn(c,x);return T(c.places),f.overrideStillValid||o(null),z(f.placeId),H(f.placeId),O(f.placeName),B(f.studioConnected),F(f.studioConnected),f.placeId}catch{return T([]),z(null),H(null),O(null),B(!1),F(!1),null}},[x]),D=d.useCallback(async()=>{g(null);try{const c=await L(),f={scope:y,placeId:y==="place"?c:void 0};if(y==="place"&&c===null){s([]),n(0),b(!1),g("No active place is connected for place-scoped assets.");return}const j=await Promise.all(Me(p).map(k=>Ft({...f,category:k}))),S=$e(j.flatMap(k=>k.assets),p);s(S),n(S.length)}catch(c){g(le(c,"Failed to load Asset Library."))}finally{b(!1)}},[p,L,y]);d.useEffect(()=>{D()},[D]);const M=d.useCallback(async(c,f,j)=>{const S=we(f,U);if(!S)return g("Asset category is unavailable."),null;w(c),g(null),C(null);try{const k=await j(h(S));return s(V=>Re(V,k)),N(k.id),bn(c)&&C(gn(c,k)),k}catch(k){return g(le(k,"Asset Library action failed.")),null}finally{w(null)}},[h,U]),J=d.useCallback(async()=>{w("rescan"),g(null),C(null);try{const c=await Promise.all(Me(p).map(V=>Mt(h(V)))),f=$e(c.flatMap(V=>V.assets),p),j=c.reduce((V,ue)=>V+ue.adoptedCount,0),S=c.reduce((V,ue)=>V+ue.skippedCount,0),k=$e(c.flatMap(V=>V.adopted),p);s(f),n(f.length),C(`Rescan complete for ${p}: ${j} asset(s) added, ${S} skipped. Added: ${xn(k)}.`)}catch(c){g(le(c,"Asset Library rescan failed."))}finally{w(null)}},[p,h]),ce=d.useCallback(async(c,f)=>{w("export-selection-rbxm"),g(null),C(null);try{const j=await Wt(h(c),f);return s(S=>Re(S,j.asset)),N(j.asset.id),C(`Exported Studio selection as RBXM asset: ${pe(j.asset)}${j.deduplicated?" (reused existing local asset)":""}.`),j}catch(j){return g(le(j,"Asset Library .rbxm export failed.")),null}finally{w(null)}},[h]),oe=d.useCallback((c,f)=>M("update",c,j=>Ht(j,c,f)),[M]),_e=d.useCallback(async(c,f)=>{const j=await M("upload",c,S=>Gt(S,c,f));return j&&m(j),j},[M,m]),Se=d.useCallback(async c=>{const f=we(c,U);if(!f)return g("Asset category is unavailable."),!1;K(c);const j=e.find(S=>S.id===c)??U;w("delete"),g(null),C(null);try{return await Kt(h(f),c),s(S=>{const k=S.filter(V=>V.id!==c);return n(k.length),k}),N(S=>S===c?null:S),C(`Deleted asset: ${pe(j,c)}. Local files removed; uploaded Roblox assets were not deleted.`),!0}catch(S){return g(le(S,"Asset Library delete failed.")),!1}finally{w(null)}},[e,K,h,U]),he=d.useCallback(async(c,f)=>{const j=we(c,U);if(!j)return g("Asset category is unavailable."),null;const S=e.find(k=>k.id===c)??U;w("import-rbxm"),g(null),C(null);try{const k=await Vt(h(j),c,f);return N(c),C(`Imported RBXM asset: ${pe(S,c)} -> ${k.importedCount} instance(s) to ${k.targetParent}.`),k}catch(k){return g(le(k,"Asset Library .rbxm import failed.")),null}finally{w(null)}},[e,h,U]),xe=d.useCallback(c=>M("thumbnail-generate",c,f=>Yt(f,c)),[M]),ge=d.useCallback(c=>(K(c),M("status-refresh",c,f=>Oe(f,c))),[K,M]),be=d.useCallback((c,f)=>M("usage-scan",c,async j=>(await zt(j,c,f)).asset),[M]),Ie=d.useCallback(c=>{_(c),N(null)},[]),Ne=d.useCallback(c=>{o(c),N(null)},[]),Ae=d.useCallback(c=>{qt(c)&&(E(c),N(null))},[]);return{assets:e,totalCount:i,selectedAsset:U,selectedAssetId:l,scope:y,categoryFilter:p,availablePlaces:Y,selectedPlaceId:X,activePlaceId:W,activePlaceName:Z,selectedPlaceIsConnected:Q,studioConnected:ee,loading:v,busyAction:A,error:P,lastMessage:r,setScope:Ie,setSelectedPlaceId:Ne,setCategoryFilter:Ae,selectAsset:N,refresh:D,rescan:J,exportSelectionRbxm:ce,updateMetadata:oe,uploadAsset:_e,deleteAsset:Se,importRbxm:he,generateThumbnail:xe,refreshStatus:ge,scanUsage:be}}function Cn(e,s){return s("assets.count.shown","Shown assets: {count}").replace("{count}",String(e))}function _n(e,s){return e===null?null:s("assets.place.id","Place ID {placeId}").replace("{placeId}",String(e))}function $n(){const{t:e}=me(),{trackEvent:s}=bt(),{tier:i,loading:n}=ft(),l=vn(),[N,y]=d.useState(!1),[_,p]=d.useState(!1),[E,Y]=d.useState(!1),T=!n&&i==="pro",x=l.selectedAsset,o=(x==null?void 0:x.file.original.toLowerCase().endsWith(".rbxm"))??!1,X=(x==null?void 0:x.category)==="model"||(x==null?void 0:x.category)==="animation",z="game.Workspace",H=!!(T&&l.studioConnected&&x&&o&&X),Z=l.availablePlaces??[],O=l.selectedPlaceId??l.activePlaceId,Q=d.useMemo(()=>l.scope==="shared"?[e("assets.scope.shared","Shared")]:[l.activePlaceName??e("assets.scope.place","Current Place"),_n(l.activePlaceId,e),l.selectedPlaceIsConnected?e("assets.place.connected","Connected"):null].filter(v=>!!v),[l.activePlaceId,l.activePlaceName,l.scope,l.selectedPlaceIsConnected,e]),B=d.useMemo(()=>Le(l.categoryFilter,e),[l.categoryFilter,e]),ee=Cn(l.totalCount,e),F=e("assets.detail.importRbxm.tooltip","Insert this local RBXM asset into {target} in the connected Studio place.").replace("{target}",z);return t.jsxs("div",{className:a.page,children:[t.jsx(jt,{title:e("assets.title","Assets"),description:e("assets.subtitle","Browse local originals, upload to Roblox, and inspect synced usage by place."),badge:t.jsx("span",{className:a.experimentalBadge,children:e("assets.experimental","Experimental")}),helpTopicId:"assets",helpState:{tier:i}}),t.jsxs("div",{className:a.toolbarShell,children:[t.jsxs("div",{className:a.toolbar,children:[t.jsxs("div",{className:a.segmented,role:"group","aria-label":e("assets.scope.label","Asset scope"),children:[t.jsx("button",{type:"button",className:l.scope==="place"?a.segmentedActive:"",onClick:()=>l.setScope("place"),children:e("assets.scope.place","Current Place")}),t.jsx("button",{type:"button",className:l.scope==="shared"?a.segmentedActive:"",onClick:()=>l.setScope("shared"),children:e("assets.scope.shared","Shared")})]}),l.scope==="place"&&Z.length>0?t.jsxs("label",{className:a.placeSelectorLabel,children:[t.jsx("span",{children:e("assets.place.selector","Asset place")}),t.jsx("select",{className:a.placeSelect,value:typeof O=="number"?String(O):"",onChange:v=>{const b=Number.parseInt(v.currentTarget.value,10);Number.isInteger(b)&&l.setSelectedPlaceId(b)},children:Z.map(v=>t.jsxs("option",{value:v.placeId,children:[v.placeName," (",v.placeId,")"]},v.placeId))})]}):null,t.jsxs("div",{className:a.listContextSummary,children:[Q.map((v,b)=>t.jsxs("span",{children:[b>0?t.jsx("span",{className:a.contextDivider,children:" · "}):null,v]},`${v}-${b}`)),t.jsx("span",{className:a.contextDivider,children:" · "}),t.jsx("span",{children:B}),t.jsx("span",{className:a.contextDivider,children:" · "}),t.jsx("strong",{children:ee})]}),t.jsxs("div",{className:a.toolbarActions,children:[t.jsx(G,{text:e("assets.rescan.tooltip","Scan inbox folders for the current filter."),children:t.jsxs("button",{type:"button",className:a.commandButton,disabled:l.busyAction==="rescan",onClick:()=>{s("dashboard_click_event",{click_target:"assets_rescan",page:"assets"}),l.rescan()},children:[t.jsx(Ze,{size:15}),e("assets.rescan","Rescan")]})}),t.jsx(G,{text:_?"":e("assets.settings.open.tooltip","Open Roblox upload settings."),children:t.jsx("button",{type:"button",className:[a.iconButton,_?a.iconButtonActive:""].filter(Boolean).join(" "),onClick:()=>{s("dashboard_click_event",{click_target:"assets_open_settings",page:"assets"}),p(v=>!v)},"aria-label":e("assets.settings.open","Open settings"),"aria-controls":"asset-library-settings-panel","aria-expanded":_,children:t.jsx(Je,{size:16})})})]}),t.jsxs("div",{className:a.categoryControl,children:[t.jsx("span",{id:"assets-category-filter-label",className:a.categoryControlLabel,children:e("assets.category.filter","Category")}),t.jsx("div",{className:a.categoryRail,role:"radiogroup","aria-labelledby":"assets-category-filter-label",children:nt.map(v=>{const b=l.categoryFilter===v,A=Le(v,e);return t.jsx("button",{type:"button",role:"radio","aria-checked":b,className:[a.categoryButton,b?a.categoryButtonActive:""].filter(Boolean).join(" "),onClick:()=>{l.setCategoryFilter(v)},children:A},v)})})]})]}),t.jsx(pn,{open:_,tier:i,onClose:()=>p(!1)})]}),l.error&&t.jsx("div",{className:a.errorState,children:l.error}),l.lastMessage&&t.jsx("div",{className:a.messageState,children:l.lastMessage}),l.categoryFilter==="rbxm"&&t.jsxs("section",{className:a.rbxmGuide,"aria-label":e("assets.rbxmGuide.title","Save RBXM from Studio"),children:[t.jsx("h2",{children:e("assets.rbxmGuide.title","Save RBXM from Studio")}),t.jsx("p",{children:e("assets.rbxmGuide.body","Select objects in Roblox Studio, then use WEPPY Plugin > Assets to save the selection as a local RBXM asset.")}),t.jsx("p",{children:e("assets.rbxmGuide.thumbnail","The plugin save flow includes a thumbnail option, and saved RBXM assets appear here for management, upload, and insertion.")})]}),!T&&!n&&t.jsx("div",{className:`${a.notice} ${a.proNotice}`,children:e("assets.basic.notice","Browse, preview, edit metadata, and scan usage on Basic. Roblox upload controls are available on Pro.")}),l.loading?t.jsx("div",{className:a.emptyState,children:e("common.loading","Loading...")}):t.jsx(Ra,{assets:l.assets,selectedAssetId:l.selectedAssetId,onSelect:l.selectAsset}),t.jsx(za,{asset:N||_||E?null:x,busyAction:l.busyAction,canUpload:T,canImportRbxm:H,importRbxmTooltip:F,importRbxmTargetParent:z,onClose:()=>l.selectAsset(null),onSave:async(v,b)=>{x&&await l.updateMetadata(x.id,{displayName:v,description:b})},onUpload:()=>y(!0),onDelete:()=>Y(!0),onImportRbxm:async()=>{x&&(s("dashboard_click_event",{click_target:"assets_import_rbxm",page:"assets"}),await l.importRbxm(x.id,{targetParent:z}))},onRefreshStatus:async()=>{x&&await l.refreshStatus(x.id)},onScanUsage:async()=>{x&&(s("dashboard_click_event",{click_target:"assets_usage_scan",page:"assets"}),await l.scanUsage(x.id,l.activePlaceId??void 0))}}),t.jsx(Qe,{open:E&&!!x,title:e("assets.delete.title","Delete asset"),message:e("assets.delete.message","This removes the local Asset Library files only. Uploaded Roblox assets are not deleted."),cancelLabel:e("common.cancel","Cancel"),confirmLabel:e("common.delete","Delete"),loading:l.busyAction==="delete",onCancel:()=>Y(!1),onConfirm:()=>{x&&(s("dashboard_click_event",{click_target:"assets_delete",page:"assets"}),l.deleteAsset(x.id).then(v=>{v&&Y(!1)}))}}),t.jsx(rn,{asset:x,open:N,canUpload:T,busyAction:l.busyAction,onClose:()=>{y(!1),l.selectAsset(null)},onBack:()=>y(!1),onOpenSettings:()=>{y(!1),p(!0)},onUpload:async v=>{if(!x)return;s("dashboard_click_event",{click_target:"assets_upload_submit",page:"assets"}),await l.uploadAsset(x.id,v)&&y(!1)}})]})}export{$n as Component};
@@ -0,0 +1 @@
1
+ import{r as c,a as O,u as P,b as U,c as H,d as q,j as e}from"./index-C8kXDvHv.js";import{I as W}from"./InfoLabel-dwgFWAxs.js";import{G as Y}from"./GameChangeDetail-raYOxmZc.js";import{T as u}from"./TooltipText-DLPk69aK.js";import{B as z}from"./UiPrimitive-jQZP77uI.js";function J(t){const s={scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0};for(const r of t)switch(r.category){case"script":r.changeType==="create"?s.scriptsCreated++:s.scriptsModified++;break;case"instance":r.changeType==="create"?s.instancesCreated++:r.changeType==="delete"?s.instancesDeleted++:r.changeType==="move"&&s.instancesMoved++;break;case"property":s.propertiesChanged++;break;case"lighting":s.lightingChanged=!0;break;case"terrain":s.terrainChanged=!0;break;case"asset":s.assetsInserted++;break}return s}function Q(t){if(typeof t=="number")return{placeId:String(t)}}function X(t,s){const[r,p]=c.useState(""),[L,a]=c.useState(""),[h,w]=c.useState(),[y,B]=c.useState("completed"),[$,M]=c.useState([]),[v,R]=c.useState([]),[A,G]=c.useState([]),[K,V]=c.useState(),[S,C]=c.useState(),[b,N]=c.useState(),[T,k]=c.useState({scriptsModified:0,scriptsCreated:0,instancesCreated:0,instancesDeleted:0,instancesMoved:0,propertiesChanged:0,lightingChanged:!1,terrainChanged:!1,assetsInserted:0}),[I,x]=c.useState(!0),[E,f]=c.useState(null),g=c.useCallback(async()=>{if(t){x(!0),f(null);try{const m=Q(s),[d,_]=await Promise.all([m?O.get(`/api/dashboard/changelog/${t}`,m):O.get(`/api/dashboard/changelog/${t}`),m?O.get(`/api/dashboard/changelog/${t}/changes`,m):O.get(`/api/dashboard/changelog/${t}/changes`)]);p(d.entryId),a(d.startTime),w(d.endTime),B(d.status),M(d.entries),R(d.failures),V(d.contextSummary),C(d.replayMetadata),N(d.verificationSummary),G(_.changes),k(J(_.changes))}catch(m){f(m instanceof Error?m.message:"Failed to load changelog detail")}finally{x(!1)}}},[t,s]);return c.useEffect(()=>{g()},[g]),{entryId:r,startTime:L,endTime:h,status:y,entries:$,failures:v,changes:A,changeSummary:T,contextSummary:K,replayMetadata:S,verificationSummary:b,loading:I,error:E,refresh:g}}const Z={script:"📝",instance:"🧱",property:"🎨",lighting:"🌅",terrain:"⛰️",asset:"📦"};function ee(t){return Z[t]??"❓"}const te="_page_11hjw_2",ne="_header_11hjw_10",ae="_backLink_11hjw_16",se="_headerTitle_11hjw_29",ie="_headerTime_11hjw_37",ce="_statusActive_11hjw_44",re="_statusCompleted_11hjw_49",oe="_section_11hjw_54",le="_sectionTitle_11hjw_61",de="_summaryGrid_11hjw_74",me="_summaryCard_11hjw_80",he="_summaryCardActive_11hjw_94",ge="_summaryIcon_11hjw_99",ue="_summaryCount_11hjw_105",pe="_summaryLabel_11hjw_112",ye="_contextGrid_11hjw_121",xe="_contextRow_11hjw_127",fe="_contextKey_11hjw_133",_e="_contextValue_11hjw_141",je="_timelineFilter_11hjw_149",we="_filterLabel_11hjw_157",ve="_filterSelect_11hjw_163",Se="_ownershipToggle_11hjw_173",Ce="_timeline_11hjw_149",be="_timelineEntry_11hjw_201",Ne="_timelineTime_11hjw_218",Te="_timelineIcon_11hjw_226",ke="_timelineBody_11hjw_231",Ie="_timelineSummary_11hjw_236",Ee="_timelineTarget_11hjw_243",Oe="_timelineConfidence_11hjw_250",Le="_ownershipBadge_11hjw_259",Be="_confidenceExact_11hjw_267",$e="_confidencePartial_11hjw_272",Me="_confidenceAfterOnly_11hjw_277",Re="_confidenceIntentOnly_11hjw_282",Ae="_confidenceUnknown_11hjw_287",Ge="_timelineExpanded_11hjw_293",Ke="_empty_11hjw_365",Ve="_loading_11hjw_374",Fe="_error_11hjw_383",n={page:te,header:ne,backLink:ae,headerTitle:se,headerTime:ie,statusActive:ce,statusCompleted:re,section:oe,sectionTitle:le,summaryGrid:de,summaryCard:me,summaryCardActive:he,summaryIcon:ge,summaryCount:ue,summaryLabel:pe,contextGrid:ye,contextRow:xe,contextKey:fe,contextValue:_e,timelineFilter:je,filterLabel:we,filterSelect:ve,ownershipToggle:Se,timeline:Ce,timelineEntry:be,timelineTime:Ne,timelineIcon:Te,timelineBody:ke,timelineSummary:Ie,timelineTarget:Ee,timelineConfidence:Oe,ownershipBadge:Le,confidenceExact:Be,confidencePartial:$e,confidenceAfterOnly:Me,confidenceIntentOnly:Re,confidenceUnknown:Ae,timelineExpanded:Ge,empty:Ke,loading:Ve,error:Fe},D=[{key:"script",icon:"📝",labelKey:"changelog.category.script"},{key:"instance",icon:"🧱",labelKey:"changelog.category.instance"},{key:"property",icon:"🎨",labelKey:"changelog.category.property"},{key:"lighting",icon:"🌅",labelKey:"changelog.category.lighting"},{key:"terrain",icon:"⛰️",labelKey:"changelog.category.terrain"},{key:"asset",icon:"📦",labelKey:"changelog.category.asset"}];function F(t){if(!t)return"--:--";const s=new Date(t);return`${String(s.getHours()).padStart(2,"0")}:${String(s.getMinutes()).padStart(2,"0")}`}function De(t){if(!t)return"--:--:--";const s=new Date(t);return`${String(s.getHours()).padStart(2,"0")}:${String(s.getMinutes()).padStart(2,"0")}:${String(s.getSeconds()).padStart(2,"0")}`}function Pe(t,s){if(!t||!s)return"";const r=new Date(s).getTime()-new Date(t).getTime();return r<0?"":`${Math.round(r/6e4)}min`}function Ue(t){switch(t){case"exact":return n.confidenceExact;case"partial":return n.confidencePartial;case"after-only":return n.confidenceAfterOnly;case"intent-only":return n.confidenceIntentOnly;default:return n.confidenceUnknown}}function He(t,s){switch(s){case"exact":return t("changelog.detail.confidence.exact","Exact");case"partial":return t("changelog.detail.confidence.partial","Partial");case"after-only":return t("changelog.detail.confidence.afterOnly","After only");case"intent-only":return t("changelog.detail.confidence.intentOnly","Intent only");default:return t("changelog.detail.confidence.unknown","Unknown")}}function qe(t,s){switch(s){case"exact":return t("changelog.detail.confidence.exact.tooltip","Both the before and after state were confirmed for this change.");case"partial":return t("changelog.detail.confidence.partial.tooltip","Only part of the before and after state could be confirmed for this change.");case"after-only":return t("changelog.detail.confidence.afterOnly.tooltip","Only the resulting state after the change could be confirmed.");case"intent-only":return t("changelog.detail.confidence.intentOnly.tooltip","Only the requested action was recorded, not the resulting state.");default:return t("changelog.detail.confidence.unknown.tooltip","This change could not be confidently classified from the available data.")}}function We(t,s){switch(s){case"user_source":return t("changelog.ownership.userSource","User source");case"canonical_mirror":return t("changelog.ownership.canonicalMirror","Mirror metadata");case"generated":return t("changelog.ownership.generated","Generated");default:return null}}function Ye(t){const s=new URLSearchParams(t).get("placeId");if(!s)return null;const r=Number.parseInt(s,10);return Number.isInteger(r)&&r>=0?r:null}function et(){var S,C,b,N,T,k,I,x,E,f,g,m,d,_;const{t}=P(),{id:s}=U(),r=H(),p=q(),L=c.useMemo(()=>Ye(p.search),[p.search]),a=X(s,L),[h,w]=c.useState("all"),[y,B]=c.useState(!0),[$,M]=c.useState(null),v=c.useMemo(()=>{const i=y?a.changes:a.changes.filter(o=>o.artifactOwnership!=="generated");return[...h==="all"?i:i.filter(o=>o.category===h)].reverse()},[a.changes,h,y]),R=a.changes.some(i=>i.artifactOwnership==="generated");if(a.loading)return e.jsx("div",{className:n.loading,children:t("common.loading","Loading...")});if(a.error)return e.jsxs("div",{className:n.error,children:[a.error,e.jsx("br",{}),e.jsxs("span",{className:n.backLink,onClick:()=>r("/changelog"),children:["←"," ",t("changelog.detail.backToList","Back to list")]})]});const A=Pe(a.startTime,a.endTime),G=a.endTime?`${F(a.startTime)} → ${F(a.endTime)} (${A})`:`${F(a.startTime)} → ${t("changelog.card.inProgress","in progress")}`,K=!!((S=a.contextSummary)!=null&&S.intent||(C=a.contextSummary)!=null&&C.testScenario||(b=a.contextSummary)!=null&&b.expectedBehavior||(N=a.contextSummary)!=null&&N.observedBehavior),V=!!((T=a.verificationSummary)!=null&&T.label||(k=a.verificationSummary)!=null&&k.status||(I=a.verificationSummary)!=null&&I.testTimestamp);return e.jsxs("div",{className:n.page,children:[e.jsxs("div",{className:n.header,children:[e.jsxs("span",{className:n.backLink,onClick:()=>r("/changelog"),children:["←"," ",t("sidebar.changelog","Changelog")]}),e.jsx("span",{className:n.headerTitle,children:"|"}),e.jsx("span",{className:n.headerTime,children:G}),e.jsx(u,{text:a.status==="active"?t("changelog.card.active.tooltip","This session is still receiving new game changes."):t("changelog.card.completed.tooltip","This session has ended and no more changes are expected."),children:e.jsx("span",{className:a.status==="active"?n.statusActive:n.statusCompleted,children:a.status==="active"?t("changelog.card.active","Active"):t("changelog.card.completed","Completed")})})]}),e.jsxs("div",{className:n.section,children:[e.jsx("div",{className:n.sectionTitle,children:e.jsx(u,{text:t("changelog.detail.changeSummary.tooltip","Counts of extracted game changes grouped by category for this session."),children:e.jsx("span",{children:t("changelog.detail.changeSummary","Change Summary")})})}),e.jsx("div",{className:n.summaryGrid,children:D.map(i=>{const l=a.changeSummary;let o;switch(i.key){case"script":o=l.scriptsModified+l.scriptsCreated;break;case"instance":o=l.instancesCreated+l.instancesDeleted+l.instancesMoved;break;case"property":o=l.propertiesChanged;break;case"lighting":o=l.lightingChanged?1:0;break;case"terrain":o=l.terrainChanged?1:0;break;case"asset":o=l.assetsInserted;break;default:o=0}const j=h===i.key;return e.jsxs("div",{className:`${n.summaryCard} ${j?n.summaryCardActive:""}`,onClick:()=>w(j?"all":i.key),children:[e.jsx("span",{className:n.summaryIcon,children:i.icon}),e.jsx("div",{className:n.summaryCount,children:o}),e.jsx("div",{className:n.summaryLabel,children:t(i.labelKey,i.key)})]},i.key)})})]}),K&&e.jsxs("div",{className:n.section,children:[e.jsx("div",{className:n.sectionTitle,children:e.jsx(u,{text:t("changelog.detail.context.tooltip","Structured execution context captured for this changelog session."),children:e.jsx("span",{children:t("changelog.detail.context.title","Context Summary")})})}),e.jsxs("div",{className:n.contextGrid,children:[((x=a.contextSummary)==null?void 0:x.intent)&&e.jsxs("div",{className:n.contextRow,children:[e.jsx("span",{className:n.contextKey,children:t("changelog.card.sessionIntent","Session intent")}),e.jsx("span",{className:n.contextValue,children:a.contextSummary.intent})]}),((E=a.contextSummary)==null?void 0:E.testScenario)&&e.jsxs("div",{className:n.contextRow,children:[e.jsx("span",{className:n.contextKey,children:t("playtest.context.why","Why this test ran")}),e.jsx("span",{className:n.contextValue,children:a.contextSummary.testScenario})]}),((f=a.contextSummary)==null?void 0:f.expectedBehavior)&&e.jsxs("div",{className:n.contextRow,children:[e.jsx("span",{className:n.contextKey,children:t("playtest.context.expected","Expected")}),e.jsx("span",{className:n.contextValue,children:a.contextSummary.expectedBehavior})]}),((g=a.contextSummary)==null?void 0:g.observedBehavior)&&e.jsxs("div",{className:n.contextRow,children:[e.jsx("span",{className:n.contextKey,children:t("playtest.context.observed","Observed")}),e.jsx("span",{className:n.contextValue,children:a.contextSummary.observedBehavior})]})]})]}),V&&e.jsxs("div",{className:n.section,children:[e.jsx("div",{className:n.sectionTitle,children:e.jsx(u,{text:t("changelog.detail.verification.tooltip","Verification signals linked to this changelog session."),children:e.jsx("span",{children:t("changelog.detail.verification.title","Verification")})})}),e.jsxs("div",{className:n.contextGrid,children:[((m=a.verificationSummary)==null?void 0:m.label)&&e.jsxs("div",{className:n.contextRow,children:[e.jsx("span",{className:n.contextKey,children:t("changelog.detail.verification.label","Result")}),e.jsx("span",{className:n.contextValue,children:a.verificationSummary.label})]}),((d=a.verificationSummary)==null?void 0:d.status)&&e.jsxs("div",{className:n.contextRow,children:[e.jsx("span",{className:n.contextKey,children:t("changelog.detail.verification.status","Status")}),e.jsx("span",{className:n.contextValue,children:a.verificationSummary.status})]}),((_=a.verificationSummary)==null?void 0:_.testTimestamp)&&e.jsxs("div",{className:n.contextRow,children:[e.jsx("span",{className:n.contextKey,children:t("changelog.detail.verification.timestamp","Recorded at")}),e.jsx("span",{className:n.contextValue,children:a.verificationSummary.testTimestamp})]})]})]}),e.jsxs("div",{className:n.section,children:[e.jsx("div",{className:n.sectionTitle,children:e.jsx(u,{text:t("changelog.detail.changeTimeline.tooltip","Chronological list of extracted game changes for this session."),children:e.jsx("span",{children:t("changelog.detail.changeTimeline","Change Timeline")})})}),e.jsxs("div",{className:n.timelineFilter,children:[e.jsx("span",{className:n.filterLabel,children:e.jsx(W,{label:`${t("changelog.detail.filterCategory","Category")}:`,tooltip:t("changelog.detail.filterCategory.tooltip","Filter the timeline to a single change category.")})}),e.jsxs("select",{className:n.filterSelect,value:h,onChange:i=>w(i.target.value),children:[e.jsx("option",{value:"all",children:t("tools.filter.all","All")}),D.map(i=>e.jsxs("option",{value:i.key,children:[i.icon," ",t(i.labelKey,i.key)]},i.key))]}),R&&e.jsxs("label",{className:n.ownershipToggle,children:[e.jsx("input",{type:"checkbox",checked:y,onChange:i=>B(i.target.checked)}),t("changelog.ownership.showGenerated","Show generated metadata")]})]}),v.length===0?e.jsx("div",{className:n.empty,children:t("changelog.detail.noChanges","No changes in this category")}):e.jsx("div",{className:n.timeline,children:v.map((i,l)=>{const o=$===l,j=We(t,i.artifactOwnership);return e.jsxs("div",{children:[e.jsxs("div",{className:n.timelineEntry,onClick:()=>M(o?null:l),children:[e.jsx("span",{className:n.timelineTime,children:De(i.timestamp)}),e.jsx("span",{className:n.timelineIcon,children:ee(i.category)}),e.jsxs("div",{className:n.timelineBody,children:[e.jsxs("div",{className:n.timelineSummary,children:[i.summary,j&&e.jsx(z,{variant:i.artifactOwnership==="generated"?"neutral":"accent",className:n.ownershipBadge,children:j}),e.jsx(u,{text:qe(t,i.confidence),children:e.jsx("span",{className:`${n.timelineConfidence} ${Ue(i.confidence)}`,children:He(t,i.confidence)})})]}),e.jsx("div",{className:n.timelineTarget,children:i.target})]})]}),o&&e.jsx("div",{className:n.timelineExpanded,children:e.jsx(Y,{change:i})})]},l)})})]})]})}export{et as Component};
@@ -0,0 +1 @@
1
+ ._page_11hjw_2{display:flex;flex-direction:column;gap:20px;max-width:900px}._header_11hjw_10{display:flex;align-items:center;gap:12px}._backLink_11hjw_16{font-family:var(--font-label);font-size:12px;color:var(--accent);cursor:pointer;text-decoration:none;transition:opacity var(--transition)}._backLink_11hjw_16:hover{opacity:.8}._headerTitle_11hjw_29{font-family:var(--font-label);font-size:14px;font-weight:600;color:var(--text-primary);letter-spacing:.03em}._headerTime_11hjw_37{font-family:var(--font-code);font-size:12px;color:var(--text-secondary);margin-left:auto}._statusActive_11hjw_44{color:var(--success);font-weight:600}._statusCompleted_11hjw_49{color:var(--text-muted)}._section_11hjw_54{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px 20px}._sectionTitle_11hjw_61{font-family:var(--font-label);font-size:12px;font-weight:600;color:var(--text-primary);text-transform:uppercase;letter-spacing:.05em;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border)}._summaryGrid_11hjw_74{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:10px}._summaryCard_11hjw_80{background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;padding:10px 12px;text-align:center;cursor:pointer;transition:border-color var(--transition)}._summaryCard_11hjw_80:hover{border-color:var(--accent)}._summaryCardActive_11hjw_94{border-color:var(--accent);background:var(--accent-dim)}._summaryIcon_11hjw_99{font-size:20px;display:block;margin-bottom:4px}._summaryCount_11hjw_105{font-family:var(--font-code);font-size:18px;font-weight:700;color:var(--text-primary)}._summaryLabel_11hjw_112{font-family:var(--font-label);font-size:10px;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.04em;margin-top:2px}._contextGrid_11hjw_121{display:flex;flex-direction:column;gap:10px}._contextRow_11hjw_127{display:flex;flex-direction:column;gap:4px}._contextKey_11hjw_133{font-family:var(--font-label);font-size:10px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em}._contextValue_11hjw_141{font-family:var(--font-label);font-size:13px;color:var(--text-primary);line-height:1.5}._timelineFilter_11hjw_149{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-bottom:12px}._filterLabel_11hjw_157{font-family:var(--font-label);font-size:11px;color:var(--text-secondary)}._filterSelect_11hjw_163{font-family:var(--font-code);font-size:11px;padding:3px 8px;border:1px solid var(--border);border-radius:4px;background:var(--bg-secondary);color:var(--text-primary)}._ownershipToggle_11hjw_173{display:inline-flex;min-height:44px;align-items:center;gap:8px;margin-left:auto;color:var(--text-secondary);font-family:var(--font-label);font-size:12px;cursor:pointer}._ownershipToggle_11hjw_173 input{width:16px;height:16px;accent-color:var(--accent)}._timeline_11hjw_149{display:flex;flex-direction:column;gap:0;position:relative;max-height:480px;overflow-y:auto}._timelineEntry_11hjw_201{display:flex;gap:12px;padding:8px 0;border-bottom:1px solid var(--border);transition:background var(--transition);cursor:pointer}._timelineEntry_11hjw_201:last-child{border-bottom:none}._timelineEntry_11hjw_201:hover{background:var(--bg-secondary)}._timelineTime_11hjw_218{font-family:var(--font-code);font-size:11px;color:var(--text-muted);min-width:50px;flex-shrink:0}._timelineIcon_11hjw_226{font-size:14px;flex-shrink:0}._timelineBody_11hjw_231{flex:1;min-width:0}._timelineSummary_11hjw_236{font-family:var(--font-code);font-size:12px;color:var(--text-primary);word-break:break-all}._timelineTarget_11hjw_243{font-family:var(--font-code);font-size:11px;color:var(--text-secondary);margin-top:2px}._timelineConfidence_11hjw_250{font-family:var(--font-label);font-size:9px;padding:1px 5px;border-radius:3px;margin-left:8px;vertical-align:middle}._ownershipBadge_11hjw_259{min-height:20px;margin-left:8px;padding:1px 6px;font-size:9px;vertical-align:middle}._confidenceExact_11hjw_267{background:#22c55e26;color:var(--success)}._confidencePartial_11hjw_272{background:#f59e0b26;color:var(--warning)}._confidenceAfterOnly_11hjw_277{background:#22c55e14;color:var(--text-secondary)}._confidenceIntentOnly_11hjw_282{background:#ef444426;color:var(--error)}._confidenceUnknown_11hjw_287{background:var(--bg-secondary);color:var(--text-muted)}._timelineExpanded_11hjw_293{margin-top:8px;padding:8px;background:var(--bg-card);border:1px solid var(--border);border-radius:6px}._beforeAfterList_11hjw_302{display:flex;flex-direction:column;gap:12px}._beforeAfterItem_11hjw_308{background:var(--bg-secondary);border:1px solid var(--border);border-radius:6px;overflow:hidden}._beforeAfterHeader_11hjw_315{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:var(--bg-card);border-bottom:1px solid var(--border);cursor:pointer}._beforeAfterPath_11hjw_325{font-family:var(--font-code);font-size:11px;color:var(--text-primary)}._beforeAfterBadge_11hjw_331{font-family:var(--font-label);font-size:9px;padding:1px 6px;border-radius:3px;text-transform:uppercase;letter-spacing:.04em}._badgeCreate_11hjw_340{background:#22c55e26;color:var(--success)}._badgeModify_11hjw_345{background:#f59e0b26;color:var(--warning)}._badgeDelete_11hjw_350{background:#ef444426;color:var(--error)}._badgeMove_11hjw_355{background:#3b82f626;color:var(--accent)}._beforeAfterBody_11hjw_360{padding:8px}._empty_11hjw_365{text-align:center;padding:20px;color:var(--text-muted);font-family:var(--font-label);font-size:12px}._loading_11hjw_374{text-align:center;padding:40px 20px;color:var(--text-secondary);font-family:var(--font-label);font-size:12px}._error_11hjw_383{text-align:center;padding:40px 20px;color:var(--error);font-family:var(--font-label);font-size:13px}
@@ -0,0 +1 @@
1
+ import{r as l,a as F,D,u as M,j as e,e as O,c as V,h as U,l as K,T as G}from"./index-C8kXDvHv.js";import{P as H}from"./PageHeader-BfTFbEOK.js";import{C as Z}from"./ConfirmModal-Cxha5h-n.js";import{C as Q}from"./CurrentPlaceScope-BKwvaN7Z.js";import{T as k}from"./TooltipText-DLPk69aK.js";import{T as q}from"./Tabs-9EkdOGoe.js";import"./UiPrimitive-jQZP77uI.js";import"./ConfirmModal.module-D1aZY2bQ.js";const z=10;function J(t,o){return typeof o!="number"?t:`${t}?placeId=${encodeURIComponent(String(o))}`}function W(t){const o=(t==null?void 0:t.placeId)??null,[s,n]=l.useState([]),[u,_]=l.useState(0),[a,f]=l.useState(!1),[x,v]=l.useState(!0),[g,C]=l.useState(0),[d,y]=l.useState("all"),N=l.useRef(null),m=l.useCallback(async(h,b)=>{v(!0);try{const j={limit:String(z),offset:String(h)};b!=="all"&&(j.status=b),typeof o=="number"&&(j.placeId=String(o));const I=await F.get("/api/dashboard/changelog",j);n(I.entries),_(I.total),f(I.hasMore)}catch{n([]),_(0),f(!1)}finally{v(!1)}},[o]),S=l.useCallback(()=>{m(g,d)},[m,g,d]),i=l.useCallback(async()=>{await F.post(J("/api/dashboard/changelog/clear",o)),n([]),_(0),f(!1)},[o]);return l.useEffect(()=>{m(g,d)},[m,g,d]),l.useEffect(()=>{const h=new D;N.current=h,h.connect();const b=h.on("command",()=>{m(g,d)});return()=>{b(),h.disconnect(),N.current=null}},[m,g,d]),{entries:s,total:u,hasMore:a,loading:x,offset:g,statusFilter:d,setOffset:C,setStatusFilter:y,refresh:S,clear:i}}const X="_card_1n89u_2",Y="_header_1n89u_17",ee="_statusBadge_1n89u_24",te="_statusDot_1n89u_35",se="_active_1n89u_41",ae="_completed_1n89u_50",ne="_timeRange_1n89u_58",ce="_summaryList_1n89u_65",oe="_summaryItem_1n89u_71",ie="_summaryIcon_1n89u_80",le="_summaryText_1n89u_86",re="_progressBar_1n89u_91",ge="_progressFill_1n89u_99",de="_emptySummary_1n89u_112",me="_contextBlock_1n89u_120",he="_contextLabel_1n89u_129",pe="_contextValue_1n89u_137",c={card:X,header:Y,statusBadge:ee,statusDot:te,active:se,completed:ae,timeRange:ne,summaryList:ce,summaryItem:oe,summaryIcon:ie,summaryText:le,progressBar:re,progressFill:ge,emptySummary:de,contextBlock:me,contextLabel:he,contextValue:pe};function R(t){if(!t)return"--:--";const o=new Date(t);return`${String(o.getHours()).padStart(2,"0")}:${String(o.getMinutes()).padStart(2,"0")}`}function ue({entry:t,onClick:o}){var h,b,j,I,B,L,A,P,w,E;const{t:s}=M(),n=t.changeSummary,u=t.status==="active",_=t.isBootstrapOnly===!0,a=[],f=n.scriptsModified+n.scriptsCreated;if(f>0){const p=[];n.scriptsModified>0&&p.push(`${n.scriptsModified} ${s("changelog.card.modified","modified")}`),n.scriptsCreated>0&&p.push(`${n.scriptsCreated} ${s("changelog.card.created","created")}`);const T=`${f} ${s("changelog.card.scripts","scripts")} ${p.join(", ")}`;a.push({icon:"📝",text:T,tooltip:s("changelog.card.scripts.tooltip","Script changes made in this session.")})}const x=n.instancesCreated+n.instancesDeleted+n.instancesMoved;if(x>0){const p=[];n.instancesCreated>0&&p.push(`${n.instancesCreated} ${s("changelog.card.created","created")}`),n.instancesDeleted>0&&p.push(`${n.instancesDeleted} ${s("changelog.card.deleted","deleted")}`),n.instancesMoved>0&&p.push(`${n.instancesMoved} ${s("changelog.card.moved","moved")}`);const T=`${x} ${s("changelog.card.instances","instances")} ${p.join(", ")}`;a.push({icon:"🧱",text:T,tooltip:s("changelog.card.instances.tooltip","Instance create, delete, move, or clone changes in this session.")})}n.propertiesChanged>0&&a.push({icon:"🎨",text:`${n.propertiesChanged} ${s("changelog.card.propertiesChanged","properties changed")}`,tooltip:s("changelog.card.propertiesChanged.tooltip","Property value changes recorded for this session.")}),n.lightingChanged&&a.push({icon:"🌅",text:s("changelog.card.lightingConfigured","Lighting configured"),tooltip:s("changelog.card.lightingConfigured.tooltip","Lighting or atmosphere settings changed in this session.")}),n.terrainChanged&&a.push({icon:"⛰️",text:s("changelog.card.terrainConfigured","Terrain configured"),tooltip:s("changelog.card.terrainConfigured.tooltip","Terrain data or terrain settings changed in this session.")}),n.assetsInserted>0&&a.push({icon:"📦",text:`${n.assetsInserted} ${s("changelog.card.assetsInserted","assets inserted")}`,tooltip:s("changelog.card.assetsInserted.tooltip","Assets inserted into the place during this session.")});const v=R(t.startTime),g=u?s("changelog.card.inProgress","in progress"):t.endTime?R(t.endTime):"--:--",C=_?s("changelog.card.bootstrapStatus","Bootstrap"):u?s("changelog.card.active","Active"):s("changelog.card.completed","Completed"),d=_?s("changelog.card.bootstrapStatus.tooltip","This session only contains the initial sync bootstrap snapshot."):u?s("changelog.card.active.tooltip","This session is still receiving new game changes."):s("changelog.card.completed.tooltip","This session has ended and no more changes are expected."),y=_?s("changelog.card.bootstrapSummary","Initial sync snapshot"):s("changelog.card.noChanges","No changes yet"),N=_?s("changelog.card.bootstrapSummary.tooltip","Initial file sync writes are collapsed into a single bootstrap snapshot row."):s("changelog.card.noChanges.tooltip","No game changes have been extracted for this session yet."),m=(b=(h=t.contextSummary)==null?void 0:h.intent)==null?void 0:b.trim(),S=((L=(B=(I=(j=t.contextSummary)==null?void 0:j.affectedAreas)==null?void 0:I[0])==null?void 0:B.label)==null?void 0:L.trim())||((P=(A=t.contextSummary)==null?void 0:A.testScenario)==null?void 0:P.trim()),i=(E=(w=t.verificationSummary)==null?void 0:w.label)==null?void 0:E.trim();return e.jsxs("div",{className:c.card,onClick:o,children:[e.jsxs("div",{className:c.header,children:[e.jsx(k,{text:d,children:e.jsxs("span",{className:`${c.statusBadge} ${u?c.active:c.completed}`,children:[e.jsx("span",{className:c.statusDot}),C]})}),e.jsxs("span",{className:c.timeRange,children:[v,"~",g]})]}),e.jsx("div",{className:c.summaryList,children:a.length>0?a.map((p,T)=>e.jsxs("div",{className:c.summaryItem,children:[e.jsx("span",{className:c.summaryIcon,children:p.icon}),e.jsx(k,{text:p.tooltip,children:e.jsx("span",{className:c.summaryText,children:p.text})})]},T)):e.jsx(k,{text:N,children:e.jsx("span",{className:c.emptySummary,style:{display:"block"},children:y})})}),m&&e.jsxs("div",{className:c.contextBlock,children:[e.jsx("span",{className:c.contextLabel,children:s("changelog.card.sessionIntent","Session intent")}),e.jsx("span",{className:c.contextValue,children:m})]}),!m&&S&&e.jsxs("div",{className:c.contextBlock,children:[e.jsx("span",{className:c.contextLabel,children:s("changelog.card.representativeArea","Representative area")}),e.jsx("span",{className:c.contextValue,children:S})]}),i&&e.jsxs("div",{className:c.contextBlock,children:[e.jsx("span",{className:c.contextLabel,children:s("changelog.card.verification","Verification")}),e.jsx("span",{className:c.contextValue,children:i})]}),u&&e.jsx("div",{className:c.progressBar,children:e.jsx("div",{className:c.progressFill})})]})}const _e="_page_1tggr_2",fe="_limitNotice_1tggr_9",xe="_limitNoticeContent_1tggr_23",ye="_limitNoticeTitle_1tggr_28",be="_limitNoticeText_1tggr_35",ve="_primaryAction_1tggr_41",Ce="_clearButton_1tggr_67",Ne="_list_1tggr_88",Se="_empty_1tggr_95",je="_loading_1tggr_104",Ie="_pagination_1tggr_113",Te="_pageInfo_1tggr_121",$e="_btn_1tggr_127",r={page:_e,limitNotice:fe,limitNoticeContent:xe,limitNoticeTitle:ye,limitNoticeText:be,primaryAction:ve,clearButton:Ce,list:Ne,empty:Se,loading:je,pagination:Ie,pageInfo:Te,btn:$e},$=10;function ke(t,o){return typeof o!="number"?`/changelog/${t}`:`/changelog/${t}?placeId=${encodeURIComponent(String(o))}`}const Be=[{key:"all",labelKey:"changelog.filter.all"},{key:"active",labelKey:"changelog.filter.active"},{key:"completed",labelKey:"changelog.filter.completed"}];function De(){const{t}=M(),{trackEvent:o,trackPageView:s}=O(),n=V(),[u,_]=l.useState(null),a=W({placeId:u}),f=U(),{show:x}=K(),[v,g]=l.useState(!1),[C,d]=l.useState(!1),y=!f.loading&&f.tier==="basic",N=y?a.entries.slice(0,3):a.entries,m=!y&&a.total>$,S=async()=>{d(!0);try{await a.clear(),x(t("toast.clearSuccess","Cleared successfully"),"success"),g(!1)}catch{x(t("toast.clearFailed","Failed to clear data"),"error")}finally{d(!1)}};return e.jsxs("div",{className:r.page,children:[e.jsx(H,{title:t("page.changelog.title","Changelog"),description:t("page.changelog.description","Review game-change sessions captured from AI actions and sync events."),helpTopicId:"changelog",helpState:{tier:f.tier}}),e.jsx(Q,{surface:"changelog",selectable:!0,selectedPlaceId:u,onSelectedPlaceIdChange:i=>{_(i),a.setOffset(0)}}),e.jsx(q,{items:Be.map(i=>({key:i.key,label:t(i.labelKey,i.key.charAt(0).toUpperCase()+i.key.slice(1))})),value:a.statusFilter,onChange:i=>{const h=`changelog_${i}`;o("dashboard_click_event",{click_target:`changelog_tab_${i}`,page:"changelog",tab:h}),s({page:"changelog",tab:h}),a.setStatusFilter(i),a.setOffset(0)},rightActions:e.jsx("button",{className:r.clearButton,onClick:()=>{o("dashboard_click_event",{click_target:"changelog_clear",page:"changelog",tab:`changelog_${a.statusFilter}`}),g(!0)},children:t("common.clear","Clear")})}),a.loading&&a.entries.length===0&&e.jsx("div",{className:r.loading,children:t("common.loading","Loading...")}),!a.loading&&a.entries.length===0?e.jsx("div",{className:r.empty,children:t("changelog.empty","No changelog entries for the current place yet")}):e.jsx("div",{className:r.list,children:N.map(i=>e.jsx(ue,{entry:i,onClick:()=>n(ke(i.entryId,u))},i.entryId))}),m&&e.jsxs("div",{className:r.pagination,children:[e.jsx("button",{className:r.btn,disabled:a.offset===0,onClick:()=>a.setOffset(Math.max(0,a.offset-$)),children:t("tools.page.prev","Prev")}),e.jsxs("span",{className:r.pageInfo,children:[a.offset+1,"–",Math.min(a.offset+$,a.total)," / ",a.total]}),e.jsx("button",{className:r.btn,disabled:!a.hasMore,onClick:()=>a.setOffset(a.offset+$),children:t("tools.page.next","Next")})]}),y&&e.jsx(e.Fragment,{children:e.jsxs("div",{className:r.limitNotice,children:[e.jsxs("div",{className:r.limitNoticeContent,children:[e.jsx("div",{className:r.limitNoticeTitle,children:t("changelog.basic.limit.title","Basic preview shows the latest 3 sessions")}),e.jsx("div",{className:r.limitNoticeText,children:t("changelog.basic.limit.body","Full changelog timeline browsing is available with Pro.")})]}),e.jsx("a",{className:r.primaryAction,href:G.changelog,target:"_blank",rel:"noreferrer",onClick:()=>o("dashboard_click_event",{click_target:"upgrade_cta",placement:"changelog_limit_notice",page:"changelog",tab:`changelog_${a.statusFilter}`}),children:t("tier.upgrade","View Pro")})]})}),e.jsx(Z,{open:v,title:t("changelog.clear.title","Clear changelog?"),message:t("changelog.clear.message","This permanently removes the stored changelog for the current place."),cancelLabel:t("common.cancel","Cancel"),confirmLabel:t("common.clear","Clear"),loading:C,onCancel:()=>!C&&g(!1),onConfirm:S})]})}export{De as Component};
@@ -1 +1 @@
1
- import{r as u,j as s}from"./index-T_F9Rs-N.js";import{s as a}from"./ConfirmModal.module-D1aZY2bQ.js";function p({open:r,title:t,message:o,cancelLabel:c,confirmLabel:n,loading:e=!1,onCancel:l,onConfirm:d}){const i=u.useId();return r?s.jsx("div",{className:a.backdrop,onClick:e?void 0:l,children:s.jsxs("div",{className:a.modal,role:"dialog","aria-modal":"true","aria-labelledby":i,onClick:m=>m.stopPropagation(),children:[s.jsx("h2",{id:i,className:a.title,children:t}),s.jsx("p",{className:a.message,children:o}),s.jsxs("div",{className:a.actions,children:[s.jsx("button",{className:a.cancelButton,onClick:l,disabled:e,children:c}),s.jsx("button",{className:a.confirmButton,onClick:d,disabled:e,children:e?"...":n})]})]})}):null}export{p as C};
1
+ import{r as u,j as s}from"./index-C8kXDvHv.js";import{s as a}from"./ConfirmModal.module-D1aZY2bQ.js";function p({open:r,title:t,message:o,cancelLabel:c,confirmLabel:n,loading:e=!1,onCancel:l,onConfirm:d}){const i=u.useId();return r?s.jsx("div",{className:a.backdrop,onClick:e?void 0:l,children:s.jsxs("div",{className:a.modal,role:"dialog","aria-modal":"true","aria-labelledby":i,onClick:m=>m.stopPropagation(),children:[s.jsx("h2",{id:i,className:a.title,children:t}),s.jsx("p",{className:a.message,children:o}),s.jsxs("div",{className:a.actions,children:[s.jsx("button",{className:a.cancelButton,onClick:l,disabled:e,children:c}),s.jsx("button",{className:a.confirmButton,onClick:d,disabled:e,children:e?"...":n})]})]})}):null}export{p as C};