flea-qml 0.0.0-stage → 0.2.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 (637) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +511 -2
  3. package/THIRD-PARTY-NOTICES.md +29 -0
  4. package/demos/App.java +5 -0
  5. package/demos/Dockerfile +4 -0
  6. package/demos/Main.kt +3 -0
  7. package/demos/Program.cs +1 -0
  8. package/demos/README.md +12 -0
  9. package/demos/app.dart +3 -0
  10. package/demos/app.deb +0 -0
  11. package/demos/app.js +1 -0
  12. package/demos/backup.tar +0 -0
  13. package/demos/budget.xlsx +0 -0
  14. package/demos/build.sh +2 -0
  15. package/demos/bundle.zip +0 -0
  16. package/demos/clip.mp4 +0 -0
  17. package/demos/data.sqlite +0 -0
  18. package/demos/disk.iso +0 -0
  19. package/demos/engine.cpp +5 -0
  20. package/demos/firmware.bin +0 -0
  21. package/demos/flake.nix +4 -0
  22. package/demos/folder/inside.txt +1 -0
  23. package/demos/font.ttf +0 -0
  24. package/demos/index.html +5 -0
  25. package/demos/index.php +2 -0
  26. package/demos/init.lua +1 -0
  27. package/demos/letter.docx +0 -0
  28. package/demos/lib.rs +3 -0
  29. package/demos/main.c +6 -0
  30. package/demos/main.h +3 -0
  31. package/demos/math-and-diagrams.md +200 -0
  32. package/demos/notes.tar.gz +0 -0
  33. package/demos/notes.txt +3 -0
  34. package/demos/photo.png +0 -0
  35. package/demos/program +2 -0
  36. package/demos/report.pdf +32 -0
  37. package/demos/script.py +1 -0
  38. package/demos/server.go +7 -0
  39. package/demos/settings.json +4 -0
  40. package/demos/slides.pptx +0 -0
  41. package/demos/song.mp3 +0 -0
  42. package/demos/style.css +4 -0
  43. package/demos/tool.rb +1 -0
  44. package/demos/types.ts +2 -0
  45. package/docs/pele.md +23 -0
  46. package/docs/protocol.md +3420 -0
  47. package/docs/temml.md +63 -0
  48. package/index.js +107 -0
  49. package/package.json +34 -4
  50. package/src/archive.js +407 -0
  51. package/src/archiveops.js +728 -0
  52. package/src/backend.js +369 -0
  53. package/src/bulkrename.js +95 -0
  54. package/src/clip-host.js +76 -0
  55. package/src/clip.js +462 -0
  56. package/src/code.js +168 -0
  57. package/src/compare.js +74 -0
  58. package/src/create.js +128 -0
  59. package/src/dirsize.js +147 -0
  60. package/src/figure-svg.js +530 -0
  61. package/src/figure-thread.js +23 -0
  62. package/src/figure.js +132 -0
  63. package/src/find.js +55 -0
  64. package/src/flea.js +39 -0
  65. package/src/fsinfo.js +39 -0
  66. package/src/highlight.js +141 -0
  67. package/src/html.js +52 -0
  68. package/src/kinds.js +89 -0
  69. package/src/listing.js +130 -0
  70. package/src/markdown-html.js +317 -0
  71. package/src/mathml.js +186 -0
  72. package/src/menu.js +180 -0
  73. package/src/meta.js +135 -0
  74. package/src/office.js +810 -0
  75. package/src/order.js +100 -0
  76. package/src/peek.js +49 -0
  77. package/src/pele-wrapper.js +695 -0
  78. package/src/permissions.js +180 -0
  79. package/src/places.js +313 -0
  80. package/src/preview-language.js +10 -0
  81. package/src/terminal-server.js +95 -0
  82. package/src/terminal-shell.js +26 -0
  83. package/src/transfer.js +669 -0
  84. package/src/trash-record.js +41 -0
  85. package/src/trash.js +210 -0
  86. package/src/trashbrowse.js +327 -0
  87. package/src/uistate.js +393 -0
  88. package/src/uistore.js +168 -0
  89. package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
  90. package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
  91. package/src/vendor/LICENSES/MIT-katex.txt +21 -0
  92. package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
  93. package/src/vendor/LICENSES/MIT-pele.txt +40 -0
  94. package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
  95. package/src/vendor/LICENSES/MIT-temml.txt +21 -0
  96. package/src/vendor/pele.js +145 -0
  97. package/src/vendor/temml.mjs +14708 -0
  98. package/src/watch.js +98 -0
  99. package/src/wayland/client.js +109 -0
  100. package/src/wayland/protocol.js +55 -0
  101. package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
  102. package/src/wayland/protocols/wayland.xml +3248 -0
  103. package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
  104. package/src/wayland/resource-io.js +6 -0
  105. package/src/wayland/socket-discovery.js +26 -0
  106. package/src/wayland/transport-posix.js +120 -0
  107. package/src/wayland/transport-win32.js +11 -0
  108. package/src/wayland/transport.js +3 -0
  109. package/src/wayland/win32-resources.js +80 -0
  110. package/src/wayland/win32-wire.js +62 -0
  111. package/test/archive.test.js +80 -0
  112. package/test/bench-markdown-scroll.mjs +190 -0
  113. package/test/clip-host.test.js +113 -0
  114. package/test/code-preview.test.js +35 -0
  115. package/test/compare-ui-paths.test.js +24 -0
  116. package/test/compare.test.js +54 -0
  117. package/test/delete-trash.test.js +67 -0
  118. package/test/dirsize.test.js +138 -0
  119. package/test/file-ops.test.js +307 -0
  120. package/test/file-url.test.js +24 -0
  121. package/test/find-contents.test.js +161 -0
  122. package/test/find-input.test.js +66 -0
  123. package/test/fixtures/pele-parity.json +1006 -0
  124. package/test/highlight-launcher.test.js +35 -0
  125. package/test/html-preview.test.js +22 -0
  126. package/test/input.test.js +15 -0
  127. package/test/keymap.test.js +26 -0
  128. package/test/language-icons.test.js +36 -0
  129. package/test/launcher.test.js +51 -0
  130. package/test/manual-archive-here-ui.mjs +47 -0
  131. package/test/manual-code-scroll.mjs +28 -0
  132. package/test/manual-column-scroll.mjs +24 -0
  133. package/test/manual-compare-ui.mjs +20 -0
  134. package/test/manual-find-status.mjs +37 -0
  135. package/test/manual-folder-focus.mjs +63 -0
  136. package/test/manual-html-security.mjs +23 -0
  137. package/test/manual-html-ui.mjs +30 -0
  138. package/test/manual-syntax-preview.mjs +26 -0
  139. package/test/manual-terminal-lifecycle.mjs +42 -0
  140. package/test/manual-terminal-navigation.mjs +48 -0
  141. package/test/manual-terminal-ui.mjs +47 -0
  142. package/test/manual-trash-ui.mjs +86 -0
  143. package/test/markdown-diagrams.test.js +93 -0
  144. package/test/markdown-html.test.js +105 -0
  145. package/test/mathml.test.js +92 -0
  146. package/test/menu-transfer.test.js +57 -0
  147. package/test/office-preview.test.js +154 -0
  148. package/test/pele-parity.test.js +28 -0
  149. package/test/places.test.js +134 -0
  150. package/test/preview-keys.test.js +60 -0
  151. package/test/preview-language.test.js +22 -0
  152. package/test/status-filename.test.js +20 -0
  153. package/test/transfer-replace-merge.test.js +187 -0
  154. package/test/trash-address.test.js +23 -0
  155. package/test/trash-view.test.js +37 -0
  156. package/test/trashbrowse.test.js +135 -0
  157. package/ui/AboutFacts.qml +78 -0
  158. package/ui/ArchiveCards.qml +95 -0
  159. package/ui/ArchiveCompressDialog.qml +378 -0
  160. package/ui/ArchiveHereConfirm.qml +127 -0
  161. package/ui/ArchivePasswordDialog.qml +257 -0
  162. package/ui/Backend.qml +775 -0
  163. package/ui/BulkOldNames.qml +47 -0
  164. package/ui/BulkRenameDialog.qml +380 -0
  165. package/ui/CardFrame.qml +67 -0
  166. package/ui/CardScroll.qml +79 -0
  167. package/ui/CheckBox.qml +73 -0
  168. package/ui/ChromeBar.qml +360 -0
  169. package/ui/ChromeButton.qml +131 -0
  170. package/ui/ChromeModes.qml +43 -0
  171. package/ui/CodeLines.qml +256 -0
  172. package/ui/CodeRefusal.qml +52 -0
  173. package/ui/CollideConfirm.qml +147 -0
  174. package/ui/CollideHost.qml +167 -0
  175. package/ui/ColumnPane.qml +525 -0
  176. package/ui/ColumnRow.qml +380 -0
  177. package/ui/ColumnsArea.qml +594 -0
  178. package/ui/ColumnsLanding.qml +147 -0
  179. package/ui/CompareView.qml +321 -0
  180. package/ui/ContextMenu.qml +743 -0
  181. package/ui/ConvertDialog.qml +456 -0
  182. package/ui/CountedWorker.qml +7 -0
  183. package/ui/Crumb.qml +64 -0
  184. package/ui/CrumbDrop.qml +25 -0
  185. package/ui/CsvTable.qml +394 -0
  186. package/ui/CursorMark.qml +41 -0
  187. package/ui/DefaultClaim.qml +130 -0
  188. package/ui/DeviceLock.qml +47 -0
  189. package/ui/DeviceMounts.qml +540 -0
  190. package/ui/DialogButton.qml +150 -0
  191. package/ui/DialogField.qml +147 -0
  192. package/ui/DialogHeader.qml +31 -0
  193. package/ui/DialogScrim.qml +20 -0
  194. package/ui/DialogTitle.qml +37 -0
  195. package/ui/Divider.qml +9 -0
  196. package/ui/DropInto.qml +126 -0
  197. package/ui/DropTarget.qml +35 -0
  198. package/ui/DropboxMark.qml +60 -0
  199. package/ui/EmptyState.qml +150 -0
  200. package/ui/EscapeHint.qml +11 -0
  201. package/ui/FactsTable.qml +54 -0
  202. package/ui/FastScrollHandler.qml +476 -0
  203. package/ui/FatNamesConfirm.qml +157 -0
  204. package/ui/Favourites.qml +143 -0
  205. package/ui/FigureService.qml +120 -0
  206. package/ui/FileDrag.qml +267 -0
  207. package/ui/FilterStrip.qml +133 -0
  208. package/ui/FitMetrics.qml +22 -0
  209. package/ui/FlashDriveRows.qml +137 -0
  210. package/ui/FlashHost.qml +72 -0
  211. package/ui/FlashImageRow.qml +104 -0
  212. package/ui/FlashRunner.qml +119 -0
  213. package/ui/FlashStepRow.qml +172 -0
  214. package/ui/FlashStrip.qml +38 -0
  215. package/ui/FlashView.qml +397 -0
  216. package/ui/FleaMark.qml +88 -0
  217. package/ui/FlyoutFade.qml +23 -0
  218. package/ui/FontPane.qml +170 -0
  219. package/ui/Glass.qml +114 -0
  220. package/ui/GlassTagger.qml +59 -0
  221. package/ui/Glyph.qml +64 -0
  222. package/ui/GlyphSolid.qml +22 -0
  223. package/ui/GridArea.qml +664 -0
  224. package/ui/GridTile.qml +325 -0
  225. package/ui/GvfsBridge.qml +164 -0
  226. package/ui/Header.qml +433 -0
  227. package/ui/HoverTimers.qml +39 -0
  228. package/ui/HtmlClip.qml +30 -0
  229. package/ui/HtmlPane.qml +63 -0
  230. package/ui/HyprlandMark.qml +45 -0
  231. package/ui/Ipc.qml +1005 -0
  232. package/ui/IpcControls.qml +7 -0
  233. package/ui/IpcMenuState.qml +48 -0
  234. package/ui/IpcPreviewState.qml +185 -0
  235. package/ui/JumpPath.qml +51 -0
  236. package/ui/KeymapSheet.qml +561 -0
  237. package/ui/KeymapSheetResult.qml +89 -0
  238. package/ui/KindStack.qml +40 -0
  239. package/ui/LangMark.qml +51 -0
  240. package/ui/LangMarkLoader.qml +26 -0
  241. package/ui/List.qml +480 -0
  242. package/ui/LoadingState.qml +54 -0
  243. package/ui/LocalSend.qml +56 -0
  244. package/ui/LocalSendMark.qml +73 -0
  245. package/ui/MarkdownBlockView.qml +311 -0
  246. package/ui/MarkdownBlocks.qml +35 -0
  247. package/ui/MarkdownFigure.qml +254 -0
  248. package/ui/MarkdownImages.qml +72 -0
  249. package/ui/MarkdownList.qml +81 -0
  250. package/ui/MarkdownMathsText.qml +97 -0
  251. package/ui/MarkdownPane.qml +83 -0
  252. package/ui/MarkdownPictures.qml +41 -0
  253. package/ui/MarkdownQuote.qml +52 -0
  254. package/ui/MarkdownRemote.qml +82 -0
  255. package/ui/MarkdownSource.qml +155 -0
  256. package/ui/MarkdownTable.qml +222 -0
  257. package/ui/MarkdownTableScroll.qml +64 -0
  258. package/ui/MarkdownTableWheel.qml +126 -0
  259. package/ui/MarkdownText.qml +87 -0
  260. package/ui/MarkdownWorker.js +132 -0
  261. package/ui/MatchText.qml +99 -0
  262. package/ui/MediaSession.qml +38 -0
  263. package/ui/MediaSound.qml +26 -0
  264. package/ui/MediaStrip.qml +191 -0
  265. package/ui/MediaTrack.qml +36 -0
  266. package/ui/MediaVolume.qml +54 -0
  267. package/ui/MenuActionDialog.qml +396 -0
  268. package/ui/MenuEdgeFade.qml +24 -0
  269. package/ui/MenuHost.qml +227 -0
  270. package/ui/MenuRow.qml +351 -0
  271. package/ui/MountListing.qml +100 -0
  272. package/ui/NetworkDialog.qml +435 -0
  273. package/ui/NetworkForm.qml +426 -0
  274. package/ui/NetworkMounts.qml +913 -0
  275. package/ui/NetworkPlaces.qml +127 -0
  276. package/ui/OpenWithDialog.qml +613 -0
  277. package/ui/Opener.qml +95 -0
  278. package/ui/Pane.qml +1320 -0
  279. package/ui/PaneMenuActions.qml +527 -0
  280. package/ui/PanePath.qml +90 -0
  281. package/ui/PaneRail.qml +268 -0
  282. package/ui/PaneStates.qml +88 -0
  283. package/ui/PaneSwap.qml +339 -0
  284. package/ui/PaneWire.qml +601 -0
  285. package/ui/ParkedWait.qml +9 -0
  286. package/ui/PathEntry.qml +186 -0
  287. package/ui/PathJump.qml +400 -0
  288. package/ui/PdfViewer.qml +297 -0
  289. package/ui/PermissionsDialog.qml +658 -0
  290. package/ui/PermissionsHeadings.qml +31 -0
  291. package/ui/PhoneMounts.qml +67 -0
  292. package/ui/PickerAnswers.qml +75 -0
  293. package/ui/PickerBox.qml +26 -0
  294. package/ui/PickerChrome.qml +295 -0
  295. package/ui/PickerFilter.qml +97 -0
  296. package/ui/PickerGrid.qml +308 -0
  297. package/ui/PickerHeader.qml +28 -0
  298. package/ui/PickerLifecycle.qml +27 -0
  299. package/ui/PickerList.qml +218 -0
  300. package/ui/PickerListing.qml +149 -0
  301. package/ui/PickerPathBar.qml +127 -0
  302. package/ui/PickerPlaces.qml +189 -0
  303. package/ui/PickerRecent.qml +92 -0
  304. package/ui/PickerSave.qml +101 -0
  305. package/ui/PickerSelection.qml +155 -0
  306. package/ui/PickerWindow.qml +846 -0
  307. package/ui/PowerSectorsReader.qml +10 -0
  308. package/ui/PrebuildDriver.qml +146 -0
  309. package/ui/Preview.qml +1005 -0
  310. package/ui/PreviewAnimation.qml +24 -0
  311. package/ui/PreviewArchive.qml +91 -0
  312. package/ui/PreviewColumn.qml +553 -0
  313. package/ui/PreviewEdge.qml +63 -0
  314. package/ui/PreviewFacts.qml +30 -0
  315. package/ui/PreviewFactsLine.qml +34 -0
  316. package/ui/PreviewHtml.qml +233 -0
  317. package/ui/PreviewImage.qml +253 -0
  318. package/ui/PreviewImagePan.qml +13 -0
  319. package/ui/PreviewImageSharp.qml +32 -0
  320. package/ui/PreviewLines.qml +106 -0
  321. package/ui/PreviewMarkdown.qml +706 -0
  322. package/ui/PreviewMedia.qml +250 -0
  323. package/ui/PreviewPdf.qml +482 -0
  324. package/ui/PreviewScroll.qml +201 -0
  325. package/ui/PreviewSwap.qml +335 -0
  326. package/ui/PreviewText.qml +149 -0
  327. package/ui/ProtocolChip.qml +18 -0
  328. package/ui/QuickLookArchive.qml +41 -0
  329. package/ui/QuickLookBar.qml +103 -0
  330. package/ui/QuickLookPrepare.qml +355 -0
  331. package/ui/QuickLookSwap.qml +10 -0
  332. package/ui/QuickLookWarm.qml +65 -0
  333. package/ui/RailDrop.qml +155 -0
  334. package/ui/RailHeading.qml +19 -0
  335. package/ui/RailPlaces.qml +38 -0
  336. package/ui/RailTrashRow.qml +67 -0
  337. package/ui/RenameField.qml +353 -0
  338. package/ui/RendererRetry.qml +11 -0
  339. package/ui/ResizeHandle.qml +52 -0
  340. package/ui/Reveal.qml +54 -0
  341. package/ui/Row.qml +476 -0
  342. package/ui/RowDrag.qml +213 -0
  343. package/ui/RowDropTarget.qml +27 -0
  344. package/ui/RunCard.qml +286 -0
  345. package/ui/Scripts.qml +65 -0
  346. package/ui/SearchStrip.qml +232 -0
  347. package/ui/SelectionBand.qml +140 -0
  348. package/ui/SelectionPreview.qml +370 -0
  349. package/ui/SettingsFavourite.qml +122 -0
  350. package/ui/SettingsGroup.qml +96 -0
  351. package/ui/SettingsHint.qml +12 -0
  352. package/ui/SettingsMetrics.qml +29 -0
  353. package/ui/SettingsPane.qml +178 -0
  354. package/ui/SettingsPanel.qml +547 -0
  355. package/ui/SettingsRail.qml +128 -0
  356. package/ui/SettingsRow.qml +409 -0
  357. package/ui/SettingsRuler.qml +85 -0
  358. package/ui/SettingsSegment.qml +85 -0
  359. package/ui/ShareBrowser.qml +113 -0
  360. package/ui/ShareLink.qml +67 -0
  361. package/ui/ShelfPins.qml +101 -0
  362. package/ui/Sidebar.qml +728 -0
  363. package/ui/SidebarRow.qml +358 -0
  364. package/ui/Spinner.qml +60 -0
  365. package/ui/StableModel.qml +89 -0
  366. package/ui/StateMessage.qml +84 -0
  367. package/ui/StatusBar.qml +512 -0
  368. package/ui/StatusFileName.qml +27 -0
  369. package/ui/TabBar.qml +673 -0
  370. package/ui/TabDragGeometry.qml +60 -0
  371. package/ui/TagMenuMark.qml +52 -0
  372. package/ui/TagRailSection.qml +53 -0
  373. package/ui/TagSlot.qml +40 -0
  374. package/ui/TagState.qml +150 -0
  375. package/ui/TagSwatch.qml +28 -0
  376. package/ui/Taildrop.qml +86 -0
  377. package/ui/TailscaleMark.qml +50 -0
  378. package/ui/TerminalService.qml +69 -0
  379. package/ui/TerminalTab.qml +48 -0
  380. package/ui/TerminalTabs.qml +27 -0
  381. package/ui/Theme.qml +460 -0
  382. package/ui/ThemeColors.qml +43 -0
  383. package/ui/TransferCard.qml +239 -0
  384. package/ui/TrashConfirm.qml +129 -0
  385. package/ui/TrashDropHandler.qml +11 -0
  386. package/ui/TrashHost.qml +202 -0
  387. package/ui/TrashMonitor.qml +30 -0
  388. package/ui/TrashToolbar.qml +19 -0
  389. package/ui/TrashView.qml +492 -0
  390. package/ui/UnlockDialog.qml +450 -0
  391. package/ui/UnlockHost.qml +206 -0
  392. package/ui/UpdateCheck.qml +97 -0
  393. package/ui/UserDirs.qml +25 -0
  394. package/ui/ViewState.qml +565 -0
  395. package/ui/ViewportScrollBar.qml +195 -0
  396. package/ui/ViewportScrollBars.qml +25 -0
  397. package/ui/WebPreview.qml +33 -0
  398. package/ui/WebPreviewView.qml +26 -0
  399. package/ui/WindowBody.qml +829 -0
  400. package/ui/WindowDrag.qml +35 -0
  401. package/ui/boot/Commons/AudioNodes.qml +50 -0
  402. package/ui/boot/Commons/AudioNodesModel.js +96 -0
  403. package/ui/boot/Commons/Border.qml +243 -0
  404. package/ui/boot/Commons/BorderGeometry.js +373 -0
  405. package/ui/boot/Commons/Color.qml +258 -0
  406. package/ui/boot/Commons/I18n.qml +118 -0
  407. package/ui/boot/Commons/InputDevices.qml +112 -0
  408. package/ui/boot/Commons/InputMethodState.qml +38 -0
  409. package/ui/boot/Commons/IpcRegistry.qml +77 -0
  410. package/ui/boot/Commons/Numbers.js +19 -0
  411. package/ui/boot/Commons/Plural.js +91 -0
  412. package/ui/boot/Commons/ShellIpc.qml +12 -0
  413. package/ui/boot/Commons/Style.qml +561 -0
  414. package/ui/boot/Commons/Translations.qml +100 -0
  415. package/ui/boot/Commons/UntypedInput.qml +152 -0
  416. package/ui/boot/Commons/Util.qml +188 -0
  417. package/ui/boot/Commons/qmldir +13 -0
  418. package/ui/boot/LICENSE-omarchy +20 -0
  419. package/ui/boot/Ui/BackgroundMedia.qml +49 -0
  420. package/ui/boot/Ui/BarIconButton.qml +106 -0
  421. package/ui/boot/Ui/BarIconContent.qml +38 -0
  422. package/ui/boot/Ui/BarIndicator.qml +53 -0
  423. package/ui/boot/Ui/BarWidget.qml +50 -0
  424. package/ui/boot/Ui/BorderOverlay.qml +54 -0
  425. package/ui/boot/Ui/BorderSurface.qml +40 -0
  426. package/ui/boot/Ui/Button.qml +224 -0
  427. package/ui/boot/Ui/ButtonGroup.qml +131 -0
  428. package/ui/boot/Ui/ConfirmDialog.qml +134 -0
  429. package/ui/boot/Ui/CursorSurface.qml +42 -0
  430. package/ui/boot/Ui/Dropdown.qml +245 -0
  431. package/ui/boot/Ui/FilterInput.qml +26 -0
  432. package/ui/boot/Ui/IconContentBounds.qml +141 -0
  433. package/ui/boot/Ui/KeyboardPanel.qml +453 -0
  434. package/ui/boot/Ui/MultiSelect.qml +624 -0
  435. package/ui/boot/Ui/NumberField.qml +86 -0
  436. package/ui/boot/Ui/OpticalGlyph.qml +68 -0
  437. package/ui/boot/Ui/OverlayWindow.qml +102 -0
  438. package/ui/boot/Ui/Panel.qml +60 -0
  439. package/ui/boot/Ui/PanelActionButton.qml +105 -0
  440. package/ui/boot/Ui/PanelController.qml +16 -0
  441. package/ui/boot/Ui/PanelHero.qml +112 -0
  442. package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
  443. package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
  444. package/ui/boot/Ui/PanelSeparator.qml +19 -0
  445. package/ui/boot/Ui/PanelSlider.qml +156 -0
  446. package/ui/boot/Ui/PanelToolTip.qml +50 -0
  447. package/ui/boot/Ui/PluginBarApi.qml +89 -0
  448. package/ui/boot/Ui/PointerMoveGate.qml +54 -0
  449. package/ui/boot/Ui/PopupCard.qml +181 -0
  450. package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
  451. package/ui/boot/Ui/SearchableDropdown.qml +354 -0
  452. package/ui/boot/Ui/SizedImage.qml +125 -0
  453. package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
  454. package/ui/boot/Ui/TextField.qml +58 -0
  455. package/ui/boot/Ui/Toggle.qml +118 -0
  456. package/ui/boot/Ui/ToggleSwitch.qml +115 -0
  457. package/ui/boot/Ui/WidgetButton.qml +172 -0
  458. package/ui/boot/Ui/qmldir +41 -0
  459. package/ui/boot/fleatab.qml +50 -0
  460. package/ui/boot/picker.qml +39 -0
  461. package/ui/boot/shell.qml +131 -0
  462. package/ui/boot/tabtearoff.qml +51 -0
  463. package/ui/js/Anchor.js +379 -0
  464. package/ui/js/AnchorHold.js +162 -0
  465. package/ui/js/Archive.js +157 -0
  466. package/ui/js/ArchiveCard.js +44 -0
  467. package/ui/js/ArchiveOps.js +44 -0
  468. package/ui/js/BackReturn.js +118 -0
  469. package/ui/js/BulkRename.js +100 -0
  470. package/ui/js/Buttons.js +54 -0
  471. package/ui/js/ChromeKeys.js +116 -0
  472. package/ui/js/ClipMarks.js +73 -0
  473. package/ui/js/ClipSelection.js +67 -0
  474. package/ui/js/Clipboard.js +179 -0
  475. package/ui/js/Cloud.js +97 -0
  476. package/ui/js/CodeRuns.js +72 -0
  477. package/ui/js/Collide.js +212 -0
  478. package/ui/js/ColumnFit.js +28 -0
  479. package/ui/js/ColumnMenu.js +111 -0
  480. package/ui/js/Columns.js +298 -0
  481. package/ui/js/ColumnsCarry.js +103 -0
  482. package/ui/js/Compare.js +74 -0
  483. package/ui/js/Contrast.js +157 -0
  484. package/ui/js/ControlReader.js +42 -0
  485. package/ui/js/Convert.js +52 -0
  486. package/ui/js/CopyAs.js +52 -0
  487. package/ui/js/Crumbs.js +178 -0
  488. package/ui/js/Csv.js +231 -0
  489. package/ui/js/Density.js +44 -0
  490. package/ui/js/Devices.js +440 -0
  491. package/ui/js/DirSizes.js +180 -0
  492. package/ui/js/Drag.js +360 -0
  493. package/ui/js/DragOut.js +166 -0
  494. package/ui/js/DropDev.js +52 -0
  495. package/ui/js/Dropbox.js +41 -0
  496. package/ui/js/Eject.js +217 -0
  497. package/ui/js/Errors.js +188 -0
  498. package/ui/js/ExtThumbs.js +115 -0
  499. package/ui/js/Facts.js +402 -0
  500. package/ui/js/FigureDate.js +14 -0
  501. package/ui/js/Filter.js +285 -0
  502. package/ui/js/Find.js +46 -0
  503. package/ui/js/Flash.js +184 -0
  504. package/ui/js/FlashCard.js +79 -0
  505. package/ui/js/FlashEndings.js +125 -0
  506. package/ui/js/FlashPane.js +116 -0
  507. package/ui/js/FleaBin.js +12 -0
  508. package/ui/js/Focus.js +504 -0
  509. package/ui/js/FolderSorts.js +108 -0
  510. package/ui/js/FolderViews.js +44 -0
  511. package/ui/js/Format.js +314 -0
  512. package/ui/js/Fuzzy.js +141 -0
  513. package/ui/js/GlassTag.js +72 -0
  514. package/ui/js/Grid.js +33 -0
  515. package/ui/js/GridGeometry.js +90 -0
  516. package/ui/js/GridNames.js +153 -0
  517. package/ui/js/GvfsBridge.js +200 -0
  518. package/ui/js/HostClipboard.js +29 -0
  519. package/ui/js/Icons.js +218 -0
  520. package/ui/js/Input.js +50 -0
  521. package/ui/js/Jump.js +200 -0
  522. package/ui/js/KeyName.js +64 -0
  523. package/ui/js/Keymap.js +401 -0
  524. package/ui/js/Kinds.js +164 -0
  525. package/ui/js/LICENSES/ISC-lucide.txt +43 -0
  526. package/ui/js/LangMarkPaths.js +47 -0
  527. package/ui/js/LangMarks.js +120 -0
  528. package/ui/js/Lists.js +11 -0
  529. package/ui/js/LocalSend.js +39 -0
  530. package/ui/js/LockedMenu.js +63 -0
  531. package/ui/js/MakeDefault.js +186 -0
  532. package/ui/js/MarkBox.js +7 -0
  533. package/ui/js/Markdown.js +119 -0
  534. package/ui/js/MarkdownLists.js +86 -0
  535. package/ui/js/MarkdownMaths.js +58 -0
  536. package/ui/js/MarkdownPictures.js +32 -0
  537. package/ui/js/MarkdownPrepared.js +139 -0
  538. package/ui/js/MarkdownTableFit.js +34 -0
  539. package/ui/js/Marks.js +148 -0
  540. package/ui/js/Marquee.js +96 -0
  541. package/ui/js/Match.js +93 -0
  542. package/ui/js/Material.js +109 -0
  543. package/ui/js/MdBlocks.js +437 -0
  544. package/ui/js/MdBreak.js +71 -0
  545. package/ui/js/MdChunks.js +70 -0
  546. package/ui/js/MdContainer.js +137 -0
  547. package/ui/js/MdDocument.js +337 -0
  548. package/ui/js/MdEmph.js +97 -0
  549. package/ui/js/MdEntity.js +108 -0
  550. package/ui/js/MdEntityTable.js +223 -0
  551. package/ui/js/MdEscape.js +59 -0
  552. package/ui/js/MdFront.js +37 -0
  553. package/ui/js/MdHold.js +32 -0
  554. package/ui/js/MdHtml.js +307 -0
  555. package/ui/js/MdHtmlBlock.js +290 -0
  556. package/ui/js/MdHtmlHeading.js +53 -0
  557. package/ui/js/MdHtmlImage.js +179 -0
  558. package/ui/js/MdInline.js +154 -0
  559. package/ui/js/MdItems.js +212 -0
  560. package/ui/js/MdLeaf.js +309 -0
  561. package/ui/js/MdLink.js +196 -0
  562. package/ui/js/MdMath.js +67 -0
  563. package/ui/js/MdParagraphs.js +138 -0
  564. package/ui/js/MdRefs.js +232 -0
  565. package/ui/js/MdResolve.js +226 -0
  566. package/ui/js/MdRun.js +300 -0
  567. package/ui/js/MdUrl.js +226 -0
  568. package/ui/js/Menu.js +514 -0
  569. package/ui/js/MenuContext.js +85 -0
  570. package/ui/js/MenuFit.js +13 -0
  571. package/ui/js/MenuRefresh.js +74 -0
  572. package/ui/js/MenuWheel.js +35 -0
  573. package/ui/js/Messages.js +186 -0
  574. package/ui/js/Motion.js +16 -0
  575. package/ui/js/Mounts.js +320 -0
  576. package/ui/js/MouseNav.js +13 -0
  577. package/ui/js/Nav.js +329 -0
  578. package/ui/js/NetFs.js +26 -0
  579. package/ui/js/OpenWith.js +83 -0
  580. package/ui/js/Ops.js +585 -0
  581. package/ui/js/Palette.js +33 -0
  582. package/ui/js/PathBar.js +260 -0
  583. package/ui/js/Permissions.js +179 -0
  584. package/ui/js/Phones.js +112 -0
  585. package/ui/js/Picker.js +353 -0
  586. package/ui/js/PlaceMenu.js +96 -0
  587. package/ui/js/Places.js +265 -0
  588. package/ui/js/PreviewAsk.js +21 -0
  589. package/ui/js/PreviewKeys.js +155 -0
  590. package/ui/js/PreviewSettle.js +29 -0
  591. package/ui/js/PreviewSwap.js +101 -0
  592. package/ui/js/PropertyFacts.js +144 -0
  593. package/ui/js/Protocols.js +296 -0
  594. package/ui/js/QuickLookKinds.js +27 -0
  595. package/ui/js/QuickLookRect.js +24 -0
  596. package/ui/js/RailDrop.js +51 -0
  597. package/ui/js/RailKeys.js +87 -0
  598. package/ui/js/RailMenu.js +133 -0
  599. package/ui/js/Recent.js +135 -0
  600. package/ui/js/RecentMode.js +156 -0
  601. package/ui/js/Reload.js +60 -0
  602. package/ui/js/Renderer.js +9 -0
  603. package/ui/js/RunFile.js +143 -0
  604. package/ui/js/Scripts.js +28 -0
  605. package/ui/js/Scroll.js +304 -0
  606. package/ui/js/ScrollOff.js +69 -0
  607. package/ui/js/Search.js +478 -0
  608. package/ui/js/Selection.js +97 -0
  609. package/ui/js/Settings.js +476 -0
  610. package/ui/js/SettingsAbout.js +97 -0
  611. package/ui/js/SettingsShelf.js +52 -0
  612. package/ui/js/SheetKeys.js +42 -0
  613. package/ui/js/SheetQuery.js +281 -0
  614. package/ui/js/ShelfPile.js +27 -0
  615. package/ui/js/SlowClick.js +53 -0
  616. package/ui/js/SlowOp.js +6 -0
  617. package/ui/js/Sort.js +134 -0
  618. package/ui/js/Startup.js +63 -0
  619. package/ui/js/StateWords.js +17 -0
  620. package/ui/js/Status.js +238 -0
  621. package/ui/js/Swap.js +166 -0
  622. package/ui/js/TabMove.js +39 -0
  623. package/ui/js/Tabs.js +751 -0
  624. package/ui/js/Tags.js +134 -0
  625. package/ui/js/Taildrop.js +128 -0
  626. package/ui/js/Tap.js +180 -0
  627. package/ui/js/TextSize.js +107 -0
  628. package/ui/js/Thumbs.js +158 -0
  629. package/ui/js/Transfer.js +172 -0
  630. package/ui/js/Trash.js +84 -0
  631. package/ui/js/TrashDates.js +47 -0
  632. package/ui/js/TrashDrop.js +64 -0
  633. package/ui/js/UiState.js +438 -0
  634. package/ui/js/Unlock.js +152 -0
  635. package/ui/js/Update.js +130 -0
  636. package/ui/js/UserDirs.js +56 -0
  637. package/ui/qmldir +230 -0
package/ui/js/Ops.js ADDED
@@ -0,0 +1,585 @@
1
+ .pragma library
2
+
3
+ .import "Archive.js" as Archive
4
+ .import "Convert.js" as Convert
5
+ .import "CopyAs.js" as CopyAs
6
+ .import "Clipboard.js" as Clipboard
7
+ .import "ClipSelection.js" as ClipSelection
8
+ .import "Filter.js" as Filter
9
+ .import "Format.js" as Format
10
+ .import "Menu.js" as Menu
11
+ .import "Transfer.js" as Transfer
12
+ .import "Status.js" as Status
13
+ .import "Search.js" as Search
14
+
15
+ // Whole sentences with "%1" to "%3" for a name, a count or a place, filled by Format.fill so each reads as one.
16
+ var WORDS = {
17
+ duplicated: "Duplicated to %1",
18
+ convertedTo: "Converted to %1",
19
+ alreadyExists: "%1 already exists.",
20
+ shelfOne: "Added it to the shelf",
21
+ shelfMany: "Added %1 items to the shelf",
22
+ deleteOne: "This %1 is deleted from disk. This cannot be undone.",
23
+ deleteMany: "These %1 are deleted from disk. This cannot be undone.",
24
+ deleteAllOne: "%1, %2. This deletes it from disk. This cannot be undone.",
25
+ deleteAllMany: "%1, %2. This deletes them from disk. This cannot be undone.",
26
+ moved: "Moved %1",
27
+ movedOf: "Moved %1 of %2",
28
+ copied: "Copied %1",
29
+ copiedOf: "Copied %1 of %2",
30
+ cut: "Cut %1",
31
+ failedNote: " · %1 failed",
32
+ cancelledNote: " · cancelled",
33
+ skippedNote: " · %1 skipped",
34
+ moveFailed: "Move failed: %1 · %2",
35
+ copyFailed: "Copy failed: %1 · %2",
36
+ linked: "Linked %1",
37
+ selectedForRetry: "%1 selected for retry",
38
+ trashFailedOne: "That item could not be moved to Trash.",
39
+ trashFailedOneWhy: "That item could not be moved to Trash: %1.",
40
+ trashFailedMany: "%1 could not be moved to Trash.",
41
+ trashFailedManyWhy: "%1 could not be moved to Trash: %2.",
42
+ trashedAll: "Moved %1 to Trash",
43
+ trashedSome: "Moved %1 to Trash, %2 failed",
44
+ trashedSomeWhy: "Moved %1 to Trash, %2 failed: %3",
45
+ created: "Created %1",
46
+ taildropReason: "Taildrop · %1",
47
+ compressing: "Compressing %1 to .%2",
48
+ converting: "Converting %1 to .%2",
49
+ undoNothing: "Undid the last action"
50
+ }
51
+
52
+ // What a journal word undoes and redoes, as whole sentences: a word the backend uses for itself is never shown.
53
+ var UNDONE = {
54
+ copy: "Undid the copy", move: "Undid the move", rename: "Undid the rename", merge: "Undid the merge",
55
+ permissions: "Undid the permissions", duplicate: "Undid the duplicate", link: "Undid the link",
56
+ bulkrename: "Undid the bulk rename", newfile: "Removed the new file", paste: "Undid the paste", cut: "Undid the cut"
57
+ }
58
+ var REDONE = {
59
+ copy: "Redid the copy", move: "Redid the move", rename: "Redid the rename", merge: "Redid the merge",
60
+ permissions: "Redid the permissions", duplicate: "Redid the duplicate", link: "Redid the link",
61
+ bulkrename: "Redid the bulk rename", newfile: "Redid the new file", paste: "Redid the paste", cut: "Redid the cut"
62
+ }
63
+
64
+ function emptyClipboard() {
65
+ return Clipboard.empty()
66
+ }
67
+
68
+ // What the status bar and the card are tracking while a transfer runs; id is what a cancel names.
69
+ // done, bytes and total are the card's bar, the items finished and the one in flight; moved is ui/js/Transfer.js's own sum of the finished ones, which the wire never carries.
70
+ function emptyTransfer() {
71
+ return { id: 0, moving: false, n: 0, index: 0, name: "", running: false,
72
+ done: 0, bytes: 0, total: 0, moved: 0, writing: false, drive: "" }
73
+ }
74
+
75
+ // Any counted noun, so callers with their own word never hand-build the plural.
76
+ function pluralWord(n, one, many) {
77
+ return n === 1 ? one : many
78
+ }
79
+
80
+ // "item" or "items", the noun alone for a line that already carries its count.
81
+ function itemWord(n) {
82
+ return pluralWord(n, "item", "items")
83
+ }
84
+
85
+ // "1 item" or "1,204 items", so no caller builds a plural by hand.
86
+ function items(n) {
87
+ return Format.count(n) + " " + itemWord(n)
88
+ }
89
+
90
+ // The delete confirm names its scope ("Trash items" in the Trash view, "items" on a menu
91
+ // delete), singular for one and plural otherwise, so no caller keeps its own "items" constant.
92
+ function scopeSingle(scope) {
93
+ return String(scope).replace("items", "item")
94
+ }
95
+ function deleteScopeLine(scope, n) {
96
+ return n === 1 ? Format.fill(WORDS.deleteOne, scopeSingle(scope)) : Format.fill(WORDS.deleteMany, scope)
97
+ }
98
+
99
+ // The Empty Trash body, two whole sentences with the row's own count and formatted size; this module never formats a size itself.
100
+ function deleteAllLine(n, sizeText) {
101
+ return Format.fill(n === 1 ? WORDS.deleteAllOne : WORDS.deleteAllMany, items(n), sizeText)
102
+ }
103
+
104
+ // "Deleted 1 of 1 item" or "Restored 0 of 2 items": the Trash view and the menu delete status.
105
+ function doneOf(verb, done, total) {
106
+ return verb + " " + Format.count(done) + " of " + Format.count(total) + " " + itemWord(total)
107
+ }
108
+
109
+ // extract is the one verb not derived from moving: an extract drives this same card and its Cancel.
110
+ function started(id, moving, n, extract) {
111
+ return { id: id, moving: moving, n: n, index: 0, name: "", running: true, extract: extract === true,
112
+ done: 0, bytes: 0, total: 0, moved: 0, writing: false, drive: "" }
113
+ }
114
+
115
+ // The count comes from the card's headline so both surfaces name the same progress sample.
116
+ function progressLine(t) {
117
+ return t.name.length > 0 ? Transfer.head(t) + " · " + t.name : Transfer.head(t)
118
+ }
119
+
120
+ function transferDone(t, ok, failed, skipped, cancelled, durable, note) {
121
+ var partial = failed > 0 || skipped > 0 || cancelled
122
+ var line = partial
123
+ ? Format.fill(t.moving ? WORDS.movedOf : WORDS.copiedOf, Format.count(ok), Format.count(t.n))
124
+ : Format.fill(t.moving ? WORDS.moved : WORDS.copied, items(ok))
125
+ if (failed > 0) line += Format.fill(WORDS.failedNote, Format.count(failed))
126
+ if (skipped > 0) line += Format.fill(WORDS.skippedNote, Format.count(skipped))
127
+ if (cancelled) line += WORDS.cancelledNote
128
+ // The durable verdict's own note rides ahead of the undo hint, so the strip draws
129
+ // "Copied N items" with "<note> · z undoes" beside it. Only what landed is said:
130
+ // a verdict note with nothing copied stays unsaid.
131
+ if (ok > 0 && String(note || "").length > 0) line += Format.fill(Status.HINTS.note, note)
132
+ return ok > 0 ? Status.withUndo(line) : line
133
+ }
134
+
135
+ function transferFailure(t, name, error) {
136
+ return Format.fill(t.moving ? WORDS.moveFailed : WORDS.copyFailed, name, error)
137
+ }
138
+
139
+ // MenuAdditions040: Paste as links answers one line per request, and one
140
+ // journal entry, so one undo removes every link it created.
141
+ function linkedLine(ok, failed, skipped, note) {
142
+ var line = Format.fill(WORDS.linked, items(ok))
143
+ if (failed > 0) line += Format.fill(WORDS.failedNote, Format.count(failed))
144
+ if (skipped > 0) line += Format.fill(WORDS.skippedNote, Format.count(skipped))
145
+ // A stranded replace rides ahead of the undo hint, so the counts keep their shape.
146
+ if (String(note || "").length > 0) line += Format.fill(Status.HINTS.note, note)
147
+ return ok > 0 ? Status.withUndo(line) : line
148
+ }
149
+
150
+ // Only the identity-checked locate reply supplies these selected retry matches.
151
+ function retrySelectionLine(matches) {
152
+ if (!matches.length) return ""
153
+ return Format.fill(WORDS.selectedForRetry, matches.length === 1 ? leaf(matches[0].path) : items(matches.length))
154
+ }
155
+
156
+ // The canvas draws this one verbatim: "Moved 4 items to Trash · z undoes".
157
+ // A failure names its reason, so a hung mount or a denial reads as what happened rather than silence.
158
+ function trashed(ok, failed, reason) {
159
+ var why = String(reason || "")
160
+ if (ok === 0) {
161
+ if (failed === 1)
162
+ return why.length > 0 ? Format.fill(WORDS.trashFailedOneWhy, why) : WORDS.trashFailedOne
163
+ return why.length > 0 ? Format.fill(WORDS.trashFailedManyWhy, items(failed), why) : Format.fill(WORDS.trashFailedMany, items(failed))
164
+ }
165
+ if (failed === 0)
166
+ return Format.fill(WORDS.trashedAll, items(ok)) + Status.undoHint()
167
+ return (why.length > 0 ? Format.fill(WORDS.trashedSomeWhy, items(ok), Format.count(failed), why)
168
+ : Format.fill(WORDS.trashedSome, items(ok), Format.count(failed))) + Status.undoHint()
169
+ }
170
+
171
+ // The op an undone line carries is the backend's own word for the operation it reversed.
172
+ function undone(op) {
173
+ if (op === "trash")
174
+ return "Put it back from Trash."
175
+ if (op === "settags")
176
+ return "Restored the previous tags."
177
+ // src/backend/undo.rs reverses a mkdir with remove_dir, and "mkdir" is a wire word the operator
178
+ // never typed, so this one says what left the disk instead.
179
+ if (op === "mkdir")
180
+ return "Removed the new folder."
181
+ return UNDONE[op] !== undefined ? UNDONE[op] : WORDS.undoNothing
182
+ }
183
+
184
+ // The redo line for a journal word, before the undo hint the caller adds.
185
+ function redone(op) {
186
+ return REDONE[op] !== undefined ? REDONE[op] : "Redid the last action"
187
+ }
188
+
189
+ // The line for a new file or folder, which the status line draws beside its reversal hint when it has one.
190
+ function createdLine(path) {
191
+ return Format.fill(WORDS.created, leaf(path))
192
+ }
193
+
194
+ // The created folder's own line, carrying the same reversal hint the transfer and trash lines do.
195
+ function made(path) {
196
+ return Status.withUndo(createdLine(path))
197
+ }
198
+
199
+ function copied(n, moving) {
200
+ return Status.withPaste(Format.fill(moving ? WORDS.cut : WORDS.copied, items(n)))
201
+ }
202
+
203
+ // The three reasons a cursor is not a target, asked in the order ui/js/Nav.js asks them of Enter.
204
+ function sayNoTarget(pane) {
205
+ if (pane.cursorIndex < 0) return pane.message("There is nothing to act on.", false)
206
+ if (!pane.rowFor(pane.cursorIndex)) return pane.message("That row has not loaded yet.", false)
207
+ pane.message("That row is hidden by the filter.", false)
208
+ }
209
+
210
+ // The cursor is a target only while the filter draws it, the rule prune already applies to a selection.
211
+ function targetIndices(pane) {
212
+ var picked = pane.selectedIndices()
213
+ return picked.length > 0 ? picked : (Filter.cursorShown(pane) ? [pane.cursorIndex] : [])
214
+ }
215
+
216
+ // The marked indices in listing order, which makes the first the pair's file a and the second its file b.
217
+ function markedIndices(pane) {
218
+ return targetIndices(pane).slice().sort(function (a, b) { return a - b })
219
+ }
220
+
221
+ function markedRows(pane) {
222
+ return markedIndices(pane).map(function (index) { return pane.rowFor(index) })
223
+ }
224
+
225
+ // Each row's own type bits; a row carries no target's type, so a link stays a link and Menu.canCompare leaves it out.
226
+ function kinds(rowList) {
227
+ return rowList.map(function (row) { return row ? Number(row.p) || 0 : 0 })
228
+ }
229
+
230
+ // A ready matching snapshot wins over held modes that may predate an external replacement.
231
+ function menuKinds(pane) {
232
+ var picked = markedRows(pane)
233
+ var snapshot = pane.menuActions
234
+ return snapshot && snapshot.ready && snapshot.identity === pane.menuSelectionIdentity()
235
+ && snapshot.selectedKinds.length === picked.length ? snapshot.selectedKinds : kinds(picked)
236
+ }
237
+
238
+ // QML has no node:path; accept POSIX, drive-rooted and UNC paths. The backend
239
+ // still validates using its own platform's path.isAbsolute and opens the file.
240
+ function absoluteFilePath(path) {
241
+ return typeof path === "string" && (path.charAt(0) === "/"
242
+ || /^[A-Za-z]:[\\/]/.test(path) || /^\\\\[^\\]+\\[^\\]+/.test(path))
243
+ }
244
+
245
+ // The choice uses the menu's validated paths, reordered like the marked indices; unvalidated choices can only use held rows.
246
+ function open(pane, paths) {
247
+ var indices = markedIndices(pane)
248
+ var picked = indices.map(function (index) { return pane.rowFor(index) })
249
+ if (!Menu.canCompare(menuKinds(pane))) return
250
+ if (paths && paths.length === indices.length) {
251
+ var original = targetIndices(pane)
252
+ paths = indices.map(function (index) { return paths[original.indexOf(index)] })
253
+ } else {
254
+ paths = targetPaths(pane, indices)
255
+ }
256
+ if (paths.length !== 2 || paths.some(function (path) { return !absoluteFilePath(path) })) return
257
+ pane.quickLook().openCompare(paths[0], paths[1], picked[0] ? picked[0].i : "text-x-generic")
258
+ }
259
+
260
+ // Only rows inside the held window can be named as a path, so the caller sends indices instead and
261
+ // lets the backend resolve them; this is the one place that rule is written down on the client.
262
+ function targetPaths(pane, indices) {
263
+ var out = []
264
+ for (var i = 0; i < indices.length; i++) {
265
+ var row = pane.rowFor(indices[i])
266
+ if (row) {
267
+ out.push(pane.join(Search.baseOf(pane), row.n))
268
+ }
269
+ }
270
+ return out
271
+ }
272
+
273
+ // The name a progress line shows for an item the client may not hold a row for.
274
+ function leaf(path) {
275
+ var cut = String(path).lastIndexOf("/")
276
+ return cut >= 0 ? String(path).substring(cut + 1) : String(path)
277
+ }
278
+
279
+ // The single target the menu may name as a zip: the cursor or the one selection, "" otherwise.
280
+ function zipTarget(pane) {
281
+ // The probe fires on listing signals that also run before the first listing binds shown; with it unbound there is no target.
282
+ if (pane.shown === undefined) return ""
283
+ var indices = targetIndices(pane)
284
+ if (indices.length !== 1) return ""
285
+ var row = pane.rowFor(indices[0])
286
+ if (!row || row.d || Archive.imageKind(row.n) !== "zip") return ""
287
+ return pane.join(Search.baseOf(pane), row.n)
288
+ }
289
+
290
+ // A zip rewritten in place keeps its name, so the ask key carries its size and mtime too.
291
+ function zipSig(pane) {
292
+ var indices = targetIndices(pane)
293
+ if (indices.length !== 1) return ""
294
+ var row = pane.rowFor(indices[0])
295
+ return row ? String(row.s) + "|" + String(row.m) : ""
296
+ }
297
+
298
+ // Asks the backend once per target zip; a rewritten zip asks again, a member naming another file clears at once.
299
+ function checkZip(pane) {
300
+ if (!pane.backend) return
301
+ var target = zipTarget(pane)
302
+ var key = target ? target + "|" + zipSig(pane) : "|"
303
+ if (key === pane.flashZipAsked) return
304
+ pane.flashZipAsked = key
305
+ pane.flashZipMember = ""
306
+ if (target.length > 0) pane.backend.flashImage(target)
307
+ }
308
+
309
+ // Only the reply for the current target lands, and never into an open menu: the next opening draws it.
310
+ function noteZip(pane, message) {
311
+ var want = zipTarget(pane)
312
+ if (!want || !message || message.path !== want) return
313
+ var member = message.member || ""
314
+ pane.flashZipMember = message.kind === "zip" && Archive.isDiskImage(leaf(want), member) ? member : ""
315
+ }
316
+
317
+ // The pane's own delete verdict, which ui/PaneMenuActions.qml draws when a menu delete lands.
318
+ function deletedLine(message) {
319
+ var text = doneOf("Deleted", message.deleted, message.count)
320
+ if (message.failed) text += " · " + Format.count(message.failed) + " failed"
321
+ if (message.cancelled) text += " · cancelled"
322
+ return text
323
+ }
324
+
325
+ // Bulk rename answers one line for the whole batch, as whole-sentence templates.
326
+ var BULK_DONE_ONE = "Renamed 1 item%1"
327
+ var BULK_DONE_MANY = "Renamed %1 items%2"
328
+ function bulkDoneLine(ok) {
329
+ if (ok === 1) return BULK_DONE_ONE.replace("%1", Status.undoHint())
330
+ return BULK_DONE_MANY.replace("%1", Format.count(ok)).replace("%2", Status.undoHint())
331
+ }
332
+
333
+ // ---- the actions, each taking the pane the way Search.js's own do ----
334
+
335
+ // Duplicate acts on the cursor row alone: the operations design gives it one path, not a batch.
336
+ function duplicate(pane, menuId) {
337
+ var row = pane.rowFor(pane.cursorIndex)
338
+ if (!row) {
339
+ return
340
+ }
341
+ pane.backend.duplicate(pane.join(Search.baseOf(pane), row.n), menuId)
342
+ }
343
+
344
+ // No name field: the backend answers with the first free "New Folder", so there is no retry loop.
345
+ function newFolder(pane) {
346
+ pane.backend.mkdir(pane.path)
347
+ }
348
+
349
+ // A ready snapshot over the unchanged identity opens at once, one still in flight takes the F2 route, a moved identity is stale.
350
+ function menuRenameRoute(ready, identity, currentIdentity) {
351
+ if ((identity || "") === "" || identity !== currentIdentity) return "stale"
352
+ return ready === true ? "now" : "f2"
353
+ }
354
+
355
+ // No live editor sends the refusal to the status bar and closes the edit.
356
+ function refuseRename(pane, reason) {
357
+ if (pane.renamingIndex >= 0 && pane.renameEditor() !== null) {
358
+ pane.renameError = reason
359
+ return "editor"
360
+ }
361
+ pane.message(reason, true)
362
+ if (pane.renamingIndex >= 0)
363
+ pane.renamingIndex = -1
364
+ return "status"
365
+ }
366
+
367
+ // One inline editor in every view; a pointer rename passes context 0 so the list never moves under it.
368
+ function startRename(pane, menuId, index, context) {
369
+ if (pane.renamePending) return
370
+ // The row the request named, not wherever the cursor has reached by the time the reply lands.
371
+ var named = index !== undefined && index >= 0
372
+ var at = named ? index : pane.cursorIndex
373
+ var row = pane.rowFor(at)
374
+ if (!row) return
375
+ // A hidden row has no delegate to draw the editor in, so it would open on the filter clearing.
376
+ if (!named && !Filter.cursorShown(pane)) return sayNoTarget(pane)
377
+ pane.setCursor(at, context)
378
+ pane.renameError = ""
379
+ pane.renameSource = pane.join(Search.baseOf(pane), row.n)
380
+ pane.renameMenuId = menuId || 0
381
+ pane.renamingIndex = at
382
+ }
383
+
384
+ // Closing before acceptance loses the draft on a refused write; only success or Escape closes it.
385
+ function commitRename(pane, newName) {
386
+ if (pane.renamePending) return
387
+ var row = pane.rowFor(pane.renamingIndex)
388
+ if (!row) {
389
+ pane.renameError = "Item changed; reopen Rename."
390
+ return
391
+ }
392
+ if (!newName.length || newName === "." || newName === ".." || newName.indexOf("/") >= 0 || newName.indexOf("\u0000") >= 0) {
393
+ pane.renameError = "A name cannot be empty, . or .., or contain /."
394
+ return
395
+ }
396
+ pane.renameError = ""
397
+ var source = pane.renameSource || pane.join(Search.baseOf(pane), row.n)
398
+ // The request survives a hidden/reused editor so a late reply cannot finish another rename.
399
+ pane.renameRequest = {source: source, destination: source.substring(0, source.lastIndexOf("/") + 1) + newName, folder: pane.path}
400
+ pane.backend.rename(source, newName, pane.renameMenuId || 0)
401
+ }
402
+
403
+ // Indices, not paths: trash acts on the listing that is up right now, so the backend resolves them.
404
+ function trash(pane, menuId) {
405
+ if (pane.recentMode === "trash") { pane.trash.action("deletePermanently", menuId); return }
406
+ var idx = targetIndices(pane)
407
+ if (idx.length === 0) return sayNoTarget(pane)
408
+ // Sorted ascending, so this is the block's own first row and not wherever the cursor sat in it.
409
+ pane.trashedFirst = idx[0]
410
+ pane.backend.trash(idx, menuId)
411
+ }
412
+
413
+ // One line while a paths round trip is out; every asker refuses through it, so none steals another's reply.
414
+ function pathsBusy(pane) {
415
+ pane.message("Still resolving the last selection; try again.", false)
416
+ }
417
+
418
+ function refuseWhileBusy(pane) {
419
+ if (!(pane.pathsPending || pane.clipPending !== null)) return false
420
+ pathsBusy(pane)
421
+ return true
422
+ }
423
+
424
+ // Resolve absolute paths with each request's own verb, deferring the latest overlapping selection.
425
+ function clip(pane, moving, paths) {
426
+ if (!paths && pane.pathsPending) { pathsBusy(pane); return }
427
+ var indices = paths ? [] : targetIndices(pane)
428
+ if (!paths && indices.length === 0) return sayNoTarget(pane)
429
+ ClipSelection.take(pane, moving, paths, indices, copied)
430
+ }
431
+
432
+ function clipFailed(pane) {
433
+ ClipSelection.failed(pane)
434
+ }
435
+
436
+ // MenuAdditions040: Copy as names absolute paths, because like the clipboard
437
+ // a copy happens in a different directory from the listing it was started
438
+ // from. With paths the text goes out at once; without, the backend resolves
439
+ // the indices while it still can, the same rule clip follows.
440
+ function copyAs(pane, kind, paths) {
441
+ if (paths && paths.length > 0) {
442
+ pane.opener.copyText(CopyAs.lines(paths, kind))
443
+ return
444
+ }
445
+ if (refuseWhileBusy(pane)) return
446
+ var idx = targetIndices(pane)
447
+ if (idx.length === 0) return sayNoTarget(pane)
448
+ pane.pathsPending = { kind: "copyAs", format: kind }
449
+ pane.backend.askPaths(idx)
450
+ }
451
+
452
+ // Two kinds of success, said apart: an extract whose archive index could not be read was published
453
+ // without being checked against it, and the operator is the one who decides whether to care.
454
+ function archiveDoneLine(verified) {
455
+ return verified ? "Archive written."
456
+ : "Extracted. The archive index could not be read, so this was not verified."
457
+ }
458
+
459
+ function paste(pane, forceMove) { Clipboard.paste(pane, "", forceMove === true) }
460
+ function pasteLink(pane, kind) { Clipboard.paste(pane, kind, false) }
461
+
462
+ function undo(pane) {
463
+ pane.backend.undo()
464
+ }
465
+
466
+ // Sending the cursor row alone rather than the whole selection is Task 9's own scope; row.d is
467
+ // defensive, because the menu already empties its peer list for a directory cursor.
468
+ function sendTaildrop(pane, taildrop, peerId, path) {
469
+ if (typeof path !== "string" || path.charAt(0) !== "/") {
470
+ pane.message("That menu is out of date. Reopen it.", true)
471
+ return
472
+ }
473
+ var row = pane.rowFor(pane.cursorIndex)
474
+ if (!row || row.d) {
475
+ return
476
+ }
477
+ if (taildrop.send(peerId, [path]) === false) {
478
+ // The reason is one shared token: the menu, both front ends and the probes all read it, and
479
+ // the TUI draws it as "taildrop · signed out". The bar names the subject the same way rather
480
+ // than printing a bare fragment beside errors that are sentences.
481
+ pane.message(taildrop.reason ? Format.fill(WORDS.taildropReason, taildrop.reason)
482
+ : "That Taildrop peer is no longer available.", true)
483
+ return
484
+ }
485
+ // The dispatch is the only result Flea itself ever knows; success or failure is the OEM script's
486
+ // own desktop notification, see the operations design section 4.1.
487
+ pane.message("Sending " + leaf(path) + " to " + taildrop.labelFor(peerId) + ".", false)
488
+ }
489
+
490
+ // ---- archives and convert, whose menu rows are only offered when a tool for them exists ----
491
+
492
+ // One row compresses under its own name, several under the directory holding them; the name is free
493
+ // before the request goes out, and the backend refuses a destination that appeared meanwhile anyway.
494
+ function compress(pane, format) {
495
+ var idx = targetIndices(pane)
496
+ if (idx.length === 0) return sayNoTarget(pane)
497
+ if (refuseWhileBusy(pane)) return
498
+ // The archive request names paths and has no rows form, so the indices are resolved first and the
499
+ // request is built in compressResolved. Naming them here would drop every row outside the window.
500
+ pane.pathsPending = { kind: "compress", format: format }
501
+ pane.backend.askPaths(idx)
502
+ }
503
+
504
+ // The answer to the askPaths above, and the only place an archive request is built.
505
+ function compressResolved(pane, list, format, menuId) {
506
+ if (list.length === 0) {
507
+ return
508
+ }
509
+ var names = []
510
+ for (var i = 0; i < list.length; i++) {
511
+ names.push(leaf(list[i]))
512
+ }
513
+ var stem = Archive.archiveStem(names, leaf(pane.path))
514
+ pane.backend.compress(list, pane.join(Search.baseOf(pane), stem + "." + format), format, menuId)
515
+ pane.sticky(Format.fill(WORDS.compressing, items(list.length), format))
516
+ }
517
+
518
+ // One paths reply, two possible askers. The clipboard is the default because it is what every reply
519
+ // meant before compress joined, so a reply nobody claimed still lands where it always did.
520
+ function pathsResolved(pane, list) {
521
+ var pending = pane.pathsPending
522
+ pane.pathsPending = null
523
+ // A pending carrying its own deliver answers itself, the drag's pattern the password flow reuses.
524
+ if (pending && typeof pending.deliver === "function") { pending.deliver(list, pending); return }
525
+ if (pending && pending.kind === "compress") {
526
+ compressResolved(pane, list, pending.format)
527
+ return
528
+ }
529
+ // MenuAdditions040: every Copy as variant covers the whole selection, one
530
+ // path per line, as plain text; nothing reaches the file clipboard.
531
+ if (pending && pending.kind === "copyAs") {
532
+ if (list.length > 0)
533
+ pane.opener.copyText(CopyAs.lines(list, pending.format))
534
+ return
535
+ }
536
+ // MenuAdditions040: Permissions takes the whole selection, so the dialog
537
+ // opens over every resolved path rather than the cursor row alone.
538
+ if (pending && pending.kind === "permissions") {
539
+ pane.openPermissionsWith(list)
540
+ return
541
+ }
542
+ // Bulk rename takes the whole selection for its card.
543
+ if (pending && pending.kind === "bulkrename") {
544
+ pane.openBulkRenameWith(list)
545
+ return
546
+ }
547
+ ClipSelection.resolved(pane, list, copied)
548
+ }
549
+
550
+ // Extract unpacks beside the archive; its sticky and card come off the wire's own start line.
551
+ function extract(pane, menuId) {
552
+ var row = pane.rowFor(pane.cursorIndex)
553
+ if (!row) {
554
+ return
555
+ }
556
+ pane.backend.extract(pane.join(Search.baseOf(pane), row.n), pane.join(Search.baseOf(pane), Archive.extractDir(row.n)), menuId)
557
+ }
558
+
559
+ // A directory has nothing to convert, so the popup never opens on one.
560
+ function openConvert(pane, menuId) {
561
+ var row = pane.rowFor(pane.cursorIndex)
562
+ if (row && !row.d) {
563
+ pane.convertSource = {path: pane.join(Search.baseOf(pane), row.n), name: leaf(row.n), menuId: menuId || 0}
564
+ pane.convertRequested(row.n)
565
+ }
566
+ }
567
+
568
+ function convert(pane, source, format, strip, requestId) {
569
+ pane.convertSource = Object.assign({}, source, {requestId: requestId})
570
+ pane.sticky(Format.fill(WORDS.converting, source.name, format))
571
+ pane.backend.convertImage(source.path, Convert.destination(source, format), strip, source.menuId, requestId, false)
572
+ }
573
+
574
+ // Move to Dropbox is the transfer request with a destination filled in, which is the concrete case
575
+ // where "does this need to exist at all" answers no: no new wire, no new Rust.
576
+ function moveToDropbox(pane, dropboxPath, menuId) {
577
+ var idx = targetIndices(pane)
578
+ if (dropboxPath.length === 0) return
579
+ if (idx.length === 0) return sayNoTarget(pane)
580
+ // Deliberately does not touch pane.clipboard: this is its own move, and clobbering what the
581
+ // operator cut or copied earlier would lose it with no way back.
582
+ // Rows, not paths: a selection reaches past the window the client holds, and targetPaths drops
583
+ // every index outside it in silence, so a wide move relocated a few files and abandoned the rest.
584
+ pane.asks().ask({ c: "transfer", op: "move", rows: idx, dest: dropboxPath, menuId: menuId || 0 })
585
+ }
@@ -0,0 +1,33 @@
1
+ // The Omarchy theme palette in colors.toml, parsed and queried. Pure, with no QML imports, so
2
+ // tests/js/palette.js can run it under qml6 with no window.
3
+
4
+ // Sample input: cyan = "#27a6a2" # the ANSI ring
5
+ function parse(body) {
6
+ var found = {};
7
+ var lines = String(body || "").split("\n");
8
+ for (var i = 0; i < lines.length; i++) {
9
+ var kv = lines[i].match(/^\s*([A-Za-z0-9_-]+)\s*=\s*["']?(#[0-9A-Fa-f]{6})/);
10
+ if (kv)
11
+ found[kv[1]] = kv[2];
12
+ }
13
+ return found;
14
+ }
15
+
16
+ // ThemeRoles.html's surface ladder: the chrome plane, then background as the neutral fallback when
17
+ // it is absent, then selection for the alacritty-derived file that emits neither ladder key at all.
18
+ var SURFACE_KEYS = ["dark_background", "background", "selection"];
19
+
20
+ // The first key the theme actually set wins, and a role no theme models keeps Flea's own colour.
21
+ function pick(found, keys, fallback) {
22
+ for (var i = 0; i < keys.length; i++) {
23
+ if (found[keys[i]])
24
+ return found[keys[i]];
25
+ }
26
+ return fallback;
27
+ }
28
+
29
+ // A theme need not set every role and pick() already falls back per role, so the only question a
30
+ // readiness flag can answer honestly is whether the file yielded any colour at all.
31
+ function isPalette(found) {
32
+ return Object.keys(found).length > 0;
33
+ }